Lier plusieurs événements à un écouteur (sans JQuery)?


144

Tout en travaillant avec les événements du navigateur, j'ai commencé à intégrer les touchEvents de Safari pour les appareils mobiles. Je trouve que les addEventListeners empilent avec des conditions. Ce projet ne peut pas utiliser JQuery.

Un écouteur d'événement standard:

/* option 1 */
window.addEventListener('mousemove', this.mouseMoveHandler, false);
window.addEventListener('touchmove', this.mouseMoveHandler, false);

/* option 2, only enables the required event */
var isTouchEnabled = window.Touch || false;
window.addEventListener(isTouchEnabled ? 'touchmove' : 'mousemove', this.mouseMoveHandler, false);

JQuery bindpermet plusieurs événements, comme ceci:

$(window).bind('mousemove touchmove', function(e) {
    //do something;
});

Existe-t-il un moyen de combiner les deux écouteurs d'événements comme dans l'exemple JQuery? ex:

window.addEventListener('mousemove touchmove', this.mouseMoveHandler, false);

Toutes les suggestions ou conseils sont appréciés!


@RobG probablement parce que la question est de savoir comment répliquer certaines fonctionnalités de jQuery. Je ne sais pas si c'est une utilisation appropriée pour une balise ou non.
Michael Martin-Smucker

Assez juste, il me semblait juste que la question n'en avait pas besoin. Cela a l'air un peu sournois, supprimé.
RobG

Réponses:


104

Dans POJS, vous ajoutez un auditeur à la fois. Il n'est pas courant d'ajouter le même écouteur pour deux événements différents sur le même élément. Vous pouvez écrire votre propre petite fonction pour faire le travail, par exemple:

/* Add one or more listeners to an element
** @param {DOMElement} element - DOM element to add listeners to
** @param {string} eventNames - space separated list of event names, e.g. 'click change'
** @param {Function} listener - function to attach for each event as a listener
*/
function addListenerMulti(element, eventNames, listener) {
  var events = eventNames.split(' ');
  for (var i=0, iLen=events.length; i<iLen; i++) {
    element.addEventListener(events[i], listener, false);
  }
}

addListenerMulti(window, 'mousemove touchmove', function(){…});

Espérons que cela montre le concept.

Modifier 25/02/2016

Le commentaire de Dalgard m'a amené à revoir cela. Je suppose que l'ajout du même auditeur pour plusieurs événements sur un élément est plus courant maintenant pour couvrir les différents types d'interface utilisés, et la réponse d'Isaac offre une bonne utilisation des méthodes intégrées pour réduire le code (bien que moins de code soit, en soi , pas nécessairement un bonus). Extension avec les fonctions fléchées ECMAScript 2015:

function addListenerMulti(el, s, fn) {
  s.split(' ').forEach(e => el.addEventListener(e, fn, false));
}

Une stratégie similaire pourrait ajouter le même auditeur à plusieurs éléments, mais la nécessité de le faire pourrait être un indicateur de la délégation d'événements.


4
Merci pour la phrase "It is not common to add the same listener for two different events on the same element."Parfois, les développeurs (plus verts) ont besoin d'entendre cela pour savoir qu'ils le font correctement :)
Ivan Durst

1
Vous ne voulez pas dire "ce n'est pas inhabituel"?
dalgard

2
@ dalgard: il est plus courant maintenant que les appareils tactiles sont plus courants, mais seulement pour un nombre limité d'événements (tels que mousemove et touchmove). Le fait qu'il soit nécessaire montre la myopie de nommer des événements après des éléments physiques, le déplacement du pointeur aurait pu être plus approprié. Il peut être implémenté par le toucher ou un autre appareil. Avant les souris (ou les souris), il y avait des roues x / y, certaines que j'ai utilisées avaient des roues main et pied (stécomètre des années 1970). Il y a aussi des trackballs et des sphères, certaines se déplacent en 3D.
RobG

2
@RobG: L'API dont je m'occupe est le DOM, et oui, ses défauts sont légion :) Mais il peut aussi s'agir simplement d'éviter les doublons de code dans des écouteurs similaires.
dalgard

1
@ PedroFerreira - oui bien sûr, probablement plus de la moitié des navigateurs actuellement utilisés ne prennent pas en charge les fonctions fléchées, mais elles sont amusantes à jouer et il y a toujours Babel . ;-)
RobG

