web-dev-qa-db-fra.com

Est-il possible de capturer par programme tous les événements de la page dans le navigateur?

Tout d’abord, voici une liste des types d’événements définis par les normes W3C. (Cette liste est basée sur les attributs onevent définis dans le standard HTML5. Je suppose qu'il existe des dizaines d'autres types d'événements, mais cette liste est suffisamment longue telle quelle.) 

  • avorter
  • post-impression
  • avant impression
  • avant le déchargement
  • brouiller
  • peut jouer
  • peut jouer
  • changement
  • cliquez sur
  • menu contextuel
  • copie
  • échange
  • couper
  • dblclick
  • DOMContentLoaded
  • traîne
  • dragend
  • dragenter
  • glisser
  • trainer
  • dragstart
  • drop
  • duréechangement
  • vide
  • terminé
  • erreur
  • concentrer
  • concentrer
  • focusout
  • échange de forme
  • en entrée
  • hashchange
  • contribution
  • invalide
  • touche Bas
  • appuyez sur la touche
  • keyup
  • charge
  • loadeddata
  • chargé de données
  • loadstart
  • message
  • souris vers le bas
  • mouseenter
  • laisser la souris
  • déplacer la souris
  • sortie de souris
  • passer la souris
  • mouseup
  • roulette de la souris
  • hors ligne
  • en ligne
  • masquer la page
  • pageshow
  • coller
  • pause
  • jouer
  • en jouant
  • popstate
  • le progrès
  • changement de taux
  • readystatechange
  • refaire
  • réinitialiser
  • redimensionner
  • scroll
  • recherché
  • cherchant
  • sélectionner
  • spectacle
  • calé
  • espace de rangement
  • soumettre
  • suspendre
  • date de mise à jour
  • undo
  • décharger
  • volumechanger
  • attendre

Maintenant, est-il possible de définir un gestionnaire d'événements global appelé lorsque l'événement any se produit à l'origine sur l'élément any de la page? (Dans ce cas, je ne veux pas compter les événements qui se sont produits sur des éléments parce qu'ils émanaient d'un élément descendant - c'est pourquoi j'ai écrit "à l'origine".)

Si cela n’est pas possible, est-il au moins possible de définir un gestionnaire d’événements appelé lorsque l’événement any bouillonne jusqu’à la racine de l’arbre DOM (soit l’objet document ou l’objet window - les deux doivent fonctionner) )? (Je sais qu’il est possible d’arrêter de faire des bulles par programmation, mais j’utiliserais ce gestionnaire d’événements sur une page qui n’a pas d’autres gestionnaires définis sur d’autres éléments.) (En outre, je crois que certains événements n’éclatent pas, mais ignorons ces cas dans l’intérêt de cet argument.)

Je sais que je peux le faire (avec jQuery): 

$(document).bind('abort afterprint beforeprint beforeunload etc.', function() {
    // handle event
});

mais ce serait une solution plutôt indésirable pour moi.

en fait, je n'ai pas besoin d'une solution multi-navigateur. Si cela fonctionne dans un seul navigateur, je vais bien.

En outre, Firebug est capable de consigner des événements , mais j'aimerais pouvoir capturer l'événement par programme (via JavaScript) plutôt que de simplement les consigner dans la console.

45
Šime Vidas
/*

function getAllEventTypes(){

  if(location.href !='https://developer.mozilla.org/en-US/docs/Web/Events') return;

  var types = {};
  $('.standard-table:eq(0) tr').find('td:eq(1)').map(function(){
    var type = $.trim(this.innerText) || 'OtherEvent';
    types[type] = types[type] || [];     
    var event = $.trim(this.previousElementSibling.innerText);
    if(event) types[type].Push(event);
  });
  for(var t in types) types[t] = types[t].join(' ');
  return "var DOMEvents = "+JSON.stringify(types, null, 4).replace(/"(\w+)\":/ig, '$1:');
}

*/

