Hanna
Hanna

Reputation: 10763

Listening to all scroll events on a page

Background:

I'm writing a component that opens up a sub-menu on click. I can't know where this component will be placed on the page or how far it will be nested in areas that may have the overflow property set.

Given that the overflow may clip the sub-menu I am instead making the sub-menu itself be attached to the body giving it an absolute position and linking it via code to the original component. This takes care of the overflow issue.

Problem:

However if a user scrolls the sub-menu remains in place, rather than moving with its linked component, so I need to be able to listen to any and all scroll events that occur on the page so I can reposition the sub-menu appropriately.

If there's an easy way to listen to all scroll events or if there's another better way to do this component I would appreciate any input.

I've played around with JSFiddle and set up a sandbox but I haven't had any success nor have I found an answer on this site or anywhere else for that matter; though perhaps I was using the wrong search terms, I can't imagine that I'm the first to have this question.

EDIT

To address the close vote, I'm not asking help to debug an issue without providing code nor am I asking something that won't help anyone in the future. I'm asking how I would go about listening to all event of a certain type not matter where the may occur, which I find globally applicable, though perhaps that's subjective.

EDIT

$(window).on('scroll', function(){ /**/ }); is not an option as it only listens to the window scroll, not any nested scrolls.

$('#ex1 #ex2').on('scroll', function(){ /**/ }); is not an option as it requires the person who is implementing the code to be aware of any current or possible future areas on the page that may scroll.

Upvotes: 36

Views: 20815

Answers (4)

csuwldcat
csuwldcat

Reputation: 8249

You should be able to attach a document-level listener with a third parameter of true to capture the scroll events on all elements. Here's what that looks like:

document.addEventListener('scroll', function(e){ }, true);

The true at the end is the important part, it tells the browser to capture the event on dispatch, even if that event does not normally bubble, like change, focus, and scroll.

Here's an example: http://jsbin.com/sayejefobe/1/edit?html,js,console,output

Upvotes: 95

ArtOfCode
ArtOfCode

Reputation: 5712

The best way to do it would be to find out which elements are scrollable, then attach listeners to them. You could run this function on any page change to make sure you've always got all the scrollables.

This is a benefit over using listeners on every element (as the other solutions would do) in terms of performance: every time the page updates so do the listeners. With lots, this quickly affects performance and memory use.

The updated fiddle: http://jsfiddle.net/ArtOfCode/wAadt/8/

The code:

$("*").each(function() {
    if($(this).css("overflow") == "auto" || $(this).css("overflow") == "scroll") {
        $(this).scroll(function() {
            console.log("scroll");
        });
    }
});

(thanks to @pebbl for the help)

You could then wrap this in a function and run it on change:

function addListeners() {
    $("*").each(function() {
        if($(this).css("overflow") == "auto" || $(this).css("overflow") == "scroll") {
            $(this).css('border', '1px solid red').scroll(function() {
                console.log("scroll");
            });
        }
    });
}

$("body").on("change",function()
    addListeners();
}

Admittedly it is a bit convoluted but it addresses the issue with as few event listeners as possible.

Upvotes: 2

Kræn Hansen
Kræn Hansen

Reputation: 1565

How about listing on all elements and the window?

$('*').add(window).scroll(function() {
    console.log('scroll');
});

Upvotes: 2

Ashok Kumar Gupta
Ashok Kumar Gupta

Reputation: 974

You need to see whether scroll is happening to window level or to an element level. Usually in your case '*' should suffice.

$('*').scroll(function() {
    alert('scroll');
});

Here is updated link: http://jsfiddle.net/wAadt/1

Upvotes: 2

Related Questions