0

基本的に、私は無限ループを取得しています。おそらく私は一生懸命働きすぎていますが、その理由はわかりません.


環境:

カルーセル(Bootstrap's)を使用しています。カルーセルのコンテンツが生成され、1 つのカルーセルスライドにプッシュされます。次に、内部のアイテムの数が特定の事前定義された max-length プロパティ ( ) を超える場合、コンテンツを取得して複数のスライドに分割することが目標です5。カルーセルの特定のユース ケース (表の行が 5 つを超える場合、表が複数のスライドにまたがっている場合) ではうまく機能しますが、十分に一般的ではありません。何が起こったのかというと、JS がオーバーフローしたテーブル行 (つまり、インデックス 5 以上) を取得し、関数内のハードコーディングされた HTML 文字列から新しいスライドを作成し (まだ空のテーブルのすべてのマークアップを含むスライドdiv)、それらをプッシュします。追加の行を追加します。

より一般的にするために、説明した場合にandに適用されるcarousel_common_listandのようなクラスを使用することにしました。次に、分離された方法でテンプレートを処理する必要があります。私が試みたのは、元の唯一のスライドのクローンを作成し、 を空にして、オーバーフローした s をそれにプッシュする、などです。しかし、私は無限ループを取得します。carousel_common_itemtbodytrcarousel_common_listcarousel_common_item


コード

これまでスライドと呼んできたものは、コード内でアイテムと呼ばれます (Bootstrap のカルーセルのスライドitemのクラスと一致させるため)。

var carousels = $('div.carousel'),
    carouselCommonListClass = 'carousel_common_list',
    carouselCommonItemClass = 'carousel_common_item',
    items_per_slide = 5;

$.each(carousels, function (index, element) {//for each carousel

    var $carousel = carousels.eq(index),
        $items = $carousel.find('.item');

    var getItemTemplate = function ($item) {
        $copy = $item.clone();//take the html, create a new element from it (not added to DOM)
        $copy.find('.' + carouselCommonListClass).empty();
        $copy.removeClass('active');
        return $copy;
    }


    var splitUpItem = function ($item, $itemTemplate) {
        var $bigList = $item.find('.' + carouselCommonListClass), group;
        while ((group = $bigList.find('.' + carouselCommonItemClass + ':gt(' + (items_per_slide - 1 ) + ')').remove()).length) {
            var $newItem = $itemTemplate;
            $newItem.find('.' + carouselCommonListClass).prepend(group);
            $newItem.insertAfter($item);
            splitUpItem($newItem, $itemTemplate);//infintely called
        }
    }

    //foreach item
    $.each($items, function (item_index, item_element) {//for each slide, in each carousel

        var $item = $items.eq(item_index);

        splitUpItem($item, getItemTemplate($item));
    });
});

参考までに、これは でマークされた行//infintely calledがコメントアウトされている場合に期待どおりに機能します。つまり、1 つの特大のスライドを 1 つのitems_per_slide長さのスライドと別のスライドに分割します (items_per_slide元のソール スライドの長さが長すぎると、長さが長くなる可能性がありますitems_per_slide * 2

また、私はこの回答を取り、の内容に合わせて修正しましたsplitUpItem()


ノート:

私のようにテーブルやリストなどを複数のスライドに分割するのが最も使いやすく、アクセスしやすいソリューションではないことはわかっていますが、より良いアイデアがある場合は、それに関する私の未解決の質問に答えてください。

4

1 に答える 1

0

同じループで無限に立ち往生していないという点で、それ自体が無限ループになっているわけではありませんwhile。あなたが言及したように、//infinitely called行を削除すると問題ありません。その while ループを最初に通過すると、計算される長さgt:(4)は、$item のすべてのリスト内の ( を含む) アイテムの数に等しくなります。次に、これらの項目をすべて削除すると、次のパススルーでその番号が 0 になります。これは常にそのループの動作であるため、実際にはループである必要はありませんが、それは主な問題ではありません。

問題は、それが再帰呼び出しであることです。そして、再帰呼び出しを無限にすることに対する唯一のガードは while ループの条件ですが、その条件は常に最初のパススルーで満たされます。実際、$item に 5 つのリストがあり、それぞれに が含まれる 3 つのアイテムがgt:(4)ある場合、$newItem には 5 つのリストがあり、それぞれに 5 x 3 = 15 のアイテムがあります。したがって、splitUpItem$newItem で gets が呼び出されると、while ループの条件は再びゼロ以外になります。そして再び呼び出され、その数は 5 x 15 = 75 になります。言い換えれば、この関数を再帰的に呼び出しており、この呼び出しが無限に何度も行われないようにするには、いくつかの数値が 0 であることを確認しますが、その数値は の再帰呼び出しごとに実際には指数関数的に増加しますsplitUpItem

「無限ループ」の理由についての質問に答えてくれることを願っています。仕事を始めなければならないが、明日までにスライドを分割するより良い方法を提案しようと思う.

于 2012-09-28T14:50:23.023 に答える