17

リストitmesのシンプルなメニューがあります。ULLI。LIの幅と数は動的です。また、ホバー/クリックで「もっと」ドロップダウンのようなものがあり、残りのLIが表示されますが、これは使用可能なスペースに収まりません。

ユーザーがウィンドウのサイズを右から左に変更しているときにjqueryを使用してみましたが、最後に表示されていたメニュー項目が非表示になります。この逆転を行い、「詳細」リンクにLIを追加するための可能な方法は何ですか。

サイズを変更すると幅が狭くなり、リストアイテムが下に移動し、ULの高さが高くなるため、いくつかのオプションを試しました。この方法を使用すると、最後に表示されたものを非表示にできます。コード

http://jsbin.com/flexmenu/2/edit

ステップ1

ウィンドウのサイズ変更

ステップ2ここに画像の説明を入力してください

ステップ3ここに画像の説明を入力してください

ユーザーがサイズを変更すると、これらの手順は逆になります(幅を大きくします)

マークアップ

<div class="twelve columns filter-wrapper">
    <ul class="nav-bar-filter" id="nav-bar-filter">
        <li><a href="#">All</a></li>
        <li><a href="#">Small</a></li>
        <li><a href="#">Medium</a></li>
        <li><a href="#">Extra large</a></li>
        <li><a href="#">Text</a></li>
        <li><a href="#">Small-1</a></li>
        <li><a href="#">Medium-1</a></li>
        <li><a href="#">Extra large text</a></li>
        <li><a href="#">Large text</a></li>
        <li><a href="#">Text</a></li>
    </ul>
<ul id="more-nav">
  <li><a href="#">More > </a>
    <ul class="subfilter"><li><a href="#">Text</a></li></ul>
  </li>    
</ul>
</div>

基本的に、このメニューはレスポンシブレイアウトメニューに使用されます。これに関するヘルプは役に立ちます。編集1:マークアップを追加

4

4 に答える 4

14

さて、私はそれを行うためのいくつかのスクリプトを作成しようとしました、これが私が持っているものです:

$().ready(function () { 

    //we reconstruct menu on window.resize
    $(window).on("resize", function (e) {                                                   
        var parentWidth = $("#nav-bar-filter").parent().width() - 40;
        var ulWidth = $("#more-nav").outerWidth();                  
        var menuLi = $("#nav-bar-filter > li");                 
        var liForMoving = new Array();      
        //take all elements that can't fit parent width to array
        menuLi.each(function () {                       
            ulWidth += $(this).outerWidth(); 
            if (ulWidth > parentWidth) {
                console.log(ulWidth);
                liForMoving.push($(this));
            }
        });                         
        if (liForMoving.length > 0) {   //if have any in array -> move them to "more" ul
            e.preventDefault();                     
            liForMoving.forEach(function (item) {
                item.clone().appendTo(".subfilter");
                item.remove();
            });                         
        }
        else if (ulWidth < parentWidth) { //check if we can put some 'li' back to menu
            liForMoving = new Array();
            var moved = $(".subfilter > li");
            for (var i = moved.length - 1; i >= 0; i--) { //reverse order
                var tmpLi = $(moved[i]).clone();
                tmpLi.appendTo($("#nav-bar-filter"));
                ulWidth += $(moved[i]).outerWidth();
                if (ulWidth < parentWidth) {                                
                    $(moved[i]).remove();
                }
                else {
                    ulWidth -= $(moved[i]).outerWidth();
                    tmpLi.remove();
                }                           
            }                       
        }                       
        if ($(".subfilter > li").length > 0) { //if we have elements in extended menu - show it
            $("#more-nav").show();
        }
        else {
            $("#more-nav").hide();
        }
    });

    $(window).trigger("resize"); //call resize handler to build menu right
});

そしてJSFiddleサンプル

