2010-10-19 47 views
1

Je suis en train d'écrire un script car je n'aime pas le fait qu'avec la plupart des scripts de sélection, lorsque le rectangle atteint le dernier objet (en utilisant un ul, donc le dernier li), il attend que item est hors écran, puis réinitialise la position de l'ul, et commence le défilement partout dans l'agian.Quel est le problème avec cette fonction récursion? (setTimeout issue)

Mon approche consiste à créer un clone de l'ul, à l'ajouter après l'ul actuel et à le lancer, puis à supprimer l'ul original une fois qu'il est complètement caché.

Cela fonctionne presque parfait, sauf pour une chose. Lorsque vous appelez la fonction, elle génère le temps requis pour setTimout. Ce setTimout est utilisé pour créer le nouvel UL et le mettre en mouvement.

Cela fonctionne bien pour la première boucle, mais ensuite glitch up.

Il est un peu difficile à expliquer, mais il semble que la deuxième fois que le délai d'attente devrait être appelé, au lieu d'attendre le temps, il appelle juste instantanément. S'il vous plaît voir http://webspirited.com/marquee.html pour un exemple

Pour un exemple de travail. Le code javascript est comme suit:

var count = 0; 
$('document').ready(function() { 
    //generate some random rows 
    for (var i = 0; i <= 20; i++) 
    $('.ulscroll').append('<li>Content ' + i + '</li>'); 
    //add one row so we can see its the last 
    $('.ulscroll').append('<li>Last Item</li>'); 

    //set the ul's width 
    var width = 0; 
    $('.ulscroll').children('li').each(function() { 
     width += $(this).outerWidth(); 
    }); 
    log('ul width: ' + width); 
    $('.ulscroll').width(width); 

    //activate the marquee    
    marquee('.ulscroll', 1, false); 
}); 

function marquee(id, speed, sub) { 
    //next two lines debugging purposes only 
    count += 1; 
    log('Marquee ran ' + count + ' times'); 

    //store copy of speed sent it(to pass for recursion) 
    var s1 = speed; 
    //set speed to 10* 
    speed = speed * 10; 

    //store parent width, and own width (if sub then add on width of parent div) 
    var pwidth = $(id).parent('div').outerWidth(); 
    var width = (sub ? $(id).width() + pwidth : $(id).width()); 

    //set timeout 
    var t = (width - pwidth) * speed; 
    setTimeout(function() { 
     var clone = $(id).clone().css('left', pwidth); 
     $(id).addClass('oldul'); 
     $(id).after(clone); 
     marquee(id + ':not(.oldul)', s1, true); 
    }, t); 

    $(id).animate({ 
     left: '-=' + width 
    }, width * speed, 'linear', function() { 
     $(this).remove(); 
    }); 
} 

function log(text) { 
    $('#log').append('<div>' + text + '</div>'); 
} 


Solution
Le problème a été provoqué par le passage du sélecteur avec: non (.ulold); Voici le setTimeout révisé

setTimeout(function(){ 
    var clone = $(id).clone().css('left', pwidth); 
    $(id).addClass('oldul'); 
    var idx = id.split(':'); 
    idx = idx[0]; 
    log('idx: '+idx); 
    $(idx).after(clone); 
    marquee(idx+':not(.oldul)', s1, true); 
},t); 
+0

Eh bien, ce n'est probablement pas le problème, mais "s1" devrait probablement être une variable locale ('var s1 = ...;'). – Pointy

+0

@pointy, Vous avez raison, sur les deux points :) – Hailwood

+0

Si vous voulez qu'une fonction soit exécutée à intervalles réguliers (enfin, aussi régulière que JS peut l'être), utilisez ['setInterval'] (https: //developer.mozilla .org/fr/DOM/window.setInterval), pas 'setTimeout'. – outis

Répondre

0

Le problème, très probablement, se trouve avec ce code ..

var clone = $(id).clone().css('left', pwidth); 
    $(id).addClass('oldul'); 

Le fait que vous réutilisez le sélecteur mess les choses parce que les matchs de sélection d'origine beaucoup de choses que le temps passe ..

Dans l'utilisation de l'appel initial marquee('.ulscroll:not(.oldul)', 1, false);

+0

vous aviez raison. après la deuxième fois, il deviendrait id: not (.ulold): not (.ulold); – Hailwood

+0

@Hailwood, j'ai fait une version plus simple pour vous à http://jsfiddle.net/MvkYU/ –

+0

Cheers! Mon code était en fait très approximatif car je n'obtenais que les bases de son déplacement correctement, mais vous m'avez sauvé un certain temps :) – Hailwood

0

Apprenez à utiliser un bon débogueur, s comme Firebug. Vous verrez que finalement le rappel de fin d'animation (celui qui supprime les éléments correspondant au sélecteur) est appelé avant la fonction de temporisation anonyme (celle qui appelle marquee).

Un problème avec le code sur la page exemple (mais pas dans le code affiché): tout est local à chaque appel de marquee. L'appel clearTimeout(tout) ne fait rien.

Enfin, s'il vous plaît ne pas utiliser un chapiteau. Il a usability problèmes: le texte en mouvement est plus difficile à lire, cause de la distraction, et se déplace toujours soit trop rapidement pour certains lecteurs, soit trop lentement pour certains lecteurs.

+0

Merci pour votre réponse, je n'ai pas rencontré le problème de la callback se faire appeler d'abord, également en ce qui concerne au chapiteau, je fais un clone complet du thème de twitter (ne vous embêtez pas à vous demander pourquoi) Mais, comme le thème de twitter utilise ce style de chapiteau, je dois aussi;) Je n'utiliserais jamais un chapiteau sur mes propres projets d'accord avec toi :) – Hailwood