Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrating Mmenu within Bootstrap

I'd like to integrate Jquery Mmenu within Bootstrap to automaticaly let bootstrap switchs to this sliding left-side menu with the responsive design, rather than displaying the native top vertical responsive menu.

Any ideas or approach ?

Jquery Mmenu : http://mmenu.frebsite.nl

I thank you all in advance.

Jay.

like image 921
wendl Avatar asked Jun 03 '13 08:06

wendl


2 Answers

Well, I set out on same quest a few hours ago and I was hoping to find an answer here to help me out.

I've got it working now and I'll share what I've learned, though I'm new to bootstrap. Someone else feel free to chime in if you see rookie mistakes. Guess it's time to repay the community since many of my questions have been answered here.

Here goes:

Look at this jsFiddle to see my complete sample code and demo: http://jsfiddle.net/acterry/fMYpg/

You'll have play with the the vertical divider to see the nav change from one style to the other.

I wanted to use the same nav ul to drive both menus. But after looking through the source of Jquery.mmenu, I saw the following things that I knew would cause problems:

  • mmenu wraps new containers (div by default) around your HTML
  • mmenu modifies the menu ul in ways that would likely freak out bootstrap navbar
  • mmenu had no function to destory itself and undo the DOM changes it caused

As a proof of concept, I was fine with using bootstraps predefined responsive breakpoints to determine which nav style was shown.

Here's the HTML for the menu portion

<div class="navbar navbar-inverse navbar-fixed-top">
  <div class="visible-desktop navbar-inner">
    <div class="container">
      <!-- .btn-navbar is used as the toggle for collapsed navbar content -->  
      <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </a>
      <a class="brand" href="/">My Site</a>
      <!-- Everything you want hidden at 940px or less, place within here -->
      <div class="nav-collapse collapse">
        <ul class="nav" id="mainSiteMenu">
          <li><a href="#">Home</a>
          </li>
          <li><a href="#">Link 1</a>
          </li>
          <li><a href="#">Link 2</a>
          </li>
          <li><a href="#">Link 3</a>
          </li>
        </ul>
      </div>
    </div>
  </div>
  <div class="hidden-desktop navbar-inner">
    <div class="container">
      <!-- .btn-navbar is used as the toggle for collapsed navbar content -->
      <a class="btn btn-navbar" href="#mainSiteMenuMMenuNav">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </a>
      <a class="brand" href="/">My Site</a>
    </div>
  </div>
</div>
<nav id="mainSiteMenuMMenuNav"></nav>

Here's a quick breakdown of the steps:

  1. (not shown above) Wrap all of the HTML on your page in a div if it is not already in a single container. If you are using something other than a div, then set the pageNodetype in the mmenu config appropriately
  2. Define your nav ul as shown on the bootstrap component page. But, give the UL an ID so we can reference it later.
  3. Duplicate the navbar-inner div
  4. In the first navbar inner, add visible-desktop to the div's class parameter -- this is the navbar that will be shown to desktop users. Bootstrap will hide it below the desktop/tablet width breakpoint
  5. In the second navbar-inner, add hidden-desktop to the div's class parameter -- this is the navbar that will be shown to tablets/phones (or anything else with a browser width less than 940px by default)
  6. Add an empty nav container with an ID (I used mainSiteMenuNav) after the closing div of the navbar. This is where the UL for mmenu will be.
  7. In my code, notice the btn-navbar link in the second navbar-inner. That's the button that's going to open/close mmenu. The href anchor needs to match whatever ID you gave that empty nav container

Since I couldn't use the exact same UL for both menu's, I decided to use jQuery to programmatically duplicate the one used by the bootstrap navbar upon page load and stuff it into the empty nav container for mmenu to use.

It would probably be cleaner to just create the empty nav container programmatically. I'll probably do that tomorrow.

This javascript copies the UL, places it into the nav container and instantiates mmenu with the copied UL:

$(function () {
    $("#mainSiteMenuMMenuNav").append($("#mainSiteMenu").clone().attr("id", "mainSiteMenuMMenu").attr("class", ""));
    $("#mainSiteMenuMMenuNav").mmenu({
        configuration: {
            pageNodetype: "div"
        }
    });
});

That should do it. If you run into problems, please double-check everything. And again, I just figured this out a couple of hours ago .... so it might NOT be a fool proof solution.

If someone has a better way or sees issues, let me know.

like image 175
Aaron Terry Avatar answered Nov 13 '22 17:11

Aaron Terry


Hopefully this is on topic and helpful. I've used the normal bootstrap menu until min-width: 1060px and then MMenu from then on down. Here's the JS (I'm using enquire.js to match media queries).

// uses enquire.js to fire js on media queries
// https://github.com/WickyNilliams/enquire.js/
enquire.register("screen and (max-width:1060px)", {

// Wait until media query is matched
deferSetup: true,
// Fires once 
setup: function() {
// requires an empty <nav id="menu"></nav>
$('.navbar-nav').clone().appendTo('#menu');
$('#menu > ul').attr("id", "mmenu");
//clean up mmenu by removing bootstrap classes
$('#mmenu ul').removeClass('dropdown-menu animated fadeInDown');
$('#mmenu li').removeClass('dropdown');
$('#mmenu li a').removeClass('dropdown-toggle').removeAttr("data-toggle data-target");
// $('#mmenu li a').removeAttr("data-toggle data-target");
$('#mmenu').removeClass('nav navbar-nav');

},

// If supplied, triggered when a media query matches.
match: function() {

//Show mmenu on media query match
$("#menu").mmenu({
"offCanvas": {
"position": "right"
}
});
},

// *from a matched state to an unmatched state*.
unmatch: function() {
//Hide mmenu
$('#menu').trigger('close.mm');
// $('#mmenu').remove();

}

});
like image 20
brockis Avatar answered Nov 13 '22 16:11

brockis