2013-03-14 12 views
16

C'è un menu semplice con gli elenchi di temi. UL LI. la larghezza e il numero di LI sono dinamici. E c'è una sorta di dropdown della cosa "more" su hover/click mostrerà la restante LI, che non si adatta allo spazio disponibile.Manipola menu jquery su ridimensionamento per layout reattivo

Ho provato a utilizzare jquery mentre l'utente ridimensiona le finestre da destra a sinistra, nasconderà l'ultima voce di menu visibile. Qual è il modo possibile per fare questo rovesciare e anche aggiungere LI in "più" link.

Provato qualche opzione, poiché la larghezza è inferiore quando ridimensioniamo quindi la voce di elenco si sposta sotto e aumenta l'altezza di UL, quindi con questo metodo sono in grado di nascondere l'ultimo visibile. codice

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

Fase 1

resize of window

Fase 2enter image description here

Fase 3enter image description here

Questi passaggi saranno retromarcia quando l'utente ripristina dimensioni (aumentare la larghezza)

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> 

Fondamentalmente questo menu viene utilizzato per il layout reattivo menu.Any aiuto in questo sarà utile. Modifica 1: markup aggiunto

+0

Possiamo vedere il file CSS? –

+0

Questo può essere ottenuto attraverso il modello 'Responsive Design'. – mukund

+1

Ovviamente. Questo è l'intero punto. Vuole usarlo per un design reattivo ... è persino etichettato come "responsive-design". –

risposta

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

dovuto modificare i CSS per farlo funzionare. Non ho dato quote statiche per nessun elemento in modo che il menu fosse reattivo indipendentemente dal suo contenuto.

Come funziona: ci sono semplicemente 2 funzioni contract() e expand(), quando la pagina carico contract() sarà chiamato a spostare gli elementi in più per sottomenu, quando la finestra viene ridimensionata se si sta espandendo expand() sarà chiamato e se è contrarre contract() sarà chiamato invece.

UPDATE: aggiunto animazione e posizione del sottomenu fisso a destra, vedere la demo.

+0

Grazie a @razzak. Includerà nel mio codice grazie per aver aggiunto due funzioni contratto ed espandere. può essere facilmente gestito. –

1

Prova questo: fai in modo che jQuery rilevi quanti termini nella barra nav devono essere troncati. Quindi aggiungere gli elementi li allo ul utilizzando il metodo JavaScript document.createElement() in base al numero di termini troncati. Ad esempio, se il jQuery rileva 5 termini sono stati troncati, quindi utilizzare il codice seguente:

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

Nel codice precedente, il jQuery sarebbe capire che 5 elementi devono essere troncato, ed eseguire un ciclo for in cui creerebbe li s per ciascun elemento troncato. Ildello new_li verrà impostato sul contenuto dell'elemento troncato (utilizzando eventualmente un array), quindi lo new_li verrà aggiunto allo ul nel sottomenu "Altro".

Posso fornire un JSFiddle/JSBin se necessario.

+0

Grazie! Penso che questo aggiungerà solo "LI" a "più" contemporaneamente. –

+0

In realtà, il ciclo 'for' continuerà ad aggiungere tag' li' se necessario. –

+0

Posso dettagliare la mia risposta più se necessario. Vorresti un JSFiddle che mostri come questo può essere realizzato? –

14

Beh, ho cercato di costruire qualche script per farlo, ecco quello che ho:

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

E JSFiddle sample

dovuto cambiare gli stili CSS per farlo funzionare correttamente. Quello che facciamo è: larghezza

  1. Get del contenitore principale, prima width del menu principale è pari a zero, ma probabilmente per visualizzare il menu supplementari, in modo da ottenere la sua dimensione pure.
  2. Su window.resize effettuiamo il ciclo di tutti gli elementi del menu principale (orizzontale) accumulando ciascuna larghezza dell'elemento nella variabile ulWidth.
  3. Una volta che il width del menu principale è più di width del contenitore genitore -> abbiamo bisogno di spostare il resto delle voci di menu nel sottomenu (verticale) - così spostiamo questi elementi su un array liForMoving.
  4. Se array liForMovingnon è vuoto - cloniamo i suoi elementi, li aggiungiamo al sottomenu e li rimuoviamo dal menu principale.
  5. Se width di tutti gli elementi in mainMenu è minore della larghezza del suo contenitore, dobbiamo controllare se possiamo spostare alcuni elementi del sottomenu a quella principale
  6. iteriamo elementi sottomenu, afferrare ogni elemento, accoda al menu principale (se si hanno diversi font e paddings nei menu - la dimensione finale dell'elemento sarà diversa), controllare se la sua dimensione è buona per adattarsi al contenitore genitore. Se è - togliamo elemento da sottomenu ($(moved[i]).remove()), se non è - togliamo elemento aggiunto (tmpLi.remove())
  7. Infine controllare se il sottomenu ha tutti gli elementi, e Mostra/Nascondi esso.
+0

aggiornato la mia risposta – Sergio

+0

Grazie grazie per la demo di jsfiddle. Sembra buono. Integrerà e vedrà se il suo lavoro nel mio locale. –

+0

assicurati che il tuo css sia corretto per mostrarlo come è nel mio violino (anche senza codice javascript). Ho avuto alcuni trilli lì, quindi ho dovuto cambiare quasi tutti gli stili: D – Sergio

1

Penso che il menu a discesa debba essere invertito per mantenere la sequenza di tabulazione in elementi focalizzabili nello stesso ordine.

Per l'accessibilità è anche possibile impostare il setize e la posizione nel set. Per motivi di accessibilità ho reimpostato lo stato attivo sull'elemento clonato quando l'elemento spostato era attivo e aggiunto setWaiAria per impostare il setize e impostare la posizione. E imposta lo stato attivo sull'ultimo elemento quando il collegamento più ha messo a fuoco e scompare. vedi 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

Aggiornamento dell'esempio di un violino con un menu di attivazione/disattivazione. Aprendo il menu quando un bambino del menu è focalizzato su: [fiddle versione 4] (http://jsfiddle.net/frontendplace/rvx26j1c/4/) –

Problemi correlati