Comment capturer tous les événements de défilement sur une page sans attacher un gestionnaire d'incrustations à chaque conteneur

Considérez la page Web suivante:

<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> 

Ce html crée une div avec une barre de défilement. Si vous déplacez la barre de défilement, l'événement "onscroll" sur l'élément div est déclenché. Cependant, l'événement "onscroll" sur le corps n'est PAS déclenché. Ceci est attendu, puisque le W3C déclare que les événements d'événements d'éléments ne "font pas la bulle".

Cependant, je développe un cadre Web côté client qui doit savoir à chaque fois qu'une barre de défilement sur TOUT élément de la page est défilée. Cela serait facile à faire si "onscroll" a bouillonné, mais malheureusement, il ne le fait pas. Existe-t-il une autre façon de détecter les événements sur une page entière? (À l'heure actuelle, je me concentre principalement sur Webkit, donc une solution spécifique à Webkit serait bien …)

Voici certaines choses que j'ai essayé: 1. Capturer DOMAttrModified (ne semble pas déclencher pour déplacer des barres de défilement.) 2. Utiliser les observateurs DOM (ne semble pas également déclencher pour les barres de défilement) 3. Modification du type d'événement "onscroll" À bulle (semble ne pas être possible)

Il semble que le seul moyen de capturer les événements onscroll dans le monde entier est de joindre un événement onscroll à TOUS les éléments qui peuvent défiler, ce qui est très laid et va nuire à la performance de mon framework.

Quelqu'un connait-il une meilleure façon?

Merci d'avance!

La manière la plus simple de détecter tous les événements de défilement dans un navigateur moderne utiliserait 'capture' plutôt que 'bouillonnement' lors de la connexion de l'événement:

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

Malheureusement, je suis conscient qu'il n'y a pas d'équivalent dans un navigateur plus ancien tel que <= IE8

* … les grillons chantant … *

D'accord, je suppose que cette question ne va pas avoir d'amour de stackoverflow, alors je pourrais aussi bien répondre à ma propre question quant à la meilleure solution que j'ai trouvée jusqu'ici, au cas où un autre utilisateur trancherait sur cette question:

La meilleure solution que j'ai trouvée consiste à capturer "onmousedown" et "onkeydown" pour l'élément BODY: ces événements font des bulles, et donc si un utilisateur essaie de déplacer une barre de défilement sur la page, ces fonctions globales vont déclencher, produit. Ensuite, dans ces fonctions, recherchez simplement event.target et joignez un événement temporaire "onscroll" à ces objets jusqu'à ce que la souris / la touche soit "à nouveau" à nouveau. À l'aide de cette méthode, vous pouvez éviter le "manipulateur bloot" et toujours capturer globalement tous les événements "onscroll". (Je pense que cela fonctionnera aussi pour le défilement de la "roulette de la souris", mais mes recherches sur cette rides finale sont toujours en attente.)

Ce qui suit fonctionne bien lorsque vous souhaitez cadrer une boîte de dialogue après que tout en arrière plan est défilé:

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

J'avais ce même problème.

La manière la plus simple est évidemment d'utiliser jQuery.

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

Dans vanilla JavaScript, vous pouvez définir le booléen useCapture sur true sur votre appel addEventListener , et il déclenchera tous les éléments, y compris ceux ajoutés dynamiquement.

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

Notez cependant que cela va déclencher avant que l'événement de défilement ne se produise réellement. Si je comprends bien, il y a deux phases d'événements. La phase de capture se produit d'abord et commence à partir de la racine de la page (ownerDocument?) Et se déplace jusqu'à l'élément où l'événement s'est produit. Ensuite, la phase bouillonnante, qui traverse l'élément en arrière vers la racine.

Certains tests rapides ont également montré que cela pourrait être la façon dont jQuery le gère (pour le suivi des défilements sur tous les éléments de la page au moins), mais je ne suis pas sûr à 100%.

Voici un JSF qui montre la méthode Vanilla JavaScript http://jsfiddle.net/0qpq8pcf/