3

ナビゲーションオーバーレイ(ノードとサブノード)を備えたレスポンシブWebサイトで作業しています。ナビゲーションは、デスクトップビューの場合は4列、タブレットビューの場合は2列に分割する必要があります。これはネストされたリストナビゲーションであるため、その<ul />周りに列が作成されます。私のアイデアは、ナビゲーションを1列に記述し、jqueryを使用して動的に4列または2列に配置することでした。

html:

<!-- overlay -->
<nav class="overlay"> 
    <!-- ul for column -->
    <ul>
        <!-- nodes & subnodes -->
        <li><a href="#">node</a>
            <ul>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
            </ul>
        </li>
        <li><a href="#">node</a>
            <ul>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>                    
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
            </ul>
        </li>
        <li><a href="#">node</a> ...
    </ul>
</nav>

私はこの関数を書きました:

    $.fn.arrangeObjects = function(wrapWith, maxCols) {

        this.each(function() {
            if ($(this).parent(wrapWith).length) $(this).unwrap();
        });

        this.parent().each(function() {
            var $el = $(this).children();
                amount = $el.length,
                wrapAmount = amount / maxCols;

            for (var i = 0; i < amount; i += wrapAmount) {
                $el.slice(i, i + wrapAmount).wrapAll('<'+ wrapWith +'/>');
            }
        });
    };

デスクトップ用に起動:

$(".overlay > ul > li").arrangeObjects('ul', 4);

タブレット用に解雇:

$(".overlay > ul > li").arrangeObjects('ul', 2);

このソリューションは、ノードを等しい部分に分割して列に分割します。残念ながら、この方法ではあまり見栄えがよくありません:http:
//bern09.ch/notgood.png

私が達成したいのは、次のように、ほぼ同じ列の高さで配置することです:http:
//bern09.ch/good.png

ある意味でサブノードの数を尊重する必要がありますが、それを実現する方法がよくわかりません。たぶん誰もが素晴らしいヒントを持っているので、少し助けていただければ幸いです。

4

2 に答える 2

3

何よりもまず、並べ替えとグループ化は、可能な限りバックエンドで行う必要があります。この状況ではそうです。

ULごとに結果を並べ替えてグループ化すると、ここで説明されている古いブラウザのjQueryフォールバックでCSS3列を使用できます。

.overlay {
    -moz-column-count: 4;
    -moz-column-gap: 10px;
    -webkit-column-count: 4;
    -webkit-column-gap: 10px;
    column-count: 4;
    column-gap: 10px;
}

ただし、すべてにJavaScriptを使用することを主張する場合は、Multi ColumnListjQueryプラグインを使用できます。
それはあなたが必要とする解決策を提供するようです。ただし、以前に作成されたため、おそらく最新のjQueryバージョンに合わせて一部を変更する必要があり、ニーズに合わせて少し変更する必要があります。

于 2012-12-27T23:41:05.450 に答える
3

Ok。私はそれを持っている。少しトリッキーでした。昨日、すべての列の高さを計算することから始めましたが、このアプローチはより柔軟であると思います。

    this.parent().each(function () {
        var $subnodes       = $(this).children();

        // true will cause counter increment
        // false will cause counter decrement
        var inc     = true;
        var cols    = [];

        for (var i = 0; i < maxCols; i++) {
            cols.push($('<ul></ul>'));
            cols[i].appendTo($(this));    
        }

        function sortByHeight(a, b) {
            return $(a).height() > $(b).height() ? 0 : 1;
        }

        $subnodes = $subnodes.sort(sortByHeight);

        var i = 0;
        $subnodes.each(function () {
            // logic for left and right boundry
            if (i < 0 || i === maxCols) {
                inc = !inc;
                // this will cause node to be added once again to the same column
                inc ? i++ : i--;
            }

            cols[i].append($(this));

            inc ? i++ : i--;
        });
    });

それはコンセプトです。まず、すべてのノードを高さ(最も高いものから最も低いものへ)で並べ替えてから、左から右、そして後ろに向かって列(maxColsで指定)に追加します。それはあなたのものほどきれいではなく、残念ながらwrapAllの使用法を壊します(私はそれがとても好きです)。私はすでにthresholdパラメータを使用する小さな最適化に取り組んでいます。最短の列と最長の列の高さの差がしきい値よりも大きい場合、最長の列の最後の要素が最短の列に移動します。それならもっと自然に見えるはずです。これがあなたが探しているものであるかどうか私に知らせてください。

于 2012-12-28T22:52:53.760 に答える