【发布时间】:2016-03-04 02:34:55
【问题描述】:
我用 jQuery 编写了一个堆叠函数,它采用容器元素 .search-results,收集容器中每个 .col 元素中的所有 .card 元素,然后将它们重新堆叠到多个列中,这些列是根据计算得出的离开容器的宽度。
页面加载时,第一列中的所有卡片都被初始化,随后的列被隐藏。然后,脚本会取消隐藏它确定应该存在的许多列,并遍历列和卡片,使用 appendTo 在列之间均匀分布卡片。
我创建了一个 jsFiddle 来演示该过程。
在页面加载时调用该脚本时效果很好。如果我想在页面加载后调用脚本,我会遇到一个严重的问题。如果我移除其中一张卡片并想重新堆叠它们以保持分布均匀,我必须再次调用堆叠函数。当我这样做时,它会导致重新加载卡片中的嵌入内容(例如嵌入的推文),这是不可取的。请注意,当页面加载时,Tweets 直到调用 stacking 函数后才会初始化。
在我的示例中,我有意迭代推文 ID 以使用 twttr.widgets.createTweet() 重新初始化它们,但是如果我省略该步骤,则推文会在卡片重新堆叠后消失。如果我检查卡片,我可以看到 Tweet 小部件 iframe 仍然存在,但 iframe 的 body 是空的。
现在显然我可以在重新堆叠卡片后简单地重新初始化我的推文,但这会提供糟糕的用户体验,因为在(重新)初始化嵌入式推文时会有延迟。我之前曾提出过与此相关的question。我发现我可以使用.clone() 和appendTo() 从控制台手动移动卡片而无需重新加载嵌入式推文,但是我没有运气重构我的堆叠功能来利用这一点行为,这就是我问这个问题的原因。
这是我的堆叠功能:
function resizeColumns(layoutElem, ignoreRank, width) {
if (width === undefined) {
var colMin = 300;
} else {
var colMin = width;
}
var w = layoutElem.width();
var numCols = Math.floor(w / colMin);
if (numCols === 0) numCols = 1;
layoutElem.removeClass('cols-1 cols-2 cols-3 cols-4 cols-5 cols-6 cols-7 cols-8 cols-9 cols-10 cols-11 cols-12');
layoutElem.addClass('cols-' + numCols);
var cols = layoutElem.find('.col');
var cards = cols.find('.card');
var sortedCards = [];
cards.each(function(i) {
var rank;
if (!ignoreRank) {
rank = parseInt($(this).attr('rank'));
if (isNaN(rank)) rank = 1000000;
} else {
var o = parseInt($(this).attr('order'));
if (isNaN(o)) {
rank = i;
$(this).attr('order', i);
} else {
rank = o;
}
}
sortedCards.push({
rank: rank,
element: $(this)
});
});
sortedCards.sort(rankCompare);
var curCol = 0;
for (var i in sortedCards) {
var cardElem = sortedCards[i].element;
cardElem.appendTo($(cols[curCol]));
curCol++;
if (curCol >= numCols) curCol = 0;
}
// hide any additional columns
cols.each(function(i) {
if (i >= numCols) {
$(this).hide();
} else {
$(this).show();
}
});
function rankCompare(a, b) {
if (a.rank < b.rank)
return -1;
if (a.rank > b.rank)
return 1;
return 0;
}
}
我在 jsFiddle 中堆叠卡片和初始化推文的步骤
第一次调用该函数时,我引入了一个延迟,以便定义 $scope.cards。这是第一个电话:
$timeout(function() {
// Only the first argument is required.
resizeColumns($('.cards'), true, 250);
}, 250)
在我调用resizeColumns 函数后,我在第一次初始化推文之前设置了一个延迟。这是必不可少的,以便 Twitter 小部件脚本可以在 DOM 中定位推文。
推文初始化后,我将延迟设置为 4 秒,然后再取出卡片并重新堆叠卡片。最后,一旦重新堆叠卡片,我就会重新初始化推文。最后一步是我想要避免的。我不想重新初始化推文,因为这是一个缓慢的过程。我希望卡片移动后立即重新出现推文。
$timeout(function() {
// Iterate over the Tweet IDs and initialize them.
ids.forEach(function(id) {
twttr.widgets.createTweet(id, document.getElementById(id));
});
$timeout(function() {
// Wait a few seconds and then remove a card from the DOM.
$('#' + $scope.cards[1].id).detach();
// Restack cards
resizeColumns($('.cards'), true, 250);
$timeout(function() {
// Reinitialize Tweets after cards have been restacked. This is the step I want to avoid.
ids.forEach(function(id) {
twttr.widgets.createTweet(id, document.getElementById(id));
});
}, 500)
}, 4000);
}, 1000);
【问题讨论】:
标签: javascript jquery twitter