5

What is the difference between the following?

$(document).on("scroll",".wrapper1", function(){
   $(".wrapper2")
    .scrollLeft($(".wrapper1").scrollLeft());
});  

$('.wrapper1').on("scroll", function(){
        $(".wrapper2")
            .scrollLeft($(".wrapper1").scrollLeft());
});

When to should each functions be used exactly?

Ash Burlaczenko
  • 24,778
  • 15
  • 68
  • 99
PSR
  • 39,804
  • 41
  • 111
  • 151
  • So following on from your [other question](http://stackoverflow.com/questions/16057384/scroll-in-not-working-in-jquery-for-dynamic-elements)... – andyb Apr 17 '13 at 10:58
  • I have updated my answer to correct the statement about `scroll` event not bubbling – andyb Apr 17 '13 at 12:29

3 Answers3

5

The difference between these two are

$('.wrapper1').on("scroll", ....) binds the scroll event to only those elements which are present at the time of execution of this statement, ie if any new element with class wrapper1 is added dynamically after this statement is executed then the event handler will not get executed for those elements.

$(document).on("scroll",".wrapper1", ...) on the other hand will register one event handler to the document object and will make use of event bubbling to invoke the handler whenever scrolling happens within an element with class `wrapper``, so it will support dynamic addition of elements.

So when to prefer a method

you can prefer first method if you have only a limited number of elements and they are not dynamically added

Prefer the second method if you have lot of elements or these elements are added dynamically.

Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
  • @if the elements are not adding dynamically why i need to use .on – PSR Apr 17 '13 at 11:12
  • 1
    One reason for me, is if there are lot of elements, there will be lot of event handlers registered in the dom if you are not using a delegated event model. If you use event delefation there wil be only one event handler registered. I haven't done any performance testing to check the effect of both cases – Arun P Johny Apr 17 '13 at 11:15
1

The effect will be the same, but the way in which the event handler is having the event delivered is slightly different.

You are using .on() in each case, but a selector is not being used in the second version. The event is delegated in the first instance and is directly bound in the second. The .on() documentation states:

For direct events,

handler is called every time an event occurs on the selected elements, whether it occurs directly on the element or bubbles from a descendant (inner) element

For delegated events,

The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector

What happens is when an event is detected by the browser it bubbles up the DOM. At each element on the way up, jQuery will call the event handlers that have been attached. In the first version the event propagates all the way up to the document before jQuery checks if the event originated in a class="wrapper1" element. The second version, the event would stop bubbling earlier if the event was on a class="wrapper1" element.

The other difference is that the first version will still be able to bind the event handler if .wrapper1 does not exist when the page has finished loading, i.e. if the element is dynamically added the second version will not work. When the page loads and the jQuery executed $('.wrapper1') might not exist.

If .wrapper1 element(s) are not dynamic then you will probably find a (negligible) performance benefit of using the second version.

All that aside, the scroll event does not bubble and cannot be delegated. However, they can be delegated Again from the .on() documentation:

In all browsers, the load, scroll, and error events (e.g., on an element) do not bubble. In Internet Explorer 8 and lower, the paste and reset events do not bubble. Such events are not supported for use with delegation, but they can be used when the event handler is directly attached to the element generating the event.

So the only version that would work is the second one! See demo in the DevTools Console the document scroll output never appears.

andyb
  • 43,435
  • 12
  • 121
  • 150
  • 1
    Something that could probably be a little bit clearer is: delegated callbacks are always called after the directly added callbacks, even if they where added before. (important if callbacks for the same objects are use with both _direct_ and _delegate_ and stopPropagation is used). and that for events like `mousemove`, `scroll`, ... that are called in short intervals, the _delegated_ events could have noticeable worser performance if the selector is not simple (because a match to the selector must be done each time the event is triggered). – t.niese Apr 17 '13 at 11:02
0

The difference is in the first case the listener is targeting the document, so if you don't have .wrapper1 on page load and add it additionally (AJAX or some other way) the event will still fire (since the document is always there).

In the second case if .wrapper1 is added dynamically the event won't fire, even thought you're using .on() since you don't have an element to bind that .on() to.

That being said second variant should be used only when the selected element is not dynamically created and the first one in the opposite case.

Kaloyan
  • 7,262
  • 4
  • 32
  • 47