2013-03-14 11 views
16

Istnieje proste menu z listami tematów. UL LI. szerokość i liczba LI jest dynamiczna. I jest rozwijany rodzaj rzeczy "więcej" po najechaniu/kliknięciu pokaże pozostały LI, który nie będzie pasował do dostępnej przestrzeni.Manipulowanie menu jquery na zmianę rozmiaru dla układu responsywnego

Próbowałem używać jquery, podczas gdy użytkownik zmienia rozmiar okna od prawej do lewej, ukryje ostatni widoczny element menu. Jaki jest możliwy sposób na wykonanie tego odwrócenia, a także dodanie LI w linku "więcej".

Wypróbowałem niektóre opcje, ponieważ szerokość jest mniejsza, gdy zmieniamy rozmiar, a następnie poruszamy się na liście i zwiększamy wysokość UL, więc używając tej metody, jestem w stanie ukryć ostatni widoczny. kod

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

Etap 1

resize of window

Etap 2enter image description here

Etap 3enter image description here

te kroki zostaną odwrócić, gdy użytkownik re-size (zwiększyć szerokość)

Markup

<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> 

Zasadniczo to menu będzie używany przez układ reagujący menu.Any pomoc w tym będzie pomocne. Edycja 1: dodano znacznik

+0

Czy możemy zobaczyć plik CSS? –

+0

Można to osiągnąć poprzez wzór "Responsive Design". – mukund

+1

Oczywiście. To cały punkt. On chce go użyć na responsywny projekt ... jest nawet oznaczony jako "responsive-design". –

Odpowiedz

9
$(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(); 
    }); 

}); 

DEMO

Musieliśmy zmodyfikować CSS, aby to działało. Nie podałem wymiarów statycznych dla żadnego elementu, aby menu reagowało bez względu na jego zawartość.

Jak to działa: istnieją tylko 2 funkcje contract() i expand(), gdy strona obciążenie contract() zostanie wywołana, aby przejść dodatkowe elementy do podmenu, gdy okno jest zmieniany, jeśli jest rozszerzenie expand() zostanie wywołana, a jeśli to zamawiający contract() będzie zamiast tego zadzwonił.

AKTUALIZACJA: dodana animacja i poprawione położenie podmenu po prawej stronie, zobacz wersję demo.

+0

Dzięki @razzak. Dołączę do mojego kodu. dziękuję za dodanie dwóch funkcji umowy i rozszerzenie. można go łatwo zarządzać. –

1

Spróbuj tego: Zrób jQuery, aby wykryć, ile terminów w polu nav musi zostać obciętych. Następnie dodaj elementy li do ul, stosując metodę JavaScript w oparciu o liczbę obciętych terminów. Na przykład, jeśli jQuery wykryje, że 5 terminy zostały obcięte, a następnie użyć następującego kodu:

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

w powyższym kodzie, jQuery by zorientować się, że 5 elementy muszą być obcięte i uruchomić for pętlę w którym tworzyłby li s dla każdego ściętego elementu. Wartość innerHTML z new_li zostanie ustawiona na zawartość obciętego elementu (prawdopodobnie przy użyciu tablicy), a następnie new_li zostanie dodany do ul w podmenu "Więcej".

Mogę dostarczyć JSFiddle/JSBin, jeśli to konieczne.

+0

Dzięki! Myślę, że to tylko doda te "LI" do "więcej" naraz. –

+0

W rzeczywistości pętla 'for' będzie nadal dodawać znaczniki" li' ". –

+0

W razie potrzeby mogę szczegółowo określić moją odpowiedź. Czy chciałbyś JSFiddle pokazując, jak można to osiągnąć? –

14

Cóż, starałem się budować jakiś skrypt, by to zrobić, oto co mam:

$().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 
}); 

I JSFiddle sample

musiał zmienić swoje style css, aby to działało poprawnie. Co możemy zrobić, to: szerokość

  1. wysiąść kontenera nadrzędnego, początkowe width z menu głównego wynosi zero, ale prawdopodobnie trzeba pokazać dodatkowe menu, dzięki czemu otrzymujemy jego wielkości, jak również.
  2. Na window.resize przechodzimy przez wszystkie elementy w głównym menu (poziome), gromadząc każdą szerokość elementu w zmiennej ulWidth.
  3. Gdy width głównego menu jest więcej niż width kontenera nadrzędnego -> musimy przenieść pozostałe elementy menu do podmenu (pionowego) - więc przesuniemy te elementy do tablicy liForMoving.
  4. Jeśli tablica liForMoving nie jest pusta - sklonujemy jej elementy, dołączamy je do podmenu i usuwamy z głównego menu.
  5. Jeśli width wszystkich elementów w mainMenu jest niewielka niż szerokość jego kontenera, musimy sprawdzić, czy możemy przenieść niektóre elementy z menu głównego jednej
  6. Mamy iterację elementów podmenu chwycić każdą pozycję, dołącz do menu głównego (jeśli masz różne czcionki i podpórki w menu - ostateczny rozmiar elementu będzie się różnić), sprawdź, czy jego rozmiar jest odpowiedni do dopasowania do pojemnika nadrzędnego. Jeśli to jest - usuwamy pierwiastek z podmenu ($(moved[i]).remove()), jeśli to nie - usuwamy elementy dołączone (tmpLi.remove())
  7. koniec sprawdzamy czy podmenu ma żadnych przedmiotów i pokaż/ukryj go.
+0

zaktualizował moją odpowiedź – Sergio

+0

Dzięki dzięki za demonstrację jsfiddle. Wygląda dobrze. Zintegruje i sprawdzi, czy działa w moim lokalnym. –

+0

tylko upewnij się, że twoje css jest poprawne, aby pokazać je tak, jak jest w moim skrzypcach (nawet bez kodu javascript). Miałem tam trochę ubrań, więc musiałem zmienić prawie wszystkie style: D – Sergio

1

Myślę, że rozwijane menu powinno zostać odwrócone, aby zachować sekwencję kart w fokusowalnych pozycjach w tej samej kolejności.

Dla ułatwienia można również ustawić rozmiar i położenie w zestawie. Ze względu na dostępność resetuję fokus do sklonowanej pozycji, gdy poruszony element miał fokus i dodano setWaiAria, aby ustawić stałą i ustawioną pozycję. Ustaw fokus na ostatni element, gdy więcej linku ma fokus i znika. zobacz fiddle

$().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 
}); 
+0

Zaktualizowałem przykład do skrzypiec z menu przełączania. Otwieranie menu, gdy dziecko z menu koncentruje się na: [skrzypce wersja 4] (http://jsfiddle.net/frontendplace/rvx26j1c/4/) –

Powiązane problemy