2010-03-03 18 views
12

Per favore perdonatemi se questo è ovvio.Come scrivere un ciclo in jQuery che aspetta che ciascuna funzione si completi prima di continuare il ciclo

Ho una quantità sconosciuta di elementi su una pagina, che ho bisogno di scorrere uno alla volta e fare cose a. Tuttavia, ho bisogno che il ciclo si interrompa fino a quando le funzioni utilizzate sugli elementi non sono state completate e quindi si prosegue alla successiva iterazione.

Ho provato a farlo in un ciclo $ .each, ma ha sparato i comandi molto rapidamente e terminato senza attendere il loro completamento.

Qualche idea?

$('elem').each(function(){ 
    $(this).fadeIn().wait(5000).fadeOut(); 
}); 

Questo è quello che ho, molto semplice. Ho ottenuto la funzione wait() da qui: jquery cookbook site.

Il problema è che il ciclo non fa wait: il comando effettivo funziona come previsto, è solo che tutti si attivano contemporaneamente.

Qualsiasi aiuto apprezzato, grazie.

EDIT: Dopo questo viene eseguito, mi può essere utile per poi eseguire di nuovo il ciclo, in modo che l'elenco dei elems sarà sbiadito in/out di nuovo in sequenza

EDIT2: da allora hanno ottenuto la 1.4.2 jQuery lib, stava usando 1.3.2, da qui la funzione di attesa() personalizzata. Ora usando delay() come menzionato da lobstrosity. Riuscito a mettere insieme qualcosa di simile a quello di cui ho bisogno dalla sua risposta, grazie a lobstrosity :).

risposta

9

Prima di tutto, jQuery 1.4 ha aggiunto la funzione delay, che presumo è quello che sta facendo la tua implementazione di attesa personalizzata.

Utilizzando il ritardo, è possibile smistare la funzionalità di ciascun elemento "in attesa" sull'elemento precedente per terminare utilizzando il primo parametro per ogni richiamata come moltiplicatore per un ritardo iniziale. In questo modo:

var duration = 5000; 

$('elem').each(function(n) { 
    $(this).delay(n * duration).fadeIn().delay(duration).fadeOut(); 
}); 

Quindi il primo elemento scomparirà immediatamente. Il secondo si dissolveraIn dopo 5.000 ms. Il terzo dopo 10.000 ms e così via. Tieni presente che questo è fingere. Ogni elemento non è in realtà in attesa sull'elemento precedente per finire.

+0

aaaahh questo è abbastanza vicino, grazie. E stavo usando la versione 1.3.2, ho appena ricevuto l'ultima lib, grazie per averlo indicato. L'unico problema con questo è che una volta eseguite le azioni su $ ('. Elem'), potrei voler ripetere tutto. Modificherò la domanda per refelct questo, dovrei averlo menzionato, grazie. – alan

+0

Non l'ho ancora perfetto, ma questo ha risposto alla mia domanda, grazie mille. – alan

0

probabilmente è necessario chiamare attendere prima che la prima funzione:

$(this).wait().fadeIn().wait(5000).fadeOut(); 

L'altra opzione è quella di utilizzare il callback.

$(this).wait().fadeIn('slow', function(){$(this).fadeOut('slow')}); 

In questo modo il fadeOut non si avvia finché non viene eseguita la dissolvenza.

+0

grazie per la risposta, ma l'ordine del fadeIn e fadeOuts non è un problema, è il fatto che l'anello .each chiama ciascuno di essi all'interno circa 0,3 secondi, e rende tutto accada allo stesso tempo, ho bisogno del ciclo per attendere la richiamata. – alan

3

Il loop principale utilizzando each() verrà eseguito senza ritardo sulla raccolta di elementi. Devi invece accodare questi elementi.

Questo potrebbe bisogno di tweaking (e potrebbe utilizzare le code di jQuery?), Ma per dimostrare utilizzando la ricorsione per elaborare la coda:

function animate(elems) { 
    var elem = elems.shift(); 
    $(elem).fadeIn().wait(5000).fadeOut(2000, function() { 
     if (elems.length) { 
      animate(elems); 
     } 
    }); 
} 

var elems = $('elem'); 
animate(elems); 
+0

Penso che un numero sconosciuto di elementi stia bene per questo, perché "spostiamo()" il prossimo elemento dalla matrice. Questo verrà eseguito solo una volta sulla raccolta, quindi terminerà. –

+0

shift sembra non funzionare su jquery object, ho ricevuto questo errore: 'TypeError: 'undefined' non è una funzione (valutando 'elems.shift()')' – Matthieu

+0

Appena fondata la soluzione: usa get(): ' var elems = $ ("elem"). get(); ' – Matthieu

0

Ecco una demo del mio solution.

Quello che ti serve non è un ciclo per gestire l'elaborazione. Quello che vuoi è concatenare le chiamate. Sembra che ci potrebbe essere un modo più semplice, ma qui c'è un metodo a forza bruta.

// Create a function that does the chaining. 
function fadeNext(x,y) { 
    return function() { x.fadeIn(100).delay(100).fadeOut(1000, (y?y.fadeNext:y)); }; 
} 

// Get all the elements to fade in reverse order. 
var elements = []; 
$('.f').each(function(i,e) {elements.unshift(e);}); 

// Iterate over the elements and configure a fadeNext for each. 
var next; 
for (var i in elements) { 
    var e = $(elements[i]); 
    e.fadeNext = fadeNext(e,next); 
    next = e; 
} 

// Start the fade. 
next.fadeNext(); 
+0

questa è una buona idea, grazie per la pubblicazione. Questo codice è buono :) – alan

Problemi correlati