2010-10-19 80 views
1

我正在寫一個選取框腳本,因爲我不喜歡大多數選取框腳本當選取框到達最後一項(使用ul,所以最後一個項目是最後一個項目)的事實,它會等到項目不在屏幕上,然後重新設置ul的位置,並開始全方位滾動。這個函數遞歸有什麼問題? (setTimeout issue)

我的方法是創建一個ul的克隆,將它追加到當前的ul之後,並開始滾動,然後刪除原來的ul,一旦它完全隱藏。

除了一件事之外,這個工作幾乎完美。當您調用該函數時,它會生成setTimout所需的時間。該setTimout用於創建新的UL並將其設置爲移動。

這適用於第一個循環,但然後小毛病。

這是有點難以解釋,但它似乎在第二次超時應該被調用,而不是等待時間,它只是立即調用自己。例如,請參閱http://webspirited.com/marquee.html

對於一個工作示例。 JavaScript代碼如下:

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>'); 
} 



這件事是通過在與通過選擇器引起的:不是(.ulold); 下面是修改後的setTimeout

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

那麼這可能不是問題,但「s1」應該可能是一個局部變量('var s1 = ...;')。 – Pointy 2010-10-19 14:01:46

+0

@pointy,你是正確的,在這兩個方面:) – Hailwood 2010-10-19 14:04:09

+0

如果你想定期執行一個函數(當然,像JS可以得到的那樣),使用['setInterval'](https://developer.mozilla .org/en/DOM/window.setInterval),而不是'setTimeout'。 – outis 2010-10-19 14:11:12

回答

0

的問題,最有可能的,在於這個代碼..

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

您重新使用選擇的事實弄亂的東西了,因爲原來的選擇匹配很多東西隨着時間的推移..

在初始呼叫使用marquee('.ulscroll:not(.oldul)', 1, false);

+0

你是對的。 第二次後它會變成id:not(.ulold):not(.ulold); – Hailwood 2010-10-19 14:20:09

+0

@Hailwood,我在http://jsfiddle.net/MvkYU/ – 2010-10-19 15:32:05

+0

爲你做了一個更簡單的版本乾杯!我的代碼實際上是非常粗糙的,因爲我只是得到它的基本移動正確,但是你已經節省了我一些時間:) – Hailwood 2010-10-19 17:17:08

0

學會用良好的調試器,S如Firebug。您將看到最終動畫結束回調(刪除與選擇器匹配的元素)會在匿名超時函數(調用marquee)之前被調用。

樣本頁面上的代碼存在問題(但不是在發佈的代碼中):tout對於每個調用marquee都是本地的。 clearTimeout(tout)調用不做任何事情。

最後,請不要使用選取框。它有usability問題:移動文本難以閱讀,導致分心,並且對於某些讀者而言,移動文本總是會太快,或者對於某些讀者移動太慢。

+0

Thankyou爲您的答案,我還沒有遇到回調問題先獲得調用,也與問候到大帳篷,我做了一個完整的嘰嘰喳喳主題克隆(不要問爲什麼)但是,由於Twitter主題使用這種字幕的風格,所以我必須;)我永遠不會在我自己的項目上使用一個字幕作爲我完全同意你 :) – Hailwood 2010-10-19 17:16:23