それが正しく機能するようにあなたのcssスタイルを変更しなければなりませんでした。私たちがしていることは:

  1. 親コンテナの幅を取得widthします。メインメニューの初期値はゼロですが、おそらく追加メニューを表示する必要があるため、そのサイズも取得します。
  2. 次にwindow.resize、メインメニュー(水平)のすべての要素をループして、変数の各要素の幅を累積しulWidthます。
  3. widthメインメニューのが親コンテナの数を超えたら、width残りのメニュー項目をサブメニュー(垂直)に移動する必要があります。そのため、これらの要素を配列にプッシュしliForMovingます。
  4. 配列liForMoving 空でない場合は、その要素のクローンを作成し、サブメニューに追加して、メインメニューから削除します。
  5. widthのすべての要素の中でコンテナの幅よりも小さい場合mainMenuは、一部の要素をサブメニューからメインメニューに移動できるかどうかを確認する必要があります
  6. サブメニュー要素を繰り返し処理し、各項目を取得してメインメニューに追加し(メニューに異なるフォントとパディングがある場合-要素の最終的なサイズは異なります)、そのサイズが親コンテナーに適合するかどうかを確認します。そうである場合-サブメニュー($(moved[i]).remove())から要素を削除し、そうでない場合-追加された要素(tmpLi.remove())を削除します
  7. 最後に、サブメニューに項目があるかどうかを確認し、表示/非表示にします。
于 2013-03-19T12:49:06.453 に答える
11
$(document).ready(function () {
    var menu = $("#nav-bar-filter"),
        subMenu = $(".subfilter"),
        more = $("#more-nav"),
        parent = $(".filter-wrapper"),
        ww = $(window).width(),
        smw = more.outerWidth();

    menu.children("li").each(function () {
        var w = $(this).outerWidth();
        if (w > smw) smw = w + 20;
        return smw
    });
    more.css('width', smw);

    function contract() {
        var w = 0,
            outerWidth = parent.width() - smw - 50;
        for (i = 0; i < menu.children("li").size(); i++) {
            w += menu.children("li").eq(i).outerWidth();
            if (w > outerWidth) {
                menu.children("li").eq(i - 1).nextAll()
                    .detach()
                    .css('opacity', 0)
                    .prependTo(".subfilter")
                    .stop().animate({
                    'opacity': 1
                }, 300);
                break;
            }
        }
    }

    function expand() {
        var w = 0,
            outerWidth = parent.width() - smw - 20;
        menu.children("li").each(function () {
            w += $(this).outerWidth();
            return w;
        });
        for (i = 0; i < subMenu.children("li").size(); i++) {
            w += subMenu.children("li").eq(i).outerWidth();
            if (w > outerWidth) {
                var a = 0;
                while (a < i) {
                    subMenu.children("li").eq(a)
                        .css('opacity', 0)
                        .detach()
                        .appendTo("#nav-bar-filter")
                        .stop().animate({
                        'opacity': 1
                    }, 300);
                    a++;
                }
                break;
            }
        }
    }
    contract();

    $(window).on("resize", function (e) {
        ($(window).width() > ww) ? expand() : contract();
        ww = $(window).width();
    });

});

デモ

それを機能させるためにCSSを変更する必要がありました。メニューがその内容に関係なく応答するように、要素に静的な寸法を指定しませんでした。

仕組み:2つの関数がcontract()ありexpand()、ページの読み込みcontract()が呼び出されて追加のアイテムがサブメニューに移動するとき、ウィンドウのサイズが変更expand()されるときにウィンドウが拡大している場合は呼び出され、縮小している場合contract()は代わりに呼び出されます。

更新:右側にアニメーションを追加し、サブメニューの場所を修正しました。デモを参照してください。

于 2013-03-23T21:35:52.080 に答える
1

これを試してください:navバー内の切り捨てが必要な用語の数をjQueryに検出させます。次に、切り捨てられた用語の数に基づいてJavaScriptメソッドを使用してli要素をに追加します。たとえば、jQueryが5つの用語が切り捨てられたことを検出した場合は、次のコードを使用します。uldocument.createElement()

