2013-03-14 9 views
16

Es gibt einfache menü mit liste itmes. UL LI. Breite und Anzahl von LI ist dynamisch. Und es gibt Drop-Down-Art der Sache "mehr" auf den Mauszeiger/Klick wird die verbleibende LI angezeigt, die nicht Platz passt.manipulieren jquery menu auf re-size für responsive layout

Ich versuchte mit jQuery während Benutzer Fenster von rechts nach links Größe ändern, es wird den letzten sichtbaren Menüpunkt ausblenden. Was ist der mögliche Weg, um diese Umkehr zu tun und auch LI in "mehr" Link hinzuzufügen.

Ich habe eine Option versucht, da die Breite geringer ist, wenn wir die Größe ändern, dann den Listeneintrag nach unten verschieben und die Höhe von UL erhöhen, so dass ich die letzte sichtbare ausblenden kann. Code

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

Schritt 1

resize of window

Schritt 2enter image description here

Schritt 3enter image description here

Diese Schritte werden umgekehrt werden, wenn der Benutzer der Größe neu bestimmen (die Breite erhöhen)

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> 

Grundsätzlich wird dieses Menü für ansprechendes Layout menu.Any Hilfe in dieser hilfreich sein wird verwendet werden. Edit 1: Markup hinzugefügt

+0

Können wir bitte die CSS-Datei sehen? –

+0

Dies kann durch 'Responsive Design' Muster erreicht werden. – mukund

+1

Offensichtlich. Das ist der ganze Punkt. Er will es für ein responsives Design verwenden ... es ist sogar mit "Responsive-Design" getaggt. –

Antwort

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

Hatte CSS zu ändern, damit es funktioniert. Ich habe keine statischen Dimensionen für jedes Element angegeben, so dass das Menü unabhängig vom Inhalt reagiert.

Wie es funktioniert: gibt es nur zwei Funktionen contract() und expand(), wenn Laden der Seite contract() werden zusätzliche Elemente Untermenü zu bewegen aufgerufen werden, wenn das Fenster verkleinert wird, wenn es expand() ist erweitert wird aufgerufen, und wenn es contract() des Vertrags wird stattdessen angerufen.

UPDATE: hinzugefügt Animation und festen Untermenü Ort auf der rechten Seite, siehe die Demo.

+0

Danke @razzak. Wird in meinem Code enthalten sein. Danke für das Hinzufügen von zwei Funktionen Vertrag und erweitern. es kann leicht verwaltet werden. –

1

Versuchen Sie Folgendes: Haben Sie Ihre jQuery erkennen, wie viele Begriffe in der nav bar abgeschnitten werden müssen. Fügen Sie anschließend li Elemente zur ul hinzu, indem Sie die JavaScript-Methode document.createElement() basierend auf der Anzahl der abgeschnittenen Begriffe verwenden. Zum Beispiel, wenn Ihre jQuery feststellt, dass fünf Bedingungen abgeschnitten worden sind, verwenden Sie dann den folgenden Code ein:

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

In dem obigen Code würde Figur die jQuery, dass 5 Elemente abgeschnitten werden müssen, und führen Sie eine for Schleife in dem es li s für jedes abgeschnittene Element erstellen würde. Die innerHTML der new_li würde auf den Inhalt des abgeschnittenen Elements gesetzt werden (unter Verwendung eines Arrays möglicherweise), und dann würde new_li an die im Untermenü "Weitere" angehängt werden.

Ich kann ein JSFiddle/JSBin bei Bedarf bereitstellen.

+0

Danke! Ich denke, das wird nur diese "LI" zu "mehr" auf einmal hinzufügen. –

+0

Tatsächlich fügt die 'for'-Schleife nach Bedarf weitere li-Tags hinzu. –

+0

Ich kann meine Antwort mehr detailliert, wenn nötig. Möchten Sie, dass ein JSFiddle zeigt, wie dies erreicht werden kann? –

14

Nun, ich habe versucht, es ein Skript bauen zu tun, hier ist, was ich habe:

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

Und JSFiddle sample

Hat Ihre CSS-Stile zu ändern, damit es richtig funktioniert. Was wir tun, ist:

  1. Get Breite des übergeordneten Container, initial width des Hauptmenüs ist Null, aber wir haben wahrscheinlich das zusätzliche Menü zeigen, so dass wir auch seine Größe.
  2. Unter window.resize durchlaufen wir alle Elemente im Hauptmenü (horizontal), wobei jede Elementbreite in der Variablen ulWidth akkumuliert wird.
  3. Sobald die width des Hauptmenüs ist mehr als width des übergeordneten Containers -> müssen wir den Rest der Menüelemente in das Untermenü (vertikal) verschieben - so schieben wir diese Elemente zu einem Array liForMoving.
  4. Wenn Array liForMovingist nicht leer - wir klonen seine Elemente, fügen Sie sie in das Untermenü und entfernen Sie sie aus dem Hauptmenü.
  5. Wenn width aller Elemente in mainMenu ist gering, als die Breite des Containers, müssen wir prüfen, ob wir einige Elemente aus dem Untermenü auf die Haupt ein
  6. Wir durchlaufen Untermenü Elemente bewegen kann, jedes Element greifen, hängen zum Hauptmenü (wenn Sie verschiedene Schriftarten und Abstände in Menüs haben - die endgültige Größe des Elements wird sich unterscheiden), überprüfen Sie, ob die Größe gut für den übergeordneten Container ist. Wenn es ist - wir Element aus einem Untermenü entfernen ($(moved[i]).remove()), wenn es nicht ist - wir entfernen hängten Element (tmpLi.remove())
  7. Schließlich überprüfen wir, ob das Untermenü alle Elemente hat und Show/ausblenden.
+0

aktualisiert meine Antwort – Sergio

+0

Danke danke für jsfiddle Demo. Sieht gut aus. Wird sich integrieren und sehen, ob es in meinem lokalen funktioniert. –

+0

stellen Sie einfach sicher, dass Ihr CSS korrekt ist, um es zu zeigen, wie es in meiner Geige ist (auch ohne JavaScript-Code). Ich hatte einige Trüffel dort, also musste ich fast alle Stile ändern: D – Sergio

1

Ich denke, das Dropdown-Menü sollte umgekehrt werden, um die Tab-Reihenfolge in fokussierbaren Elementen in der gleichen Reihenfolge zu halten.

Für die Erreichbarkeit können Sie auch die Setgröße und die Position im Set einstellen. Aus Gründen der Barrierefreiheit habe ich den Fokus auf den geklonten Eintrag zurückgesetzt, wenn das verschobene Element den Fokus hatte, und setWaiAria hinzugefügt, um die Setz- und Setzposition festzulegen. Setzen Sie den Fokus auf den letzten Punkt, wenn der Link den Fokus mehr hat und verschwindet. siehe 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

Das Beispiel wurde auf eine Geige mit einem Umschaltmenü aktualisiert. Öffnen des Menüs, wenn ein Kind des Menüs den Fokus hat: [fiddle version 4] (http://jsfiddle.net/frontendplace/rvx26j1c/4/) –