Вопрос по javascript-events, dom, javascript, scroll – Как захватить все события прокрутки на странице, не подключая обработчик прокрутки к каждому контейнеру

25

Рассмотрим следующую веб-страницу:

 <html>
   <body onscroll="alert('body scroll event')">
     <div style='width:200px;height:200px;overflow:auto' onscroll="alert('div scroll event')">
       <div style='height:400px'>
       </div>
     </div>
   </body>
 </html>

Этот HTML создает div с полосой прокрутки. Если вы передвинете полосу прокрутки, сработает событие «onscroll» для элемента div. Тем не менее, событие «onscroll» на теле НЕ запускается. Это ожидаемо, поскольку W3C заявляет, что события onscroll элемента не «всплывают».

Тем не менее, я разрабатываю клиентскую веб-инфраструктуру, которая должна знать каждый раз, когда прокручивается полоса прокрутки на ЛЮБОМ элементе страницы. Это было бы легко сделать, если бы «onscroll» всплыл, но, к сожалению, это не так. Есть ли другой способ обнаружить события прокрутки на всей странице? (Сейчас я сосредоточен в основном на Webkit, так что решение для Webkit было бы хорошо ...)

Вот некоторые вещи, которые я попробовал: 1. Захват DOMAttrModified (похоже, не срабатывает при перемещении полос прокрутки.) 2. Использование DOM Observers (также, похоже, не срабатывает при прокрутке полос) 3. Изменение типа события «onscroll» пузыриться (кажется невозможным)

Кажется, ЕДИНСТВЕННЫЙ способ захвата событий onscroll в глобальном масштабе - это прикрепить событие onscroll к КАЖДОМУ элементу, который может прокручиваться, что очень уродливо и может снизить производительность моей инфраструктуры.

Кто-нибудь знает лучший способ?

Заранее спасибо!

window.onscroll не работает? JustinDanielson

Ваш Ответ

4   ответа
1

когда вы хотите закрыть диалог после прокрутки чего-либо в фоновом режиме:

var scrollListener = function(e) {
    // TODO: hide dialog
    document.removeEventListener('scroll', scrollListener, true);
};

document.addEventListener('scroll', scrollListener, true);
52

аузере - использовать «захват», а не «всплывание» при присоединении события:

window.addEventListener('scroll', function(){ code goes here }, true)

К сожалению, насколько мне известно, в более старых браузерах, таких как <= IE8, нет эквивалента

Так много благодарности за это CWitty
5

Конечно, самый простой способ - использовать jQuery.Имейте в виду, что этот метод может замедлить вашу страницусущественно, Также он не будет учитывать какие-либо новые элементы, которые добавляются после привязки события.

$("*").scroll(function(e) {
    // Handle scroll event
});

В ванильном JavaScript вы можете установитьuseCapture логическое значение дляtrue на вашеaddEventListener вызовите, и он будет срабатывать по всем элементам, включая те, которые добавляются динамически.

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

Обратите внимание, что это сработает до того, как произойдет событие прокрутки Насколько я понимаю, есть два этапа, через которые проходят события. Фаза захвата происходит сначала, и начинается с корня страницы (ownerDocument?) И переходит к элементу, где произошло событие. После этого наступает фаза барботирования, которая проходит от элемента обратно к корню.

Некоторое быстрое тестирование также показало, что это может быть то, как jQuery справляется с этим (по крайней мере, для отслеживания прокрутки по всем элементам страницы), но я не уверен на 100%.

Вот JSFiddle, показывающий ванильный метод JavaScripthttp://jsfiddle.net/0qpq8pcf/

Будьте осторожны с первым подходом, потому что присоединение слушателей событий к каждому отдельному элементу DOM может сделать вещи ОЧЕНЬ медленными (не говоря уже о том, что это не учитывает элементы, добавленные после создания обработчика событий). Второй, вероятно, предпочтительнее, но вы также должны удалять его всякий раз, когда он не нужен, если это возможно (например, если вы хотите, чтобы он знал, когда закрывать всплывающее окно или что-то в этом роде, прикрепляйте его только тогда, когда всплывающее окно открыто, и удаляйте его, когда всплывающее окно закрывает). Turner Hayes
7

... чириканье сверчков ...

Хорошо, я думаю, что этот вопрос не получит никакого интереса к стековому потоку, поэтому я мог бы также ответить на свой собственный вопрос относительно лучшего решения, которое я нашел до сих пор, на случай, если другой пользователь наткнется на этот вопрос:

Лучшее решение, которое я придумала, - это захватить «onmousedown» и «onkeydown» для элемента BODY: пузырьки этих событий, и поэтому, если пользователь попытается переместить полосу прокрутки на странице, эти глобальные функции сработают как побочный эффект. продукт. Затем в этих функциях просто найдите event.target и прикрепите временное событие «onscroll» к этим объектам, пока мышь / клавиша снова не поднимется. Используя этот метод, вы можете избежать «раздувания обработчика» и, тем не менее, глобально перехватывать все события «прокрутки». (Я думаю, что это будет работать и для прокрутки "колесиком мыши", но мое исследование этой последней морщины еще не завершено.)

Также вы должны добавить событие mousewheel в документ. burak emre
приятно - я не получил весь ответ, но как только вы упомянули «onmousedown», я уже указал правильное направление - спасибо Demetris Leptos

Похожие вопросы