2009-09-22 5 views
2

j'ai le javascript ci-dessous après je termine une requête ajaxboucle javascript que l'application à tous les autres éléments

toutes mes images ont name = "pic"

<script type="text/javascript"> 
function done() { 
    var e = document.getElementsByName("pic"); 
    alert(e.length); 
    for (var i = 0; i < e.length; i++) { 
     cvi_instant.add(e[i], { shadow: 75, shade: 10 }); 
    } 
} 

mon objectif est d'appliquer une bordure d'image autour de l'utilisation de cette bibliothèque:

http://www.netzgesta.de/instant/

le problème est que, pour une raison ou une autre, cela fonctionne, mais cela ne semble s'appliquer qu'à toutes les autres images au lieu de toutes les autres. aucune idée pourquoi le code ci-dessus sauterait tous les autres éléments ??

EDIT: J'ai ajouté une alerte dans la boucle et ça va correctement 0, 1,2,3,4,5,6. .

 for (var i = 0; i < e.length; i++) 
    { 
     alert(i); 
     cvi_instant.add(e[i], { shadow: 75, shade: 10 }); 
    } 
+1

Je vais faire une réclamation extravagante (et peut-être follement inexacte). C'est parce que ce code (cvi_instant.add) utilise aussi une variable nommée 'i'. Essayez d'appeler votre variable 'k'. –

+1

Cela devrait être inexact. "i" est déclaré avec "var" donc ce n'est pas global, et les nombres ne sont pas passés par référence. Cependant, s'il y avait un autre "i" déclaré globalement, il pourrait y avoir un problème. – Glenn

+1

Essayez d'alerter "i" avant la boucle (par exemple, avec la longueur d'e.length) et dites-nous de quoi il s'agit. En outre, essayez l'extension firebug pour firefox afin que vous puissiez réellement déboguer et parcourir le code. Cela rendra les choses plus claires pour vous. – Glenn

Répondre

7

il semble que d'appliquer à tous les autres image au lieu de tous

C'est un signe classique d'itération destructrice.

Considérons ce qui se passe si, comme je le devine, la fonction cvi_instant.add remplace l'élément nommé pic par d'autres éléments ou éléments.

getElementsByName renvoie un NodeList 'live': il est mis à jour chaque fois que vous apportez une modification au DOM. Donc s'il avait cinq éléments avant, après votre appel à cvi_instant.add il n'en contient plus que quatre: le premier nœud est parti et les nœuds 1-4 sont descendus aux positions 0-3.

Maintenant vous faites de nouveau le tour de la boucle.i++, donc nous regardons l'élément 1. Mais l'élément 1 est maintenant ce qui était à l'origine l'élément 2! Nous avons sauté l'élément d'origine 1, et nous continuerons à sauter tous les autres éléments jusqu'à ce que nous atteignions la fin de la liste (maintenant deux fois moins longue).

Modifier une liste en même temps que l'itérer provoque ce type de problème. Si le processus à l'intérieur de l'itération ajoute éléments à la liste, vous pouvez même obtenir une boucle infinie!

La solution rapide consiste à répéter la boucle vers l'arrière. Maintenant, vous faites le dernier élément premier, laissant tous les autres éléments dans leur position d'origine et ne provoquant pas skipping:

var e= document.getElementsByName("pic"); 
for (var i= e.length; i-->0;) { 
    cvi_instant.add(e[i], { shadow: 75, shade: 10 }); 
} 

Une autre solution simple si vous savez vous allez toujours à retirer l'élément de la liste sur chaque appel est:

var e= document.getElementsByName("pic"); 
while (e.length>0) { 
    cvi_instant.add(e[0], { shadow: 75, shade: 10 }); 
} 

la solution la plus générale est nécessaire lorsque votre corps de la boucle peut faire quoi que ce soit à la liste, telles que l'insertion de nouveaux éléments nommés pic au début du document ou de la suppression d'autres éléments de la milieu . Il est légèrement plus lent mais toujours sûr de faire une copie statique de la liste à partir de:

function Array_fromList(l) { 
    var a= []; 
    for (var i= 0; i<l.length; i++) 
     a.push(l[i]); 
    return a; 
} 

var e= Array_fromList(document.getElementsByName("pic")); 
for (var i= 0; i<e.length; i++) { 
    cvi_instant.add(e[i], { shadow: 75, shade: 10 }); 
} 
+0

merci pour vos commentaires. . Avez-vous une suggestion pour un correctif ici? – leora

+1

(ajouté quelques approches) – bobince

+0

itérer à l'envers est une «solution» intéressante - je l'aime plutôt! – TML

1

Je pense que cvi_instant.add() est en train de faire une itération incrémenter ou sur les valeurs qui lui sont transmises. Essayez de faire cela au lieu - il est plus facile, et je crois qu'il va résoudre votre problème:

function done() { 
    var e = document.getElementsByName('pic'); 
    for (pic in e) { cvs_instant.add(pic, { shadow: 75, shade: 10 }); } 
} 
+0

quand je l'ai changé pour cela. . la fonction javascript ne se termine jamais et aucune de mes photos ne reçoit la mise à jour ... des idées? – leora

+0

La boucle "for/in" sur un groupe * peut poser des problèmes si vous avez ajouté des méthodes au prototype de groupe (par exemple, .bind à partir de prototype.js). "pic" finirait par être une fonction parfois. – Glenn

+0

Notez que j'ai épelé "cvi_instant" mal dans mon échantillon :) Pouvez-vous nous fournir le corps de "cvi_instant" afin que nous puissions voir mieux ce qui se passe? – TML

0

- EDIT:

Tout ce que je demande ci-dessous semble être tout à fait tort. Je laisse ceci ici comme un point pour tous ceux qui pensaient la même chose :) J'ai testé en FF3. J'aimerais affirmer que j'ai vu ce comportement une fois, dans IE, mais peut-être que c'était il y a plusieurs années (pensez-y, c'était il y a probablement 7 ans). Ma mémoire est probablement mal :)

- VIEUX:

Pour développer un peu sur ma conjecture sauvage, si elle se révèle être précis:

De mémoire, si vous ne déclarez pas une variable ('var ...') il en utilisera un ailleurs.

Ainsi, sans essai, ce code:

for(var k = 0; k < 2; k++){ 
    f(); 
    alert("k: " + k); 
} 

function f() { 
    k++; 
} 

doit afficher le même comportement. Je pense que la solution de TML est plutôt sympa, du point de vue du «codage défensif», mon analyse s'avère correcte.

1

Salut J'ai rencontré le même problème. Mon script ignorait tous les autres éléments . J'ai finalement résolu le problème en changeant le nom de la variable de 0 à k dans ma boucle. Ma supposition est donc que la variable i est utilisée par getElementsByTagName en interne à garder une trace de l'endroit où il est dans la nodelist live et fuit à l'interface de programmeurs en quelque sorte. Donc c'est un bug! :-)

Questions connexes