Gari BN
Gari BN

Reputation: 1685

javascript's document.getElementById returns null, but works from the console

I tried to access and change properties of some element, from the onerror event of some image. But... when I load the page, I get Uncaught TypeError: Cannot call method ... of null. I know that usually, this happens because the element hasn't loaded yet.

I added delay of 10 seconds, using setTimeout. Now, I loaded the code, and successfully reached the element via the console (in both Chrome and Firefox). I stil got the TypeError message.

Note that the code from the 'onerror', works fine from the console.

I tried to do what I wanted in another way: I tried to redefine a global function from the "onerror" property of the image. But again: the global function didn't change. It isn't a matter of time, and the code worked perfectly from the console (the same onerror code, redefined the global function successfully from the console in both Chrome and FF).

I will bring here some examples of tries I did (I rewrited them quickly, hopefully without any typo):

<img src='' onerror='setTimeout(function(){document.getElementById(someElementString).addEventListener(clickString,function(){alert(1234);});},6000);' height=100 width=100 />

<img src='' onerror='function(){setTimeout(function(){document.getElementById(someElementString).addEventListener(clickString,function(){alert(1234);});},6000);};' height=100 width=100 />

<img src='' onerror='f = function(){setTimeout(function(){document.getElementById(someElementString).addEventListener(clickString,function(){alert(1234);});},6000);}; f();' height=100 width=100 />

<img src='' onerror='setTimeout(function(){window.globalFunction = function(e){alert(656565);};},6000);' height=
200 width=100 />

I also wrapped the onerror as a function but without success.

If I replace the onerror code with a simple alert, it works; And again: it works also from the console, even before the code onerror code runs.

What can be the reason for this? Any help will be appreciated!

Upvotes: 0

Views: 2195

Answers (2)

enhzflep
enhzflep

Reputation: 13099

Okay, I see you've updated your question. While there was a problem with the quotes as presented, this is as you've mentioned, not the problem.

The problem comes from a number of things that I can see.

1) You've stuffed so much code into 1 line you seem to have lost track of all the arguments for each of the functions. You've forgotten the 3rd parameter for addEventListener, for instance. 2) Specifying the src attribute for the image, yet leaving it empty appears to cause an error. Setting it it an invalid filename later in js will cause the error function to fire twice - once on page load, the second when the new invalid filename is applied.

Here's an abbreviated solution that does what I think you want.

UPDATED CODE:

notice the difference in behaviour between img 4 and 5. You can click 5 immediately to change its border. img4 on the other hand needs you to wait a 3 seconds first.

<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}

window.addEventListener('load', mInit, false);

function initImage(idStr, imgSrc, errorCallback, successCallback)
{
    byId(idStr).addEventListener('error', errorCallback, false);
    byId(idStr).addEventListener('load', successCallback, false);
    byId(idStr).src = imgSrc;
}

function mInit()
{
    initImage('img1', 'doesntExist.png', errorFunc, successFunc);
    initImage('img2', 'arduino.png', errorFunc, successFunc);
}

function errorFunc()
{
    setTimeout(mFunc,3000);
    var mElement = this;
    function mFunc()
    {
        mElement.setAttribute('style','border-color: red');
        mElement.setAttribute('title', 'Error - image not found: "' + mElement.src + '"');
        mElement.addEventListener('click', function(){alert('The image didn\'t load!\nClicking aint gonna make it so, either!');}, false);
    }
}

function successFunc()
{
    setTimeout(mFunc,3000);
    var mElement = this;
    function mFunc()
    {
        mElement.setAttribute('style','border-color: green');
        mElement.setAttribute('title', '"' + mElement.src + '"');
        mElement.addEventListener('click', function(){ alert("succeeded"); }, false);
    }
}

</script>
<style>
img 
{
    border: solid 4px transparent;
}
</style>
</head>
<body>
    <img id='img1' height=100 width=100 />
    <img id='img2' height=100 width=100 />
    <img id='img3' src='doesntExistEither.png' height=100 width=100 onerror='func2();' />
    <img id='img4' src='doesntExistEither.png' height=100 width=100 onerror='setTimeout( function(){byId("img4").addEventListener("click", function(){byId("img4").setAttribute("style","border-color: purple;");}, false);}, 3000);' />
    <img id='img5' src='doesntExistEither.png' height=100 width=100 onerror='byId("img5").addEventListener("click", function(){byId("img5").setAttribute("style","border-color: purple;");}, false);' />
</body>
</html>

Upvotes: 0

Jitesh Tukadiya
Jitesh Tukadiya

Reputation: 1339

Looks like you have put your javascript code in <head>

If you did so, then you have put all your code to window.onload event, So your code should be like below,

window.onload = function() {
    var element = document.getElementById('element');
    element.addEventListener('click',function(){
        alert('You have clicked the element');
    });
};

Upvotes: 1

Related Questions