2010-03-03 9 views
12

S'il vous plaît pardonnez-moi si c'est une évidence.Comment écrire une boucle dans jQuery qui attend que chaque fonction soit terminée avant de continuer la boucle

J'ai une quantité inconnue d'éléments sur une page, que j'ai besoin de faire défiler un à la fois et faire des choses. Cependant, j'ai besoin que la boucle se mette en pause jusqu'à ce que les fonctions utilisées sur les éléments soient terminées, puis continue à l'itération suivante.

J'ai essayé de le faire dans une boucle $ .each, mais cela a rapidement déclenché les commandes et terminé sans attendre qu'elles se terminent.

Des idées?

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

C'est ce que j'ai, très simple. J'ai la fonction wait() d'ici: jquery cookbook site.

Le problème est, la boucle doesnt wait - la commande réelle fonctionne comme prévu, c'est juste qu'ils se déclenchent tous à la fois.

Toute aide appréciée, merci.

EDIT: Après cette exécution, je veux exécuter ensuite à nouveau la boucle, de sorte que la liste des elems sera fanée dans/à nouveau dans l'ordre

EDIT2: Avez depuis obtenu le jQuery 1.4.2 lib, utilisait 1.3.2, d'où la fonction personnalisée wait(). Maintenant, en utilisant delay() comme mentionné par lobstrosity. Géré pour bricoler quelque chose proche de ce dont j'ai besoin de sa réponse, grâce à la lobstrosité :).

Répondre

9

d'abord, jQuery 1.4 ajoute la fonction delay, que je suppose est ce que votre implémentation d'attente personnalisée est en cours. En utilisant le délai, vous pouvez en quelque sorte simuler la fonctionnalité de chaque élément "en attente" sur l'élément précédent pour terminer en utilisant le premier paramètre à chaque rappel comme un multiplicateur pour un délai initial. Comme ceci:

var duration = 5000; 

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

Ainsi le premier élément commencera à se fondre immédiatement. La seconde va se faner après 5000 ms. Le troisième après 10.000 ms et ainsi de suite. Gardez à l'esprit que cela fait semblant. Chaque élément n'attend pas réellement sur l'élément précédent pour finir.

+0

aaaahh c'est assez proche, merci. Et j'utilisais 1.3.2, je viens de recevoir la dernière version, merci de l'avoir signalé. Le seul problème avec celui-ci est qu'une fois que je fais les actions à $ ('.elem'), je pourrais vouloir tout recommencer. Je vais éditer la question pour refelct cela, aurait dû le mentionner, merci. – alan

+0

Je ne l'ai pas encore parfait, mais cela a répondu à ma question, merci beaucoup. – alan

0

Vous avez probablement besoin d'appeler attendre avant la première fonction:

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

L'autre option est d'utiliser la fonction de rappel.

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

De cette façon, le fadeOut ne démarre pas tant que le fadeIn n'est pas terminé.

+0

merci pour la réponse, mais l'ordre du fadeIn et évanouissements ne sont pas un problème, il est le fait que la boucle de .each appelle chacun d'entre eux à l'intérieur environ 0,3 d'une seconde, et fait tout cela en même temps, j'ai besoin de la boucle pour attendre le rappel. – alan

3

Votre boucle principale utilisant each() s'exécutera sans délai sur votre collection d'éléments. Vous devez mettre en file d'attente ces éléments à la place.

Cela pourrait avoir besoin peaufinage (et pourrait éventuellement utiliser des files d'attente jQuery?), Mais de démontrer à l'aide récursion pour traiter la file d'attente:

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

Je pense qu'un nombre inconnu d'éléments est bien pour cela parce que nous avons simplement 'shift()' l'élément suivant du tableau. Cela ne fonctionnera qu'une fois sur votre collection, puis se terminera. –

+0

shift ne semble pas fonctionner sur l'objet jquery, j'ai eu cette erreur: 'TypeError: 'undefined' n'est pas une fonction (évaluant 'elems.shift()')' – Matthieu

+0

Juste fondé la solution: use get(): ' var elems = $ ("elem"). get(); ' – Matthieu

0

Voici une démo de mon solution.

Ce dont vous avez besoin n'est pas une boucle pour gérer le traitement. Ce que vous voulez, c'est enchaîner les appels. On dirait qu'il pourrait y avoir un moyen plus simple, mais voici une méthode de force brute.

// 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

c'est une bonne idée, merci de poster. Ce code est bon :) – alan

Questions connexes