web-dev-qa-db-fra.com

ajout de plusieurs écouteurs d'événement à un élément

Donc, mon dilemme est que je ne veux pas écrire le même code deux fois. Une fois pour l'événement click et un autre pour l'événement touchstart.

Voici le code original:

document.getElementById('first').addEventListener('touchstart', function(event) {
    do_something();
    });

document.getElementById('first').addEventListener('click', function(event) {
    do_something(); 
    });

Comment puis-je compacter cela? Il doit y avoir un moyen plus simple!

34
coiso

Peut-être que vous pouvez utiliser une fonction d'assistance comme celle-ci:

// events and args should be of type Array
function addMultipleListeners(element,events,handler,useCapture,args){
  if (!(events instanceof Array)){
    throw 'addMultipleListeners: '+
          'please supply an array of eventstrings '+
          '(like ["click","mouseover"])';
  }
  //create a wrapper to be able to use additional arguments
  var handlerFn = function(e){
    handler.apply(this, args && args instanceof Array ? args : []);
  }
  for (var i=0;i<events.length;i+=1){
    element.addEventListener(events[i],handlerFn,useCapture);
  }
}

function handler(e) {
  // do things
};

// usage
addMultipleListeners(
    document.getElementById('first'),
    ['touchstart','click'],
    handler,
    false);
18
KooiInc

Je sais que c’est une vieille question, mais j’ai pensé que certains pourraient trouver cette approche utile; il pourrait être appliqué à tout code répétitif similaire:

ES6

['click','ontouchstart'].forEach( evt => 
    element.addEventListener(evt, dosomething, false)
);

ES5

['click','ontouchstart'].forEach( function(evt) {
    element.addEventListener(evt, dosomething, false);
});
59
Allan Nienhuis

Vous pouvez simplement définir une fonction et la transmettre. Les fonctions anonymes ne sont nullement spéciales, toutes les fonctions peuvent être transmises sous forme de valeurs.

var elem = document.getElementById('first');

elem.addEventListener('touchstart', handler, false);
elem.addEventListener('click', handler, false);

function handler(event) {
    do_something();
}
8
Esailija

Pour un grand nombre d'événements, cela pourrait aider:

var element = document.getElementById("myId");
var myEvents = "click touchstart touchend".split(" ");
var handler = function (e) {
    do something
};

for (var i=0, len = myEvents.length; i < len; i++) {
    element.addEventListener(myEvents[i], handler, false);
}

Mise à jour 06/2017:

Maintenant que les nouvelles fonctionnalités linguistiques sont plus largement disponibles, vous pouvez simplifier l'ajout d'une liste limitée d'événements partageant un auditeur.

const element = document.querySelector("#myId");

function handleEvent(e) {
    // do something
}
// I prefer string.split because it makes editing the event list slightly easier

"click touchstart touchend touchmove".split(" ")
    .map(name => element.addEventListener(name, handleEvent, false));

Si vous souhaitez gérer de nombreux événements et avoir différentes exigences par auditeur, vous pouvez également transmettre un objet que la plupart des gens ont tendance à oublier.

const el = document.querySelector("#myId");

const eventHandler = {
    // called for each event on this element
    handleEvent(evt) {
        switch (evt.type) {
            case "click":
            case "touchstart":
                // click and touchstart share click handler
                this.handleClick(e);
                break;
            case "touchend":
                this.handleTouchend(e);
                break;
            default:
                this.handleDefault(e);
        }
    },
    handleClick(e) {
        // do something
    },
    handleTouchend(e) {
        // do something different
    },
    handleDefault(e) {
        console.log("unhandled event: %s", e.type);
    }
}

el.addEventListener(eventHandler);
8
Torsten Walter

À moins que votre fonction do_something n'effectue réellement quelque chose avec des arguments donnés, vous pouvez simplement le transmettre en tant que gestionnaire d'événements.

var first = document.getElementById('first');
first.addEventListener('touchstart', do_something, false);
first.addEventListener('click', do_something, false);
7
Mattias Buelens

J'ai une petite solution qui s'attache au prototype

  EventTarget.prototype.addEventListeners = function(type, listener, options,extra) {
  let arr = type;
  if(typeof type == 'string'){
    let sp = type.split(/[\s,;]+/);
    arr = sp;   
  }
  for(let a of arr){
    this.addEventListener(a,listener,options,extra);
  }
};

Vous permet de lui donner une chaîne ou un tableau. La chaîne peut être séparée par un espace (''), une virgule (',') OR et un point-virgule (';') 

2
Strauss Bornman

document.getElementById('first').addEventListener('touchstart',myFunction);

document.getElementById('first').addEventListener('click',myFunction);
    
function myFunction(e){
  e.preventDefault();e.stopPropagation()
  do_something();
}    

Vous devriez utiliser e.stopPropagation() car sinon, votre fonction sera déclenchée deux fois sur mobile.

1

Je viens de faire cette fonction (intentionnellement minified):

((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, events, handler)

Usage:

((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, ['click', 'touchstart'], (event) => {
    // function body
});

La différence par rapport aux autres approches réside dans le fait que la fonction de traitement est définie une seule fois, puis transmise à chaque addEventListener.

MODIFIER:

Ajouter une version non-minifiée pour la rendre plus compréhensible. La version abrégée était simplement destinée à être copiée-collée et utilisée.

((element, event_names, handler) => {

    event_names.forEach( (event_name) => {
        element.addEventListener(event_name, handler)
    })

})(element, ['click', 'touchstart'], (event) => {

    // function body

});
0
Ian Pollak

Semi-lié, mais cela sert à initialiser un écouteur d'événement unique spécifique par élément.

Vous pouvez utiliser le curseur pour afficher les valeurs en temps réel ou consulter la console . Sur l'élément <input>, j'ai une balise attr appelée data-whatever, afin de pouvoir personnaliser ces données si vous le souhaitez.

sliders = document.querySelectorAll("input");
sliders.forEach(item=> {
  item.addEventListener('input', (e) => {
    console.log(`${item.getAttribute("data-whatever")} is this value: ${e.target.value}`);
    item.nextElementSibling.textContent = e.target.value;
  });
})
.wrapper {
  display: flex;
}
span {
  padding-right: 30px;
  margin-left: 5px;
}
* {
  font-size: 12px
}
<div class="wrapper">
  <input type="range" min="1" data-whatever="size" max="800" value="50" id="sliderSize">
  <em>50</em>
  <span>Size</span>
  <br>
  <input type="range" min="1" data-whatever="OriginY" max="800" value="50" id="sliderOriginY">
  <em>50</em>
  <span>OriginY</span>
  <br>
  <input type="range" min="1" data-whatever="OriginX" max="800" value="50" id="sliderOriginX">
  <em>50</em>
  <span>OriginX</span>
</div>

0
Vincent Tang