var truncated_elements = 5;
for (i=1; i<truncated_elements; i++){
    var new_li = document.createElement('li');
    new_li.innerHTML = "truncated_term";
    document.getElementsByTagName('ul')[0].appendChild(new_li);
}

上記のコードでは、jQueryは5つの要素を切り捨てる必要があることを認識し、切り捨てられた要素ごとにsをfor作成するループを実行します。liinnerHTMLnew_li、切り捨てられた要素のコンテンツに設定され(配列を使用する可能性があります)、[その他]サブメニューのにnew_li追加されます。ul

必要に応じてJSFiddle/JSBinを提供できます。

于 2013-03-14T21:25:17.577 に答える
1

フォーカス可能なアイテムのタブシーケンスを同じ順序に保つには、ドロップダウンメニューを逆にする必要があると思います。

アクセシビリティのために、セットサイズとセット内の位置を設定することもできます。アクセシビリティ上の理由から、移動した要素にフォーカスがあるときにフォーカスを複製されたアイテムにリセットし、setWaiAriaを追加してsetsizeとsetpositionを設定しました。そして、より多くのリンクにフォーカスがあり、消えたときに、フォーカスを最後のアイテムに設定します。フィドルを参照してください

$().ready(function () { 

  var setWaiAria = function(menuLi){
    menuLi.each(function (i,el) {
      var $el = $(el);
      $el.attr('aria-setsize',menuLi.length);
      $el.attr('aria-posinset',i+1);
    });
  }

  // set wai aria aria-setsize and aria-posinset before cloning elements in other list
  setWaiAria($("#nav-bar-filter > li"));

  //we reconstruct menu on window.resize
  $(window).on("resize", function (e) {                         
    var parentWidth = $("#nav-bar-filter").parent().width() - 40;
    var ulWidth = $("#more-nav").outerWidth();          
    var menuLi = $("#nav-bar-filter > li");         
    var liForMoving = new Array();
    var activeElement = $(document.activeElement)[0];

    // before remove item check if you have to reset the focus
    var removeOriginal = function(item,clone){
      // check focused element
      if(item.find('a')[0] === activeElement){
        activeElement = clone.find('a')[0];
      }

      item.remove();
    }

    //take all elements that can't fit parent width to array
    menuLi.each(function () {
      var $el = $(this);            
      ulWidth += $el.outerWidth(); 
      if (ulWidth > parentWidth) {
        liForMoving.unshift($el);
      }
    }); 

    if (liForMoving.length > 0) { //if have any in array -> move em to "more" ul
      e.preventDefault(); 

      liForMoving.forEach(function (item) {
        var clone = item.clone();
        clone.prependTo(".subfilter");

        removeOriginal(item, clone);
      });

    }
    else if (ulWidth < parentWidth) { //check if we can put some 'li' back to menu
      liForMoving = new Array();

      var moved = $(".subfilter > li");
      for (var i=0, j = moved.length ; i < j; i++) { 
        var movedItem = $(moved[i]);

        var tmpLi = movedItem.clone();
        tmpLi.appendTo($("#nav-bar-filter"));


        ulWidth += movedItem.outerWidth();
        if (ulWidth < parentWidth) {
          removeOriginal(movedItem, tmpLi);
        }
        else {
          // dont move back
          ulWidth -= movedItem.outerWidth();
          tmpLi.remove();
        }

      }
    }           
    if ($(".subfilter > li").length > 0) { //if we have elements in extended menu - show it
      $("#more-nav").show();
    }
    else {
      // check if 'more' link has focus then set focus to last item in list
      if($('#more-nav').find('a')[0] === $(document.activeElement)[0]){
        activeElement = $("#nav-bar-filter > li:last-child a")[0];
      }

      $("#more-nav").hide();
    }

    // reset focus
    activeElement.focus();
  });

  $(window).trigger("resize"); //call resize handler to build menu right
});
于 2015-04-06T12:17:43.013 に答える