Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript/jQuery event listener on image load IE issues

Tags:

I am looking for a way to implement this for as many browsers as possible:

var image = new Image();
image.addEventListener("load", function() {
    alert("loaded");
}, false);
image.src = "image_url.jpg";

This didn't work in IE so I googled and found out that IE's lower than 9 do not support .addEventListener(). I know there is a jQuery equivalent called .bind() but that doesn't work on an Image(). What do I have to change for this to work in IE too?

like image 268
matteok Avatar asked Sep 16 '11 09:09

matteok


3 Answers

IE supports attachEvent instead.

image.attachEvent("onload", function() {
    // ...
});

With jQuery, you can just write

$(image).load(function() {
    // ...
});

When it comes to events, if you have the possibility of using jQuery I would suggest using it because it will take care of browser compatibility. Your code will work on all major browser and you don't have to worry about that.

Note also that in order to the load event being fired in IE, you need to make sure the image won't be loaded from the cache, otherwise IE won't fire the load event.

To do this, you can append a dummy variable at the end of the url of your image, like this

image.setAttribute( 'src', image.getAttribute('src') + '?v=' + Math.random() );

Some known issues using the jQuery load method are

Caveats of the load event when used with images

A common challenge developers attempt to solve using the .load() shortcut is to execute a function when an image (or collection of images) have completely loaded. There are several known caveats with this that should be noted. These are:

  • It doesn't work consistently nor reliably cross-browser
  • It doesn't fire correctly in WebKit if the image src is set to the same src as before
  • It doesn't correctly bubble up the DOM tree
  • Can cease to fire for images that already live in the browser's cache

See the jQuery docs for more info.

like image 155
Jose Faeti Avatar answered Sep 30 '22 04:09

Jose Faeti


You have to use .attachEvent() rather than .addEventListener().

if (image.addEventListener) {
  image.addEventListener('load', function() {
       /* do stuff */ 
  });
} else {
  // it's IE!
  image.attachEvent('onload', function() {
    /* do stuff */
  });
}
like image 36
Alex Avatar answered Sep 30 '22 02:09

Alex


You can use attachEvent, but I would rather prefer you would add the addEventListener listener yourself. Here is the code on that MDN link for adding the event listener:

if (!Element.prototype.addEventListener) {
    var oListeners = {};
    function runListeners(oEvent) {
        if (!oEvent) { oEvent = window.event; }
        for (var iLstId = 0, iElId = 0, oEvtListeners = oListeners[oEvent.type]; iElId < oEvtListeners.aEls.length; iElId++) {
            if (oEvtListeners.aEls[iElId] === this) {
                for (iLstId; iLstId < oEvtListeners.aEvts[iElId].length; iLstId++) { oEvtListeners.aEvts[iElId][iLstId].call(this, oEvent); }
                break;
            }
        }
    }
    Element.prototype.addEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) {
        if (oListeners.hasOwnProperty(sEventType)) {
            var oEvtListeners = oListeners[sEventType];
            for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) {
                if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; }
            }
            if (nElIdx === -1) {
                oEvtListeners.aEls.push(this);
                oEvtListeners.aEvts.push([fListener]);
                this["on" + sEventType] = runListeners;
            } else {
                var aElListeners = oEvtListeners.aEvts[nElIdx];
                if (this["on" + sEventType] !== runListeners) {
                    aElListeners.splice(0);
                    this["on" + sEventType] = runListeners;
                }
                for (var iLstId = 0; iLstId < aElListeners.length; iLstId++) {
                    if (aElListeners[iLstId] === fListener) { return; }
                }           
                aElListeners.push(fListener);
            }
        } else {
            oListeners[sEventType] = { aEls: [this], aEvts: [ [fListener] ] };
            this["on" + sEventType] = runListeners;
        }
    };
    Element.prototype.removeEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) {
        if (!oListeners.hasOwnProperty(sEventType)) { return; }
        var oEvtListeners = oListeners[sEventType];
        for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) {
            if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; }
        }
        if (nElIdx === -1) { return; }
        for (var iLstId = 0, aElListeners = oEvtListeners.aEvts[nElIdx]; iLstId < aElListeners.length; iLstId++) {
            if (aElListeners[iLstId] === fListener) { aElListeners.splice(iLstId, 1); }
        }
    };
}
like image 41
Shef Avatar answered Sep 30 '22 04:09

Shef