jQuery appendTo(),无需重新加载嵌入内容

时间:2016-03-03 17:21:42

标签: javascript jquery twitter

我用jQuery编写了一个堆栈函数,它接受容器元素.search-results,收集容器中每个.card元素中的所有.col元素,然后将它们重新堆叠在一起列,根据容器的宽度计算。

加载页面后,所有卡片都会在第一列中初始化,后续列将被隐藏。然后该脚本取消隐藏它确定应该存在的许多列并遍历列和卡,使用appendTo在列之间均匀分布卡片。

我创建了一个jsFiddle来演示这个过程。

在页面加载时调用脚本时效果很好。如果我想在页面加载后调用脚本,我遇到了一个严重的问题。如果我删除其中一张卡并想重新打包它们以使分布保持均匀,我必须再次调用堆叠功能。当我这样做时,它导致卡内的嵌入内容(例如嵌入的推文)被重新加载,这是不希望的。请注意,当页面加载时,直到调用堆叠功能之后才会初始化推文。

在我的示例中,我故意迭代推文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秒,然后再取出卡并重新打包。最后,一旦卡被重新打包,我重新初始化推文。最后一步是我想要避免的。我不想重新初始化推文,因为这是一个缓慢的过程。我希望移动卡后,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);

1 个答案:

答案 0 :(得分:0)

根据其他问题的答案,尝试更改:

SELECT   affid,
         COUNT (CASE type WHEN 'sale' THEN 1 END) AS sale,
         COUNT (CASE type WHEN 'refund' THEN 1 END) AS refund
FROM     salelist
GROUP BY affid

为:

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

或者你可以在 sortedCards.push({ rank: rank, element: $(this).clone(); }); $(this).detach(); 循环中进行克隆和分离:

appendTo