¿Vinculando múltiples eventos a un oyente (sin JQuery)?

144

Mientras trabajaba con eventos del navegador, comencé a incorporar los eventos táctiles de Safari para dispositivos móviles. Encuentro que addEventListeners se están acumulando con condicionales. Este proyecto no puede usar JQuery.

Un oyente de eventos estándar:

/* 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's bindpermite múltiples eventos, así:

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

¿Hay alguna manera de combinar los dos oyentes de eventos como en el ejemplo de JQuery? ex:

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

Cualquier sugerencia o consejo son apreciados!

johnkreitlow
fuente
@RobG probablemente porque la pregunta es cómo replicar algunas de las funciones de jQuery. No estoy seguro de si ese es un uso apropiado para una etiqueta o no.
Michael Martin-Smucker
Justo, me pareció que la pregunta no la necesitaba. Sin embargo, parece un poco sarcástico, eliminado.
RobG

Respuestas:

104

En POJS, agrega un oyente a la vez. No es común agregar el mismo oyente para dos eventos diferentes en el mismo elemento. Puede escribir su propia función pequeña para hacer el trabajo, por ejemplo:

/* 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(){…});

Esperemos que muestre el concepto.

Editar 25-02-2016

El comentario de Dalgard me hizo revisar esto. Supongo que agregar el mismo oyente para múltiples eventos en un elemento es más común ahora para cubrir los diversos tipos de interfaz en uso, y la respuesta de Isaac ofrece un buen uso de los métodos integrados para reducir el código (aunque menos código es, en sí mismo) , no necesariamente una bonificación). Extendido con las funciones de flecha ECMAScript 2015 da:

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

Una estrategia similar podría agregar el mismo oyente a múltiples elementos, pero la necesidad de hacerlo podría ser un indicador para la delegación de eventos.

RobG
fuente
44
Gracias por la frase "It is not common to add the same listener for two different events on the same element."A veces los desarrolladores (más ecológicos) necesitan escuchar esto para saber que lo están haciendo bien :)
Ivan Durst
1
¿No quieres decir "no es poco común"?
dalgard
2
@ dalgard: es más común ahora que los dispositivos táctiles son más comunes, pero solo para un número limitado de eventos (como mousemove y touchmove). El hecho de que sea necesario muestra la miopía de los eventos de nombres después de los elementos físicos, el movimiento del puntero podría haber sido más apropiado. Se puede implementar mediante el tacto u otro dispositivo. Antes de los ratones (o ratones) había ruedas x / y, algunas que he usado tenían ruedas de mano y pie (Stecometer de los años 70). También hay bolas de seguimiento y esferas, algunas se mueven en 3d.
RobG
2
@RobG: La API con la que estoy tratando es el DOM, y sí, sus defectos son legión :) Pero también puede ser simplemente una cuestión de evitar el código duplicado en escuchas que son similares.
dalgard
1
@ Pedro Ferreira: sí, por supuesto, probablemente más de la mitad de los navegadores actualmente en uso no admiten funciones de flecha, pero son divertidos para jugar y siempre está Babel . ;-)
RobG
119

Alguna sintaxis compacta que logra el resultado deseado, POJS:

   "mousemove touchmove".split(" ").forEach(function(e){
      window.addEventListener(e,mouseMoveHandler,false);
    });
Isaac
fuente
154
O directamente['mousemove', 'touchmove'].forEach(...)
Dan Dascalescu
+1 ¡Y no necesita la extensión «Funciones de flecha ECMAScript 2015»! ;-)
Pedro Ferreira
@zuckerburg Para empezar, en lugar de codificar la matriz, codificó la cadena y luego la dividió, ¿está realmente seguro de que este es el camino a seguir? ¿Estás seguro de que esta es la forma más fácil de escribir esto? ['mousemove', 'touchmove'].forEach(function(event) { window.addEventListener(event, handler);}); no solo sería mucho más legible, sino que también sería mucho más rápido no tener que dividir la cadena y luego ejecutar una función para cada elemento en la matriz resultante.
Iharob Al Asimi
2
@IharobAlAsimi este código fue escrito hace más de 4 años, encontré mi barra espaciadora en ese momento. La división de la cadena estaba relacionada con el uso de una cadena por parte del OP
Isaac
1
@IharobAlAsimi No escribí el código. Dijiste que era ilegible. Claramente, no es así, ya que usted y yo somos capaces de leer el código. Esto es como discutir sobre la gramática. El 99% de todos los programadores pueden leer el código bastante bien
zuckerburg
55

Limpiando la respuesta de Isaac:

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

EDITAR

Función auxiliar ES6:

function addMultipleEventListener(element, events, handler) {
  events.forEach(e => element.addEventListener(e, handler))
}
pmrotule
fuente
1
FYI: map! = ForEach
jpoppe
10

Para mi; Este código funciona bien y es el código más corto para manejar múltiples eventos con las mismas funciones (en línea).

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.");
    });
}
usuario3796876
fuente
Exactamente lo que estoy buscando. ¡Gracias!
Elharony
10

ES2015:

let el = document.getElementById("el");
let handler =()=> console.log("changed");
['change', 'keyup', 'cut'].forEach(event => el.addEventListener(event, handler));
ChrisTheButcher
fuente
Alternativamente usando el for...ofbucle
amigo
3

Tengo una solución más simple para ti:

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

He probado esto y funciona muy bien, por el lado positivo, es compacto y sencillo como los otros ejemplos aquí.


fuente
1
Solo hay un .onload posible. Quizás sobrescribas a un viejo oyente. Dependiendo de su entorno, esto puede ser un problema.
HolgerJeromin
1

AddEventListener toma una cadena simple que representa event.type . Por lo tanto, debe escribir una función personalizada para iterar sobre múltiples eventos.

Esto se maneja en jQuery usando .split ("") y luego iterando sobre la lista para establecer los EventListeners para cada uno 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
Selvakumar Arumugam
fuente
0

Una forma de hacerlo:

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>

Reza Saadati
fuente