119

Une syntaxe compacte qui permet d'obtenir le résultat souhaité, POJS:

   "mousemove touchmove".split(" ").forEach(function(e){
      window.addEventListener(e,mouseMoveHandler,false);
    });

155
Ou directement['mousemove', 'touchmove'].forEach(...)
Dan Dascalescu

+1 ET il n'a pas besoin de l'extension «Fonctions fléchées ECMAScript 2015»! ;-)
Pedro Ferreira

@zuckerburg Pour commencer, au lieu de coder en dur le tableau, vous avez codé en dur la chaîne, puis vous l'avez divisée, êtes-vous vraiment sûr que c'est la voie à suivre? Êtes-vous sûr que c'est la manière la plus lisible d'écrire ceci? ['mousemove', 'touchmove'].forEach(function(event) { window.addEventListener(event, handler);}); serait non seulement beaucoup plus lisible, mais aussi beaucoup plus rapide de ne pas avoir à diviser la chaîne, puis à exécuter une fonction pour chaque élément du tableau résultant.
Iharob Al Asimi

2
@IharobAlAsimi ce code a été écrit il y a plus de 4 ans, j'ai trouvé ma barre d'espace à cette époque. La division de la chaîne était liée à l'utilisation d'une chaîne par l'OP
Isaac

1
@IharobAlAsimi Je n'ai pas écrit le code. Vous avez dit que c'était illisible. Ce n'est clairement pas parce que vous et moi sommes tous les deux capables de lire le code. C'est comme se disputer sur la grammaire. 99% de tous les programmeurs sont capables de lire le code assez bien
zuckerburg

55

Nettoyer la réponse d'Isaac:

['mousemove', 'touchmove'].forEach(function(e) {
  window.addEventListener(e, mouseMoveHandler);
});

ÉDITER

Fonction d'assistance ES6:

function addMultipleEventListener(element, events, handler) {
  events.forEach(e => element.addEventListener(e, handler))
}

1
FYI: map! = ForEach
jpoppe

10

Pour moi; ce code fonctionne bien et est le code le plus court pour gérer plusieurs événements avec les mêmes fonctions (en ligne).

var eventList = ["change", "keyup", "paste", "input", "propertychange", "..."];
for(event of eventList) {
    element.addEventListener(event, function() {
        // your function body...
        console.log("you inserted things by paste or typing etc.");
    });
}

Exactement ce que je recherche. Merci!
Elharony

10

ES2015:

let el = document.getElementById("el");
let handler =()=> console.log("changed");
['change', 'keyup', 'cut'].forEach(event => el.addEventListener(event, handler));

Alternativement en utilisant la for...ofboucle
mec

3

J'ai une solution plus simple pour vous:

window.onload = window.onresize = (event) => {
    //Your Code Here
}

J'ai testé cela et cela fonctionne très bien, du côté positif, il est compact et simple comme les autres exemples ici.


1
Il n'y a qu'un seul .onload possible. Peut-être écrasez-vous un ancien auditeur. En fonction de votre environnement, cela peut être un problème.
HolgerJeromin

1

AddEventListener prend une chaîne simple qui représente event.type . Vous devez donc écrire une fonction personnalisée pour itérer sur plusieurs événements.

Ceci est géré dans jQuery en utilisant .split (""), puis en parcourant la liste pour définir les eventListeners pour chacun types.

    // Add elem as a property of the handle function
    // This is to prevent a memory leak with non-native events in IE.
    eventHandle.elem = elem;

    // Handle multiple events separated by a space
    // jQuery(...).bind("mouseover mouseout", fn);
    types = types.split(" ");  

    var type, i = 0, namespaces;

    while ( (type = types[ i++ ]) ) {  <-- iterates thru 1 by 1

0

Une façon de le faire:

const troll = document.getElementById('troll');

['mousedown', 'mouseup'].forEach(type => {
	if (type === 'mousedown') {
		troll.addEventListener(type, () => console.log('Mouse is down'));
	}
        else if (type === 'mouseup') {
                troll.addEventListener(type, () => console.log('Mouse is up'));
        }
});
img {
  width: 100px;
  cursor: pointer;
}
<div id="troll">
  <img src="http://images.mmorpg.com/features/7909/images/Troll.png" alt="Troll">
</div>

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.