6

Is there any difference between those two?

$(window).on('scroll', function() { /**/ });

and

$(document).on('scroll', function() { /**/ });

The reason I'm asking is that I've noticed that if I have 2 handlers (one listening on window and the second on document) and at some point I will return false; in the document one, the window handler stops firing, even if the event is namespaced.

You can see the behavior here. After you scroll beyond 300px from the top, the window handler's count doesn't increase anymore.

If I change the window selector to document, the conflict doesn't occur.

And the Fiddle code:

HTML

<div class="fixed">
  <div>document scroll event: <span class="scroll1">0</span></div>
  <div>window scroll event: <span class="scroll2">0</span></div>
</div>

CSS

body {
  height: 3000px;
}

.fixed {
  position: fixed;
  top: 20px;
  left: 20px;
}

JS

$(function () {
    var $scroll1 = $('.scroll1');
    var $scroll2 = $('.scroll2');

    function updateCount($el) {
        $el.text(parseInt($el.text(), 10) + 1);
    }

    $(document).on('scroll', function () {
        updateCount($scroll1);
        if ($(this).scrollTop() > 300) {
            return false;
        }
    });

    $(window).on('scroll', function () {
        updateCount($scroll2);
    });
});
Waleed Iqbal
  • 1,308
  • 19
  • 35
lesssugar
  • 15,486
  • 18
  • 65
  • 115
  • `document` event triggers before `window` event but you are `returning false` in the `document` event so why would you expect the `window` event to trigger? – Nope Jan 25 '18 at 12:53
  • https://stackoverflow.com/questions/9895202/what-is-the-difference-between-window-screen-and-document-in-javascript – Prince Sodhi Jan 25 '18 at 12:54
  • @Nope Do you mean the `document` event fires before `window` *in my code* or generally this is how browsers handle JS in this case? If I swap the order of the event handlers in my example -- nothing changes. – lesssugar Jan 25 '18 at 12:56
  • @lesssugar Test it. do `$(window).on('click', function(){console.log('window-click');})` - `$(document).on('click', function(){console.log('document-click');})` and see what happens. Add `return false` to the document event and see the result. It's how it is. Stick with `document` or `window` I suppose. – Nope Jan 25 '18 at 12:58
  • Majority of people will use window to attach listeners for scroll and resize – charlietfl Jan 25 '18 at 12:59
  • @Nope Yep, of course, I see what you're saying. Click on `documents` returns `false`, thus preventing event propagation up. I thought I could resolve this using namespaced events, but I was wrong. – lesssugar Jan 25 '18 at 13:02

1 Answers1

23

Events bubble

what you have is

window
  |
  v
document
  |
  v
body

This is how the events are handled

  1. user scrolls on body
  2. Event scroll is triggered on body
  3. check event handlers
    3.1. if any event handler on body returns false stop here
    3.2. if no event handlers registered or all event handlers return true, null or undefined pass scroll event to parent(document, goto step 4)

  4. Event scroll is triggered on document

  5. check event handlers
    5.1. if any event handler on document returns false stop here
    5.2. if no event handlers registered or all event handlers return true, null or undefined pass scroll event to parent(window goto step 6)

  6. Event scroll is triggered on window

  7. check event handlers
    7.1. if any event handler on window returns false stop here
    7.2. if no event handlers registered or all event handlers return true, null or undefined call other event handlers that come after this one.

You can see where the break points are at #.1
If any of those return false the entire bubble sequense is halted. it's like an emergency brake on a train. Not only your cart stops where you are scoped/positioned, but the entire train stops.

Tschallacka
  • 27,901
  • 14
  • 88
  • 133