3

So, this might be a very simple question but I'll ask anyway. And this obviously is just to clarify in my mind how these two statements work.

Scenario I am pulling via an Ajax call some JSON that I then interpolate into html which has some selectors. Like this:

$.each(r, function(k,v){
  str+='location: <div class=\'loc-to-select\' data-location-id=\'' + v.id +  '\'>';
  str+= v.name + '</div>';
});
$('#event-search-locations').html(str);

basically writing out:

<div class='loc-to-select' data-location-id='2'>Joe's</div>

I have these two pieces of jQuery:

// doesn't work
$('.loc-to-select').on('click',function(){
  alert('here you go');
});

// does work
$(document).on('click','.loc-to-select', function(){
  alert('here you go');
});

All of this clearly takes place after jQuery's $(document).ready has finished firing. It is my understanding that this is the main functionality that jQuery provides. I am familiar with the concept of event bubbling. I have also read the doc's here http://api.jquery.com/on/ where it discusses delegated events. I am not understaning internally how jQuery is doing this via descendent elements. Some of this discusses how it handles from a user space pov: Direct vs. Delegated - jQuery .on()

Also, it seems that the descendent element technique is preferred for performance reasons. Does the descendent element model basically say, if we get something new added to the DOM, check to see if it complies to the 'delegated element' model whereas direct events bypass this?

On a more simple level, does the jQuery 'runtime' essentially monitor the DOM for changes and then checks or does it check earlier in for example the html function (essentially parsing though html for items it knows about)?

Finally, why don't they just make the second syntax (the delegated syntax) the default? It would seem to provide greater specificity and better performance (as mentioned in the docs)

thx

Community
  • 1
  • 1
timpone
  • 19,235
  • 36
  • 121
  • 211

1 Answers1

3

I'm not 100% certain what you want to know, since the question you linked to ( Direct vs. Delegated - jQuery .on() ) seems to hold the answer to what you are asking for.

Here is again an explanation of the differences:

$('.loc-to-select').on('click',function(){
  alert('here you go');
});

will search for all .loc-to-select elements that exist at that moment and bind the event handler to each of these elements.

The equivalent using the DOM API would be:

var elements = document.getElementsByClassName('loc-to-select');
for(var i = 0, l = elements.length; i < l; i++) {
    elements[i].onclick = handler;
}

Now consider

$(document).on('click','.loc-to-select', function(){
  alert('here you go');
});

only binds one event handler to document. It inspects every click event and test whether it originated from or within an element with class loc-to-select.

Again, the DOM equivalent (simplified):

document.body.onclick = function(event) {
    if(event.target.className === 'loc-to-select') {
         handler.call(this);
    }
}

jQuery does not monitor the DOM for changes, it simply uses the fact that events are bubbling up the tree.

Finally, why don't they just make the second syntax (the delegated syntax) the default? It would seem to provide greater specificity and better performance (as mentioned in the docs)

Let's recap again what happens in event delegation: A single event handler is bound to one element to handle multiple (similar) elements. That means you need only search and touch x elements to handle y elements, where x << y, i.e. setting it up is faster.

It comes with a tradeoff though: Since the event is first traversing up the tree and the origin has to be evaluated, whether it matches or not, processing an event when it occurs takes more time.
Think about what happens if you would use event delegation for all click events on a page and you bind the handlers to document. You'd end up with n event handlers bound to document, and each of them would be executed on a single click. But out of those n, only one needs to be executed. This does not seem to be very performant.

With direct event handling, setup is slower, since you have to find all elements and bind the event handler to each of them. If there are not many elements, that's not a problem, but if there are many it can be. Apparently browsers perform worse the more event handlers are bound, but that might change or already has.

It's a tradeoff between having many event handlers bound to many elements executed fewer times and few event handlers bound to few elements executed many times.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • thx ... (and thx for reading the whole question and your edit) so that makes a lot more sense. It would seem like the delegate model is more powerful and faster - do you know why it just isn't the default - again sorry for my lack of understanding. – timpone Aug 15 '12 at 16:04
  • thx, this is much clearer! (but i'll prob be asking another question about what is meant by bubbling up) – timpone Aug 15 '12 at 16:12
  • @timpone: See my latest edits. I hope that clarifies it. `some useless code`. @yoshi: It seems that browsers will perform worse the more event handlers are bound (or at least it was like this). Also, while event delegation is a bit more expensive at runtime, direct event handlers are more expensive at setup time, since you to search and touch for every matching element. I don't think there is will be any noticeable difference in "normal" scaled applications though. – Felix Kling Aug 15 '12 at 16:17
  • @timpone: I thought you said you are familiar with event bubbling. Anyways, this is a good explanation: http://www.quirksmode.org/js/events_order.html – Felix Kling Aug 15 '12 at 16:29