[英]Dynamic Javascript Array .length
我想要做的是將新的“ .post”(已通過無限滾動腳本檢索到)推入包含所有“ .post”的數組中。
完整代碼: https : //gist.github.com/sxxfi/8296403
現場演示: http : //soof-show.tumblr.com (使用鍵盤箭頭鍵瀏覽帖子)
最初,五個“ .post”顯示在“ .content” div中,然后每次單擊“更多”按鈕時,都會在“ .content”中再添加五個“ .post”。
問題是數組長度不計入新的“ .post”,因此它會繼續循環第一個5。
如果能解決這個問題,請先謝謝您。
使用Javascript:
$(document).ready(function(){
// I N F I N I T E S C R O L L
$('.content').infinitescroll({
navSelector : ".navigation",
nextSelector : ".navigation .next_page",
itemSelector : ".content .post",
behavior: "twitter"
});
$(window).unbind('.infscr');
$('.next_page').click(function(){
$(document).trigger('retrieve.infscr');
return false;
});
$(document).ajaxError(function(e,xhr,opt){
if (xhr.status == 404) $('.next_page').remove();
});
// I M A G E S L I D E R
var obj = $(".post");
var arr = $.makeArray(obj);
var lastDiv = $(".post");
var indexNum = arr.length-1;
$(window).keydown(function (e) {
if (e.keyCode == 37) { // L E F T
lastDiv.fadeOut(800);
indexNum--;
if (indexNum == -1) indexNum = arr.length-1; //if goes beyond first post, goto the last post
$(arr[indexNum]).appendTo(".postslide").fadeIn(800);
// C E N T E R
var width = $(arr[indexNum]).width();
var marginLeft = width / 2;
$(arr[indexNum]).css('margin-left', -marginLeft);
}
if (e.keyCode == 39) { // R I G H T
$('#instruction').fadeOut();
lastDiv.fadeOut(800);
indexNum++;
if (indexNum == arr.length) indexNum = 0; //if goes beyond last post, goto the first post
$(arr[indexNum]).appendTo(".postslide").fadeIn(800);
// C E N T E R
var width = $(arr[indexNum]).width();
var marginLeft = width / 2;
$(arr[indexNum]).css('margin-left', -marginLeft);
}
});
});
更新:
$(document).ready(function(){
// I N F I N I T E S C R O L L
$('.content').infinitescroll({
navSelector : ".navigation",
// selector for the paged navigation (it will be hidden)
nextSelector : ".navigation .next_page",
// selector for the NEXT link (to page 2)
itemSelector : ".content .post",
// selector for all items you'll retrieve
behavior: "twitter"
});
// kill scroll binding
$(window).unbind('.infscr');
// manual click
$('.next_page').click(function(){
$(document).trigger('retrieve.infscr');
return false;
});
// remove the paginator done
$(document).ajaxError(function(e,xhr,opt){
if (xhr.status == 404) $('.next_page').remove();
});
// I M A G E S L I D E R
var obj = $(".post");
var indexNum = obj.length-1;
var lastDiv = $(".post");
$(window).keydown(function (e) {
if (e.keyCode == 37) { // L E F T
lastDiv.fadeOut(800);
indexNum--;
if (indexNum == -1) indexNum = obj.length-1; //if goes beyond first post, goto the last post
$(obj[indexNum]).appendTo(".postslide").fadeIn(800);
// C E N T E R
var width = $(obj[indexNum]).width();
var marginLeft = width / 2;
$(obj[indexNum]).css('margin-left', -marginLeft);
}
if (e.keyCode == 39) { // R I G H T
$('#instruction').fadeOut();
lastDiv.fadeOut(800);
indexNum++;
if (indexNum == obj.length) indexNum = 0; //if goes beyond last post, goto the first post
$(obj[indexNum]).appendTo(".postslide").fadeIn(800);
// C E N T E R
var width = $(obj[indexNum]).width();
var marginLeft = width / 2;
$(obj[indexNum]).css('margin-left', -marginLeft);
}
});
});
jQuery選擇器在調用jQuery函數時查詢DOM,因此它們在給定的時刻選擇與選擇器匹配的元素。
即使稍后將與選擇器匹配的新元素添加到DOM,也不會選擇它們,因為沒有任何內容通知jQuery重新評估選擇器,即使這樣做,jQuery也沒有內部狀態保存所有已創建的jQuery對象。 這意味着選擇器沒有激活 。
您的主要問題是,您永遠不會更新所選DOM元素的數組,因此即使將新元素添加到DOM中,您仍然會在原始數組上循環。
更新jQuery對象很容易,您只需在代碼中的任何時間調用obj = $(".post")
,並且obj
變量將被更新。 我們只需要弄清楚何時調用它。
由於您使用的是Infinite Scroll來加載新元素,因此我們需要查看它的文檔 ,或者由於文檔中目前存在大量漏洞,因此最好查看源代碼 。
看一下infinitescroll
函數:
$.fn.infinitescroll = function infscr_init(options, callback) {
...
第二個參數稱為callback
,在檢查源代碼以及該參數的傳遞和調用方式后,您可以看到它將在檢索到新元素之后被調用。 讓我們嘗試一下此參數:
$('.content').infinitescroll({
navSelector : ".navigation",
// selector for the paged navigation (it will be hidden)
nextSelector : ".navigation .next_page",
// selector for the NEXT link (to page 2)
itemSelector : ".content .post",
// selector for all items you'll retrieve
behavior: "twitter"
}, function () {
obj = $(".post");
console.log("Current length is: " + obj.length); //this line is not necessary, just here for debug purposes.
});
假設變量obj
已經存在,這將更新其值。
請注意,在此答案的先前版本中,我將此回調函數稱為recountPosts()
。 后來我決定,它只能是內聯匿名函數,因為它只能從一個地方調用。
您快要完成了,但是...根據此選擇器還有其他變量。 即arr
和lastDiv
。 在檢查您的源代碼后,似乎它們都不是必需的:
arr
是由jQuery對象選擇的元素組成的數組 ,盡管jQuery對象不是數組 ,但它具有從零開始的數字索引器和length屬性,就像數組一樣 ,因此您可以在代碼中的任何地方用obj
替換arr
。
lastDiv
的名稱具有誤導性。 它擁有與obj
相同的元素,而不僅僅是最后一個。 因此,它也可以用obj
代替。
因此,可以將聲明變量的部分縮小為:
// I M A G E S L I D E R
var obj = $(".post");
var indexNum = obj.length-1;
我還查看了您的keydown
事件處理程序。 里面有很多重復的代碼。 以后很容易引入錯誤(實際上您已經有一個錯誤:如果在開始時按左鍵而不是按右鍵,則鍵盤的初始圖像不會消失)。
讓我為您重組一下:
$(window).keydown(function (e) {
if (e.keyCode === 37) { // L E F T
indexNum--;
}
if (e.keyCode === 39) { // R I G H T
indexNum++;
}
if (e.keyCode === 37 || e.keyCode === 39) {
$('#instruction').fadeOut();
obj.fadeOut(800);
if (indexNum === -1) {
indexNum = obj.length-1; //if goes beyond first post, goto the last post
}
if (indexNum === obj.length) {
indexNum = 0; //if goes beyond last post, goto the first post
}
$(obj[indexNum]).appendTo(".postslide").fadeIn(800);
var width = $(arr[indexNum]).width();
var marginLeft = width / 2;
$(obj[indexNum]).css('margin-left', -marginLeft);
}
});
完成了!
不,當然沒有完成。 這還遠遠沒有完成,還有很多很多事情需要改進。
就像在每次按鍵時刪除丑陋的重新計算margin-left
並用幾行CSS來解決一樣。 經驗法則:如果可以使用CSS而不是javascript解決某些問題,則應該解決。
或者像在$(".postslide")
而不是$(".content")
infinitescroll(...)
上調用infinitescroll(...)
並從fadeIn()
之前刪除完全不必要的.appendTo(".postslide")
一樣,因為元素已經附加,重新附加它們是浪費資源。
或者將常量(例如800 ms的淡入長度)移動到代碼的開頭,為它們提供一個變量,例如var fadeLength = 800;
並使用它。
而且我很確定還有很多其他事情可以做得更好,但這就是編程的方式:)
因此,您還希望僅在幻燈片的末尾才顯示更多按鈕。 您已經寫了這個:
if (indexNum === 14){
$('.next_page').html('<img src="http://long_url/">');
}
為什么將14硬編碼到源代碼中? 您為什么還要關心要加載多少圖片以及將要加載多少圖片? 代碼的給定部分僅需要知道您是否最后。 如果您有關於要加載的幻燈片數量的變量,則可以輕松地檢查是否位於最后一個索引處。 您確實擁有該變量obj.length
:
if (indexNum === obj.length-1){
$('.next_page').html('<img src="http://long_url/">');
}
這樣,如果是30、45或9001st,則更多按鈕將出現在最后一張幻燈片上,而不再需要關注。
加載新內容后,您還需要此按鈕消失。 這進入了infinitescroll的回調:
function () {
obj = $(".post");
console.log("Current length is: " + obj.length); //this line is not necessary, just here for debug purposes.
$('.next_page').html('');
}
您可以做的另一件事是代替顯示more按鈕,而可以從代碼中觸發more事件。 這樣,當用戶到達最后一張幻燈片時,新幻燈片將自動加載。
同樣,只有在實際上有更多幻燈片要加載時才需要發生這種情況。 您可以檢查當前狀態的isDone
屬性, isDone
屬性會告訴您是否“無限滾動完成”,因此不再需要加載任何元素。
$('.content').data('infinitescroll').options.state.isDone === false
因此,除了顯示更多按鈕的部分,您可以編寫以下代碼:
if (indexNum === obj.length-1 && !$('.content').data('infinitescroll').options.state.isDone){
$(document).trigger('retrieve.infscr');
}
問題:
您要在頁面加載后立即設置值,而在滾動或其他鍵綁定時不更新它
解:
// I M A G E S L I D E R
var obj = $(".post");
var arr = $.makeArray(obj);
var lastDiv = $(".post:last");
var indexNum = arr.length-1;
$(window).keydown(function (e) {
obj = $(".post");
arr = $.makeArray(obj);
lastDiv = $(".post:last");
indexNum = arr.length-1;
//other code
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.