2009-05-19 25 views
21

Sto gestendo sia l'evento click che dblclick su un elemento DOM. Ognuno esegue un comando diverso, ma trovo che quando si fa doppio clic sull'elemento, oltre a sparare l'evento doppio clic, anche l'evento click viene sparato due volte. Qual è l'approccio migliore per prevenire questo comportamento?Evita l'evento click da quando si attiva l'evento dblclick

risposta

11

In un commento è detto,

ho ritardare il gestore di clic da 300 ms (un ritardo notevole e fastidiosa) e persino ...

Così suona come quello che vuoi è che quando fai clic, il DOM dovrebbe generare immediatamente un evento click, tranne non se il clic è il primo clic di un doppio clic.

Per implementare questa funzione, quando fai clic, il DOM dovrebbe essere in grado di prevedere se questo è il clic finale o se è il primo di un doppio clic (tuttavia non penso sia possibile in generale per il DOM per prevedere se l'utente sta per fare di nuovo clic).


Quali sono le due azioni distinte che si stanno tentando di fare su clic e doppio clic? IMO, in un'applicazione normale potresti volere entrambi gli eventi: ad es. clic singolo per mettere a fuoco un elemento e quindi fare doppio clic per attivarlo.

Quando è necessario separare gli eventi, alcune applicazioni usano qualcosa di diverso dal doppio clic: ad esempio, usano il tasto destro o il control-click.

+0

Grazie per la risposta aggiornata. Penso che questo sia dovuto al fatto che ho bisogno di ripensare la mia interfaccia utente. Quello che voglio realizzare davvero non sarà possibile. Dovrei semplicemente usare due controlli per le due azioni, o usare un tasto modificatore invece del doppio clic. Grazie! – David

5

In questo caso, è meglio ritardare leggermente l'esecuzione dell'evento con un clic. Chiedi al tuo gestore del doppio clic di impostare una variabile che verrà verificata dall'evento con un solo clic. Se quella variabile ha un valore particolare, potrebbe essere boolDoubleClick == true, quindi non fare fire/handle con un solo clic.

+0

In realtà, questo è quello che sto facendo ora, ma sembra che sia una soluzione piuttosto kludgy. Ralento il click handler di 300 ms (un ritardo notevole e fastidioso) e anche con questo puoi ancora fare doppio clic abbastanza lentamente (ad esempio 350 ms) per farli sparare entrambi. – David

+0

Interessante. Non è irragionevole presumere che se ritardano troppo a lungo il secondo clic l'effetto desiderato sarebbe di 2 clic singoli. –

+0

Sfortunatamente il tempo di doppio clic è configurabile dall'utente finale (ad esempio utilizzando Pannello di controllo/Mouse) e suppongo che JavaScript in un browser non possa ottenere/determinare il tempo configurato come tale. – ChrisW

3

AFAIK DOM Level 2 Events non specifica per il doppio clic. Non funziona per me su IE7 (c'è uno shock), ma FF e Opera non hanno problemi a gestire le specifiche, dove posso allegare tutte le azioni all'evento click, ma per fare doppio clic basta attendere il "dettaglio" l'attributo dell'oggetto evento è 2. Dalla documentazione: "Se si verificano più clic nella stessa posizione sullo schermo, la sequenza si ripete con l'attributo dettaglio che aumenta ad ogni ripetizione."

+0

Questa è in realtà una soluzione molto elegante al problema. Richiede ancora una combinazione setTimout/clearTimeout per il primo clic, ma semplifica il coordinamento tra i due e apre persino la porta per i clic tripli, ecc. Grazie! – mckamey

2

Grazie a tutti gli altri risposte qui come la combinazione di essi sembra fornire una soluzione ragionevole per me quando l'interazione richiede sia, ma si escludono a vicenda:

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); 

Aggiornamento: ho aggiunto una versione generalizzata di questo approccio con un click polyfill per i dispositivi touch a questo repo GitHub con gli esempi:

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

2

Ecco quello che ho fatto per disting uish all'interno di un modulo

 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

nel caso qualcuno inciampa altro su questo (come ho fatto io) alla ricerca di una risposta, la soluzione migliore in assoluto che ho potuto venire in mente è la seguente:

$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 */ 
     } 
    }); 

Fatto.Se c'è più di un clic indietro, il secondo, il terzo, ecc. non sparerà. Sicuramente preferisco usare qualsiasi tipo di timer.

Mi sono fatto indicare in questa direzione leggendo this.


Per inciso: mi è stato prima occupando del problema, perché ho accidentalmente doppio clic su un collegamento impaginato, e l'evento licenziato e finito due volte prima della richiamata potrebbe accadere.

Prima di venire su con il codice di cui sopra, ho avuto

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

tuttavia, sono stato in grado di fare clic sul link per 3 volte (una tripla click), e anche se il secondo clic didn' t fire, il terzo ha fatto

+0

Ciò impedirebbe al secondo clic di sparare e consentirebbe ancora al primo clic di sparare. L'OP voleva disabilitare il 1 ° clic se c'è un secondo clic, se ho capito bene. Penso che la cosa migliore sia usare un piccolo ritardo (sto usando 200ms, ma speravo che ci fosse una soluzione migliore che non riuscivo a vedere). – ClarkeyBoy

+0

@ClarkeyBoy - non sei corretto. Questo disabiliterà il primo clic se c'è un secondo. Provalo. – user1167442

+5

Non funziona in IE 11 x64 (Win8.1): event.detail = 0 sempre, singolo clic o doppio – robert4

0

So che è vecchio come diamine, ma ho pensato di postare comunque poiché ho appena incontrato lo stesso problema. Ecco come l'ho risolto.

$('#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(); 
}); 
Problemi correlati