Javascript jQuery appendTo()而不重新加载嵌入内容

Javascript jQuery appendTo()而不重新加载嵌入内容,javascript,jquery,twitter,Javascript,Jquery,Twitter,我用jQuery编写了一个堆叠函数,它接受容器元素。搜索结果,收集容器中每个.col元素中的所有.card元素,然后跨多个列重新锁定它们,这些列是根据容器的宽度计算的 加载页面时,所有卡在第一列中初始化,后续列隐藏。然后,脚本取消隐藏它确定应该存在的列的数量,并使用appendTo在列和卡片之间迭代,以便将卡片均匀分布 我创建了一个演示该过程的示例 当在页面加载时调用脚本时,它工作得非常好。如果我想在页面加载后调用脚本,我会遇到一个严重的问题。如果我移除其中一张卡,并希望重新打包它们,以便分布保

我用jQuery编写了一个堆叠函数,它接受容器元素
。搜索结果
,收集容器中每个
.col
元素中的所有
.card
元素,然后跨多个列重新锁定它们,这些列是根据容器的宽度计算的

加载页面时,所有卡在第一列中初始化,后续列隐藏。然后,脚本取消隐藏它确定应该存在的列的数量,并使用
appendTo
在列和卡片之间迭代,以便将卡片均匀分布

我创建了一个演示该过程的示例

当在页面加载时调用脚本时,它工作得非常好。如果我想在页面加载后调用脚本,我会遇到一个严重的问题。如果我移除其中一张卡,并希望重新打包它们,以便分布保持均匀,我必须再次调用堆叠函数。当我这样做时,会导致卡中的嵌入内容(例如嵌入Tweets)被重新加载,这是不可取的。请注意,当页面加载时,tweet在调用stacking函数之后才会初始化

在我的示例中,我故意使用
twttr.widgets.createTweet()
对tweet ID进行迭代,以重新初始化它们,但是如果我忽略了该步骤,则在重新标记卡后tweet将消失。如果我检查这些卡,我可以看到Tweet小部件iframe仍然存在,但是iframe的
主体
是空的

现在很明显,我可以在重新打包卡片后简单地重新初始化我的Tweet,但这会提供糟糕的用户体验,因为(重新)初始化嵌入式Tweet时会有延迟。我之前曾提出过与此相关的建议。我发现我可以使用
.clone()
appendTo()
从控制台手动移动卡片,而无需重新加载嵌入的tweet,但是我没有幸重构堆叠函数来利用这种行为,这就是我问这个问题的原因

这是我的堆叠功能:

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;
    }
}
在调用
resizeColumns
函数后,我在第一次初始化tweet之前设置了一个延迟。这对于twitterwidgets脚本能够在DOM中定位Tweets是至关重要的

一旦Tweets被初始化,我设置了一个4s的延迟,然后移除一张卡并重新打包卡。最后,一旦卡片重新打包,我会重新初始化推文。这最后一步是我想要避免的。我不想重新初始化tweet,因为这是一个缓慢的过程。我希望推特在移动卡片后立即重新出现

$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);

根据另一个问题的答案,尝试更改:

    sortedCards.push({
        rank: rank,
        element: $(this)
    });
致:

或者您可以在
appendTo
循环中执行克隆和分离:

for (var i in sortedCards) {
    var cardElem = sortedCards[i].element.clone();
    cardElem.appendTo($(cols[curCol]));
    sortedCards[i].element.detach()
    curCol = (curCol + 1) % numCols;
}

关于如何将
.clone()
应用于函数,我有相同的想法,但我无法让它工作。在小提琴上测试,在第二次调用该函数后,tweet仍然消失。也就是说,我必须重新初始化它们,这是我想要避免的。我将我的代码添加到你的小提琴中,如何使它再次调用函数?我刚刚更新了我的问题,更清楚地解释了我堆叠/重新堆叠卡的步骤。让我知道这是否合理。我认为超时函数中的
detach()
是问题所在。为什么在调用
resizeColumns
之前需要这样做?我正在使用它来模拟用户隐藏其中一张卡。在我的实际应用程序中,这些卡有一个按钮来隐藏它们。这样做会切换一个布尔属性,该属性通过连接到该卡的
ng if
块将该卡从DOM中移除。我不想尝试复制小提琴中的所有附加功能,所以我只使用了
.detach()
。当然,我确实在实际的应用程序上测试了您的代码,但其行为与在fiddle中相同。
    sortedCards.push({
        rank: rank,
        element: $(this).clone();
    });
    $(this).detach();
for (var i in sortedCards) {
    var cardElem = sortedCards[i].element.clone();
    cardElem.appendTo($(cols[curCol]));
    sortedCards[i].element.detach()
    curCol = (curCol + 1) % numCols;
}