var DOMEvents = {
UIEvent: "abort DOMActivate error load resize scroll select unload",
ProgressEvent: "abort error load loadend loadstart progress progress timeout",
Event: "abort afterprint beforeprint cached canplay canplaythrough change chargingchange chargingtimechange checking close dischargingtimechange DOMContentLoaded downloading durationchange emptied ended ended error error error error fullscreenchange fullscreenerror input invalid languagechange levelchange loadeddata loadedmetadata noupdate obsolete offline online open open orientationchange pause pointerlockchange pointerlockerror play playing ratechange readystatechange reset seeked seeking stalled submit success suspend timeupdate updateready visibilitychange volumechange waiting",
AnimationEvent: "animationend animationiteration animationstart",
AudioProcessingEvent: "audioprocess",
BeforeUnloadEvent: "beforeunload",
TimeEvent: "beginEvent endEvent repeatEvent",
OtherEvent: "blocked complete upgradeneeded versionchange",
FocusEvent: "blur DOMFocusIn  Unimplemented DOMFocusOut  Unimplemented focus focusin focusout",
MouseEvent: "click contextmenu dblclick mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup show",
SensorEvent: "compassneedscalibration Unimplemented userproximity",
OfflineAudioCompletionEvent: "complete",
CompositionEvent: "compositionend compositionstart compositionupdate",
ClipboardEvent: "copy cut paste",
DeviceLightEvent: "devicelight",
DeviceMotionEvent: "devicemotion",
DeviceOrientationEvent: "deviceorientation",
DeviceProximityEvent: "deviceproximity",
MutationNameEvent: "DOMAttributeNameChanged DOMElementNameChanged",
MutationEvent: "DOMAttrModified DOMCharacterDataModified DOMNodeInserted DOMNodeInsertedIntoDocument DOMNodeRemoved DOMNodeRemovedFromDocument DOMSubtreeModified",
DragEvent: "drag dragend dragenter dragleave dragover dragstart drop",
GamepadEvent: "gamepadconnected gamepaddisconnected",
HashChangeEvent: "hashchange",
KeyboardEvent: "keydown keypress keyup",
MessageEvent: "message message message message",
PageTransitionEvent: "pagehide pageshow",
PopStateEvent: "popstate",
StorageEvent: "storage",
SVGEvent: "SVGAbort SVGError SVGLoad SVGResize SVGScroll SVGUnload",
SVGZoomEvent: "SVGZoom",
TouchEvent: "touchcancel touchend touchenter touchleave touchmove touchstart",
TransitionEvent: "transitionend",
WheelEvent: "wheel"
}

var RecentlyLoggedDOMEventTypes = {};

for(DOMEvent in DOMEvents){

  var DOMEventTypes = DOMEvents[DOMEvent].split(' ');

  DOMEventTypes.filter(function(DOMEventType){
    var DOMEventCategory = DOMEvent + ' '+DOMEventType;  
    document.addEventListener(DOMEventType, function(e){
      if(RecentlyLoggedDOMEventTypes[DOMEventCategory]) return;
      RecentlyLoggedDOMEventTypes[DOMEventCategory] = true;
      setTimeout(function(){ RecentlyLoggedDOMEventTypes[DOMEventCategory] = false }, 5000);
      var isActive = e.target==document.activeElement;
      if(isActive) {
        console.info(DOMEventCategory, 
          ' target=', e.target, 
          ' active=', document.activeElement, 
          ' isActive=', true );
      } else {
        console.log(DOMEventCategory, 
          ' target=', e.target,
          ' active=', document.activeElement, 
          ' isActive=', false );
      }

    }, true);
  });

}
17
Vlad Mysla

Vous pouvez parcourir toutes les propriétés de l'élément dom et sélectionner celles qui correspondent à /on(.*)/mot (par exemple, onclick ou onmousemove):

var events = [];
for (var property in element) {
    var match = property.match(/^on(.*)/)
    if (match) { 
        events.Push(match[1]);
    }
}
console.log(events.join(' '))
7
YankovskyAndrey

Je doute fortement qu'il y ait un moyen de faire cela dans Firefox. En regardant le code source de Firebug (en particulier la méthode attachAllListeners), il s'avère qu'itérer dans une liste de noms d'événements est évidemment la solution, mais cela ne résout pas le problème.

5
user123444555621

Il ne semble pas y avoir de «moyen facile» de le faire.

Mon idée: Vous savez quels sont tous les événements, vous pouvez donc gérer tous les événements pour chaque élément DOM:

var events =
[   
    "onabort",
    "onafterprint",
    "onbeforeprint",
    "onbeforeunload",
    ...

];

var root = document.body;
var elms = root.childNodes;

for(var i = 0; i < elms.length; i++)
{
    for(var j = 0; j < events.length; j++)
    {
        elms[i][events[j]] = globalHandler;
    }
}

function globalHandler()
{
    alert("Global handler called");
}

C'est l'idée "intuitive" mais cela ne semble pas très efficace. Cependant, cela devrait fonctionner.

Bonne chance.

2
josec89

Pour la dernière version du site Web MDN:

(function getAllEventTypes(){
  if(location.href !='https://developer.mozilla.org/en-US/docs/Web/Events') return;

  var types = {};
  $('.standard-table').map(function(){
    if($(this).find('caption').length > 0){
        var type = $(this).find('caption')[0].innerHTML || 'OtherEvent';
    types[type] = types[type] || [];     
    $(this).find('tbody tr td code a').each(function(el){
        if(this.innerText) types[type].Push(this.innerText);
    });
    }
  });
  for(var t in types) types[t] = types[t].join(' ');
  return "var DOMEvents = "+JSON.stringify(types, null, 4).replace(/"(\w+)\":/ig, '$1:');
})();
0
Martino Lessio