fraxture fraxture - 1 month ago 10
Javascript Question

Add on load event for img elements now and in future?

I want to add a load event on an image that would affect that image even when that image is added to the document after the page's initial load. For a click event I would do someting like this:

$(document).on('click', '.elem', function(e) {
// do stuff
});


When I try something similar with the
load
event, however, it does not to work. This is what I have tried:

$(document).on('load', '.image', function() {
// do stuff
});


This event is simply never triggered. Does anyone know what I may be doing wrong, or how to achieve this?

Answer

By their nature, delegated handlers only work for events that bubble. Not all do, and load is one of the ones that doesn't. The jQuery documentation even highlights this:

In all browsers, the load, scroll, and error events (e.g., on an element) do not bubble.

You'll have to add the load handlers to the images when you add them.


What I mean by "delegated handlers only work for events that bubble":

Events that bubble work like this (in the "bubbling" phase, which is the phase you normally work with): The event is fired on the element where it originates, and then on that element's parent, then that element's parent, etc. until it gets to the document element (html). This diagram from the DOM3 events spec may help make this clearer:

Graphical representation of an event dispatched in a DOM tree using the DOM event flow

Using a delegated handler (the kind you're using in your question) relies on bubbling. Consider this HTML:

<div id="container">
    <div class="content">xxxx</div>
    <div class="content">xxxx</div>
    <div class="content">xxxx</div>
</div>

If you do $("#container").on("click", ".content", ...) you're not hooking the event on the "content" divs, even though jQuery will make it seem a bit like you are. You're hooking the event on the "container" div. When the event bubbles down to the container div, jQuery looks at where it started and sees whether it passed through any "content" divs during its bubbling. If it did, jQuery calls your handler as though (mostly) you'd hooked the event on the "content" div. That's why delegated handlers work when you add elements later; the event isn't hooked on the element, but on the container.

So that's why it won't work for load: load doesn't bubble, so even though it fires on the img elements you add, it doesn't bubble to the parent and so on, and so you never see it. To see it, you have to hook it on the specific element, not an ancestor of it.

Comments