2009-05-19 31 views
21

Estoy manejando tanto el clic como el evento dblclick en un elemento DOM. Cada uno lleva a cabo un comando diferente, pero me parece que al hacer doble clic en el elemento, además de disparar el evento de doble clic, el evento click también se dispara dos veces. ¿Cuál es el mejor enfoque para prevenir este comportamiento?Evitar que el evento click se active cuando se activa el evento dblclick

Respuesta

11

En un comentario, usted ha dicho,

que retrasar el controlador de clic por 300 ms (un retraso notable y molesto) e incluso ...

así que suena como lo que quiere es que al hacer clic, el DOM debe generar un evento de clic inmediatamente, excepto si el clic es el primer clic de un doble clic.

Para implementar esta característica, al hacer clic, el DOM necesitaría poder predecir si este es el clic final o si es el primero de un doble clic (sin embargo, no creo que sea posible en general para el DOM para predecir si el usuario está a punto de hacer clic nuevamente).


¿Cuáles son las dos acciones distintas que intenta realizar al hacer clic y hacer doble clic en? OMI, en una aplicación normal es posible que desee ambos eventos: p. haga clic para enfocar un elemento y luego haga doble clic para activarlo.

Cuando debe separar los eventos, algunas aplicaciones utilizan algo más que hacer doble clic: por ejemplo, usan el botón derecho o hacen clic con la tecla Control presionada.

+0

Gracias por la respuesta actualizada. Creo que esto realmente se debe al hecho de que tengo que volver a pensar en mi UI. Lo que quiero lograr realmente no va a ser posible. Simplemente debería usar dos controles para las dos acciones, o usar una tecla modificadora en lugar del doble clic. ¡Gracias! – David

5

En este caso, es mejor retrasar ligeramente la ejecución del evento de un solo clic. Haga que su manejador de doble clic establezca una variable que controlará el evento de un solo clic. Si esa variable tiene un valor particular, podría ser boolDoubleClick == true, entonces no haga fire/handle con un solo clic.

+0

En realidad, eso es lo que estoy haciendo ahora, pero parece que es una solución bastante kludgy. Retraso el controlador de clics en 300 ms (un retraso notable y molesto) e incluso con eso, puede hacer doble clic lo suficientemente lento (por ejemplo, 350 ms) para hacer que ambos disparen. – David

+0

Interesante. No es irrazonable suponer que si se demoran demasiado para el segundo clic, el efecto deseado sería de 2 clics. –

+0

Lamentablemente, el usuario final puede configurar el tiempo de doble clic (por ejemplo, utilizando el Panel de control/Mouse), y supongo que JavaScript en un navegador no puede obtener/determinar cómo se configura ese retraso. – ChrisW

3

AFAIK DOM Level 2 Events no hace ninguna especificación para hacer doble clic. No funciona para mí en IE7 (hay una sorpresa), pero FF y Opera no tienen problemas para administrar la especificación, donde puedo adjuntar todas las acciones al evento click, pero para hacer doble clic simplemente espere hasta el "detalle" El atributo del objeto de evento es 2. De los documentos: "Si se producen varios clics en la misma ubicación de pantalla, la secuencia se repite con el atributo de detalle incrementándose con cada repetición".

+0

Esta es realmente una solución muy elegante al problema. Todavía requiere un combo setTimout/clearTimeout para el primer clic, pero simplifica la coordinación entre los dos e incluso abre la puerta para clics triples, etc. ¡Gracias! – mckamey

2

Gracias a todas las otras respuestas aquí como la combinación de ellos parece proporcionar una solución razonable para mí cuando la interacción requiere ambos, pero se excluyen mutuamente:

var pendingClick = 0; 

function xorClick(e) { 
    // kill any pending single clicks 
    if (pendingClick) { 
     clearTimeout(pendingClick); 
     pendingClick = 0; 
    } 

    switch (e.detail) { 
     case 1: 
      pendingClick = setTimeout(function() { 
       console.log('single click action here'); 
      }, 500);// should match OS multi-click speed 
      break; 
     case 2: 
      console.log('double click action here'); 
      break; 
     default: 
      console.log('higher multi-click actions can be added as needed'); 
      break; 
    } 
} 

myElem.addEventListener('click', xorClick, false); 

Actualización: he añadido una versión generalizada de este enfoque, junto con un polyfill clic para dispositivos táctiles a esta cesión temporal Github con ejemplos:

https://github.com/mckamey/doubleTap.js

2

esto es lo que hice para disting uish dentro de un módulo

 node.on('click', function(e) { 

      //Prepare for double click, continue to clickHandler doesn't come soon enough 
      console.log("cleared timeout in click",_this.clickTimeout); 
      clearTimeout(_this.clickTimeout); 
      _this.clickTimeout = setTimeout(function(){ 
       console.log("handling click"); 
       _this.onClick(e); 
      },200); 
      console.log(_this.clickTimeout); 
     }); 

     node.on('dblclick', function (e) { 

      console.log("cleared timeout in dblclick",_this.clickTimeout); 
      clearTimeout(_this.clickTimeout); 
      // Rest of the handler function 
11

En caso de que alguien se tropieza más en esta (como yo) en busca de una respuesta, el absoluto mejor solución que podría llegar a es el siguiente:

$node.on('click',function(e){ 
     if(e.originalEvent.detail > 1){ 
     return; 
     /* if you are returning a value from this 
     function then return false or cancel 
     the event some other way */ 
     } 
    }); 

Hecho.Si hay más de un clic atrás, el segundo, el tercero, etc. no disparará Definitivamente prefiero usar cualquier tipo de temporizadores.

Me apunté en esta dirección leyendo this.


Por cierto: yo estaba investigando por primera vez este problema, ya que accidentalmente hace doble clic en un enlace paginado, y el evento disparado y terminó dos veces antes de la devolución de llamada podría suceder.

Antes de dar con el código anterior, que tenía

if e.originalEvent.detail === 2 //return 

sin embargo, yo era capaz de hacer clic en el enlace de 3 veces (un triple clic), y aunque el segundo clic didn' t fuego, el tercero hizo

+0

Esto evitaría que el segundo clic se dispare y aún así el primer clic se disparará. El OP desea desactivar el primer clic si hay un segundo clic, si entiendo correctamente. Creo que la mejor apuesta es usar un pequeño retraso (estoy usando 200ms, pero esperaba que hubiera una mejor solución que simplemente no podía ver). – ClarkeyBoy

+0

@ClarkeyBoy - eres incorrecto. Esto desactivará el primer clic si hay un segundo. Intentalo. – user1167442

+5

No funciona en IE 11 x64 (Win8.1): event.detail = 0 siempre, ya sea con un solo clic o doble – robert4

0

Sé que esto es viejo como diablos, pero pensé en publicar de todos modos ya que me encontré con el mismo problema. Así es como lo resolví.

$('#alerts-display, #object-display').on('click', ['.item-data-summary', '.item-marker'], function(e) { 
    e.preventDefault(); 

    var id; 

    id = setTimeout(() => { 
     // code to run here 
     return false; 
    }, 150); 

    timeoutIDForDoubleClick.push(id); 
}); 


$('.panel-items-set-marker-view').on('dblclick', ['.summary', '.marker'], function(e) { 
    for (let i = 0; i < timeoutIDForDoubleClick.length; i++) { 
     clearTimeout(timeoutIDForDoubleClick[i]); 
    } 

    // code to run on double click 

    e.preventDefault(); 
}); 
Cuestiones relacionadas