26

Can I use:

window.addEventListner();

in some way.

All my images have a display = 'none'.

Once the image has loaded,

I want to set display = 'inline'

This way I can normalize what is displayed while the image is being downloaded.

In this case, I can not pre-load my images.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129

6 Answers6

71

Use a capturing event listener on some parent DOM element like document, document.body or some other wrapper of images you need to observe. You can do this in the third argument of element's addEventListener method:

document.body.addEventListener(
    'load',
    function(event){
        var tgt = event.target;
        if( tgt.tagName == 'IMG'){
            tgt.style.display = 'inline';
        }
    },
    true // <-- useCapture (or options object)
);

The third argument can be either boolean (true) or newly added "options" object with a capture boolean property ({ capture: true }).

Using this approach, you don't have to (re-)attach event handlers while iterating through document.images live HTMLCollection or some (re-)queried static NodeList.

This is generally known as "event delegation pattern".

It will also work for dynamically inserted images.

And same applies to image's error loading events.

addEventListener at MDN

myf
  • 9,874
  • 2
  • 37
  • 49
  • 1
    I never thought to try this for event delegation of image load events. Quite brilliant! And the reason it can't be window: "For legacy reasons, load events for resources inside the document (e.g., images) do not include the Window in the propagation path in HTML implementations" – Adria Jan 19 '15 at 20:26
16

The load/onload event does not bubble (reference, reference), so what you're asking for is not possible. You'll have to attach an event handler to each image node, or intercept the event during the capture phase, as suggested in other answers.

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
  • Not even "abnormally". One more ref: http://www.w3.org/TR/DOM-Level-3-Events/#event-type-load – bfavaretto Feb 21 '13 at 14:45
  • I would have thought this is what event bubbling was for. But I guess not, I've updated my question. –  Feb 21 '13 at 20:40
  • Many other events bubble, like `click`, and that sure is useful. But the fact that `load` doesn't bubble doesn't mean you can't preload your images. Why not create a single function to handle `load` for all images? – bfavaretto Feb 21 '13 at 20:55
  • Something like that (although his pure js example won't work, you can't do `imgs.onload` like that, you have to loop) – bfavaretto Feb 21 '13 at 21:17
2
Array.prototype.forEach.call(document.querySelectorAll('img'), function (elem) {
    elem.addEventListener('load', function () {
        this.style.display = 'inline';
    });
    if (elem.complete) {
        elem.style.display = 'inline';
    }
});

The "load" event will not trigger if the image is incidentally loaded already; thus, we check whether complete is already set.

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
1

You can use the Image.onload event handler but there's no bubbling involved.

var i = new Image;
i.onload = function() {
  this.style.display = 'block';
}
marekful
  • 14,986
  • 6
  • 37
  • 59
0

Since the load event does not bubble, you can lauch your own bubbling event. An example with jQuery:

<img src="dog.jpg" onload="$(this).trigger('image-loaded')" />
Edwin
  • 733
  • 8
  • 20
-1
$('img').on('load', function() {
    $(this).show()
})

Without libraries:

window.onload = function() {
   var imgs = document.querySelectorAll('img')
   imgs.onload = function() {
      this.style.display = 'inline';
   }
}
Naftali
  • 144,921
  • 39
  • 244
  • 303