2009-06-18 15 views
9

Ho creato un jQuery content switcher. In generale, funziona bene, ma c'è un problema con esso. Se fai clic sui collegamenti sul lato più volte, a volte diventano visibili più parti del contenuto.Evita l'evento click in jQuery che si attiva più volte

Il problema molto probabilmente si trova da qualche parte all'interno dell'evento click. Ecco il codice:

$('#tab-list li a').click(
    function() { 
     var targetTab = $(this).attr('href'); 
     if ($(targetTab).is(':hidden')) { 
      $('#tab-list li').removeClass('selected'); 
      var targetTabLink = $(this).parents('li').eq(0); 
      $(targetTabLink).addClass('selected'); 
      $('.tab:visible').fadeOut('slow', 
       function() { 
        $(targetTab).fadeIn('slow'); 
       } 
      ); 
     } 
     return false; 
    } 
); 

Ho provato ad aggiungere un blocco per la transizione in modo che ulteriori scatti vengono ignorati come il passaggio sta avvenendo, ma senza alcun risultato. Ho cercato anche per evitare che il passaggio da essere attivato se qualcosa è già animando, utilizzando il seguente:

if ($(':animated')) { 
    // Don't do anything 
} 
else { 
    // Do transition 
} 

ma sembra sempre che le cose vengono animati. Qualche idea su come posso impedire che l'animazione venga attivata più volte?

risposta

12

Un'idea sarebbe rimuovere l'evento click all'inizio della funzione, quindi aggiungere nuovamente l'evento click al termine dell'animazione, quindi i clic durante la durata non avrebbero alcun effetto.

Se si ha la possibilità di eseguire il codice al termine dell'animazione, questo dovrebbe funzionare.

+0

Genius. Salvato il mio culo oggi con questa risposta, non riuscivo a capire perché fossero registrati più eventi di clic, ho pensato che jQuery sarebbe stato intelligente e smetterebbe di succedere, jQuery non può fare tutto per te come risulta. Grazie. –

0

Un modo potrebbe essere questo:

$('#tab-list ul li').one('click', loadPage); 
var loadPage = function(event) { 
    var $this = $(this); 
    $global_just_clicked = $this; 
    var urlToLoad = $this.attr('href'); 
    $('#content-area').load(urlToLoad, pageLoaded); 
} 
$global_just_clicked = null; 
var pageLoaded() { 
    $global_just_clicked.one('click', loadPage); 
} 

Come si può vedere, questo metodo è pieno di difetti: cosa succede quando un'altra scheda si fa clic prima che il caricamento della pagina corrente? Cosa succede se la richiesta viene respinta? e se fosse luna piena?

La risposta è: questo metodo è solo una dimostrazione rudimentale. Una corretta attuazione sarebbe:

  1. non contiene la variabile globale $global_just_clicked
  2. non si basano su .load(). Userebbe .ajax() e gestirà l'annullamento della richiesta, facendo clic su altre schede ecc.

NOTA: Nella maggior parte dei casi non è necessario adottare questo approccio round-about. Sono certo che è possibile rimediare al codice in modo tale che più clic sulla stessa scheda non influiscano sul risultato finale.

jrh.

6

Aggiungere una variabile da utilizzare come blocco anziché come (: animazione).

Sul clic, controllare se il blocco è impostato. In caso contrario, impostare il blocco, avviare il processo, quindi rilasciare il blocco al termine di fadeIn.

var blockAnimation = false; 

$('#tab-list li a').click(
    function() { 
     if(blockAnimation != true){ 
     blockAnimation = true; 
     var targetTab = $(this).attr('href'); 
     if ($(targetTab).is(':hidden')) { 
      $('#tab-list li').removeClass('selected'); 
      var targetTabLink = $(this).parents('li').eq(0); 
      $(targetTabLink).addClass('selected'); 
      $('.tab:visible').fadeOut('slow', 
       function() { 
        $(targetTab).fadeIn('slow', function(){ blockAnimation=false; }); 
       } 
      ); 
     } 
     } 
     return false; 
    } 
); 
+0

Ho provato questo approccio ma non riuscivo a farlo funzionare. Ha superato il test di blocco ogni volta. –

1

Ho giocato in giro con il codice precedente e si avvicinò con la seguente modifica che sembra funzionare:

$('#tab-list li a').click(
    function() { 
     $('.tab:animated').stop(true, true); 
     var targetTab = $(this).attr('href'); 
     if ($(targetTab).is(':hidden')) { 
      $('#tab-list li').removeClass('selected'); 
      var targetTabLink = $(this).parents('li').eq(0); 
      $(targetTabLink).addClass('selected'); 
      $('.tab:visible').fadeOut('slow', 
       function() { 
        $(targetTab).fadeIn('slow'); 
       } 
      ); 
     } 
     return false; 
    } 
); 

Tutto ciò che accade è, quando una nuova scheda viene cliccato, porta subito la corrente animazione fino alla fine e quindi inizia la nuova transizione.

3

Beh, è ​​così che l'ho fatto, e ha funzionato bene.

$(document).ready(function() { 
    $(".clickitey").click(function() { 
     if($("#mdpane:animated").length == 0) { 
      $("#mdpane").slideToggle("slow"); 
      $(".jcrtarrow").toggleClass("arrow-open"); 
     } 
    }); 
}); 

questo non sta facendo quello che il codice fa naturalmente questo è un codice dal mio sito, ma mi piace sottolineare come ho ignorato i clic che stavano accadendo durante l'animazione. Per favore fatemi sapere se questo è inefficiente in ogni caso. Grazie.

0

Un modo per fare questo per usare timeStamp proprietà di evento come questo a gap po 'di tempo tra i più clic:

var a = $("a"), 
    stopClick = 0; 


a.on("click", function(e) { 
    if(e.timeStamp - stopClick > 300) { // give 300ms gap between clicks 
    // logic here 

    stopClick = e.timeStamp; // new timestamp given 
    } 


}); 
Problemi correlati