2012-06-13 20 views
9

Estoy usando hammer.js y parece que I event.stopPropagation() no funciona con el evento tap.stopPropagation() con el evento tap

Si hago clic en el elemento secundario, el evento asociado se desencadena pero el evento principal también se desencadena y no quiero eso.

$('#parent').hammer().bind('tap', function(e) { 
    $(this).css('background', 'red'); 
});​​​​​​​​ 

$('#child').hammer().bind('tap', function(e) { 
    e.stopPropagation(); 
    $(this).css('background', 'blue'); 
}); 

Aquí se muestra un ejemplo: http://jsfiddle.net/Mt9gV/

También probé con jGestures y el problema parece ser la misma. ¿Cómo puedo lograr este resultado con una de esas bibliotecas? (u otro si es necesario)

+0

Creo que puede tener algo que ver con el hecho de que ha configurado las cosas "martillo" en los elementos padre e hijo. No estoy 100% seguro sin embargo. – Pointy

+0

Desafortunadamente, si no aplico el martillo a ambos elementos, el evento tap no funcionará. – TimPetricola

Respuesta

8

Como se mencionó en otro comentario, es de esperar, como lo hizo, que llamar event.stopPropagation() sería todo lo que es requiere detener el evento de burbujeo hasta el padre.

Detalles: Sin embargo, en Hammer.js esto no es así. Hammer crea una nueva máquina de estados de gestos para cada elemento al que llamas al $(el).hammer(). Por lo tanto, cuando el navegador activa un evento táctil en el niño, primero se procesa con la lógica para el niño y luego nuevamente con la lógica del elemento principal. Como tal, para evitar que el padre obtenga el evento toque, debe evitar que la máquina de estado del martillo del padre obtenga el evento táctil original . En general, llamar al event.stopPropagation() también detendrá la propagación del evento original. Sin embargo, el evento tap de hammer.js se activa en touchend pero el originalEvent es el evento touchstart almacenado en caché. Como tal, detener la propagación en el evento original no tiene ningún efecto debido a que el evento touchstart ha surgido hace mucho tiempo a través del DOM.

¿Solución? Creo que esto es un error en el martillo - envíe una solicitud de extracción que corrige el originalEvent en el evento tap. Como otros han sugerido que puedes verificar el objetivo del evento, pero ese siempre es el elemento padre, otro error en mi opinión. Por lo tanto, consulte el event.originalEvent.target. Aquí está un JS fiddle con esta solución mediocre implementada: http://jsfiddle.net/HHRHR/

+5

Nota: mi respuesta a esta pregunta no está actualizada: hammer.js ha cambiado significativamente desde que se publicó. – rharper

+0

Utilizamos un código casi idéntico al fragmento original de TimPetricola. Puedo confirmar que funciona como se esperaba con Hammer.JS - v1.0.5 - 2013-04-07. Parece que Hammer.js tomó este problema en serio y lo solucionó. – Douwe

0

Si no puede hacer que esto funcione ... simplemente llame a otro método en el grifo después de verificar lo necesario (arguments.callee es donde comenzaría en tal caso), esto haría tienen la ventaja añadida de permitir que otros usuarios gancho del botón también ...

function myFn(a) { if(a) $(this).css('background', 'red'); else $(this).css('background', 'blue');}

$('#parent').hammer().bind('tap', function(e) { 
    //Check arguments.callee or other data in event and call myFn 
});​​​​​​​​ 

$('#children').hammer().bind('tap', function(e) { 
    //Same here 
}); 
+3

No entiendo esas palabras en ese orden ... –

+2

'arguments.callee' está [ahora en desuso] (https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee) –

+0

I imaginaría que solo está en modo estricto ... https://developer.mozilla.org/es/JavaScript/Reference/Functions_and_function_scope/arguments/callee y no dejaría que una cosa tan pequeña me impida terminar la tarea. .. usa esto y regresa al problema una vez que hayas terminado. – Jay

0

se podría intentar comprobar e.currentTarget (o es e.target?) dentro del manejador de los padres para saber qué fue aprovechado elemento ; si es el elemento hijo, simplemente vuelve inmediatamente, de lo contrario continúa con la función.

+0

Buena idea, pero devuelve el elemento padre incluso si hago clic en el elemento secundario. – TimPetricola

+0

Hmmm. Tengo la sospecha de que Hammer realmente se une al objeto 'ventana' para hacer todos sus cálculos, calculando las coordenadas X/Y globales de un evento táctil y luego determinando de qué elemento se hizo clic. En cuyo caso, stopPropagation no tendrá ningún efecto. Pero estoy adivinando de un rápido vistazo a la fuente [Hammer.js] (https://github.com/EightMedia/hammer.js/blob/master/hammer.js). –

3

Como no pude conseguir este trabajo, utilicé una variable para saber si el evento hijo ya se ha activado. Funciona bastante bien con jGestures (no he probado con hammer.js)

var childTriggered = false; 

$('#child').bind('tapone', function(e) { 
    $(this).css('background', 'red'); 
    childTriggered = true; 
}); 

$('#parent').bind('tapone', function(e) { 
    if(childTriggered) { 
     childTriggered = false; 
     return;     
    } 
    $(this).css('background', 'blue'); 
}); 

+1

Puedo confirmar que esta lógica también funciona con hammer.js. –

3

Tuve un problema similar con los eventos táctiles.

I resuelto mediante el uso de

return false; 

que es el mismo que llamar e.preventDefault(); e.stopPropagation();

Cuestiones relacionadas