FF2+ IE8+ Opr8+

Power List menu

Author: Dynamic Drive

Description: Power List Menu is a mobile centric,  mult-level menu that magically transforms  a nested UL into a series of slide-in panels that occupy no more space than the top level UL itself. It's ideal on mobile devices where the playground for drop down or flyout menus is limited. Click on a header, and the corresponding sub UL slides into view over the parent UL. The menu's width can be responsive as well, supporting a percentage value.  What adds "power" to this menu is its Ajax and "lazy loading" functionality:

  • The initial contents of the menu can be defined either inline on the page or inside an external file and fetched via Ajax

  • A child menu can be undefined initially, with its contents only fetched on demand when a corresponding header is clicked on ("lazy loading" child menu).

  • A parent menu can also be undefined initially, with its contents only fetched on demand when a corresponding reverse "breadcrumb" link is clicked on ("lazy loading" parent menu).

The lazy loading functionality means you can break a large UL menu into branches that are only downloaded when that part of the menu is requested, decreasing menu download time and saving on bandwidth to boot. Dynamically loaded lazy menus can themselves link to another lazy menu, creating an endless chain of menus loaded all on demand.

The menu works across all major browsers and platforms, including IE8+ and mobile browsers of course.

Demo:

See also: Compact Drop Down Menus and Drill Down Menu.


Directions Developer's View

Step 1: Add the below code to the HEAD section of your page:

Select All

This script uses the following external files. Download them below (right click, and select "Save As"):

Step 2: Then, add the below sample menu markup to your page:

Select All

Inside powerlistmenu.css, refer to the comments to modify the style of the menu, from its dimensions to the colors.

The menu uses icon fonts from Font Awesome to render the "right" and breadcrumb "back" arrows. To modify or replace them with your own custom markup for example, near the top of powerlistmenu.js, edit the lines in red:

var defaults = {
 selectedul: 0,
 loadingdiv: '<div class="loadingscreen"><div>Fetching content...</div></div>', // HTML for loading screen while fetching Ajax content
 rightarrow: '<span class="right fa fa-angle-right"></span>', // HTML for right arrow markup. Defaults to using font-awesome icon font
 backarrow: '<span class="left fa fa-arrow-circle-o-left"></span>', // HTML for back/left arrow markup. Defaults to using font-awesome icon font

 slideduration: 500,
 easing: 'easeInOutCirc' // slide easing function
}

 The only other option you may want to edit is "loadingdiv", which defines the markup for the DIV that overlays the menu while Ajax content is being fetched. The other options can be defined when you initialize the menu, which is discussed below.

More Information

The markup of a Power List Menu consists of a main <NAV> element with a UL (nested or not) inside it:

<nav id="powermenu1" class="powerlistmenu">
<ul>
<li><a href="http://www.dynamicdrive.com">Item 1</a></li>
<li><a href="http://www.dynamicdrive.com">Folder 0</a>
<ul>
 <li><a href="http://www.dynamicdrive.com">Sub Item 0.1</a></li>
 <li><a href="http://www.dynamicdrive.com">Sub Item 0.2</a></li>
 <li><a href="http://www.dynamicdrive.com">Sub Item 0.3</a></li>
"
"
</nav>

The NAV element should contain a unique ID and a CSS class of "powerlistmenu".  The UL contained inside can either be defined inline (as is the case above), or inside an external file on the server and fetched via Ajax instead (more on this later).

To initialize the menu, call new Powerlistmenu() in the head section of your page, for example:

<script type="text/javascript">

var powerinstance

jQuery(function($){ // on DOM load
 powerinstance = new Powerlistmenu({
  menuid: 'powermenu1' // id of main nav container
 })
})

</script>

where at the minimum you should have  the "menuid" option pointing to the ID of your Power List NAV element. Here are the full list of options Powerlistmenu() supports:

Option Description
menuid: 'string'

Required

The ID of the menu outermost NAV element.
selectedul: 'jquery_selector' | int

defaults to 0

The default UL to show when the menu loads. It accepts either a jQuery selector targeting the desired UL (recommended way), or a numeric index reflecting the position of the UL within the collection of ULs.

The easiest way to set it up is to give the desired UL to show an ID attribute, for example:

<nav id="powermenu1" class="powerlistmenu">
<ul>
<li><a href="http://www.dynamicdrive.com">Item 1</a></li>
<li><a href="http://www.dynamicdrive.com">Folder 0</a>
<ul id="selected">
 <li><a href="http://www.dynamicdrive.com">Sub Item 0.1</a></li>
 <li><a href="http://www.dynamicdrive.com">Sub Item 0.2</a></li>
 <li><a href="http://www.dynamicdrive.com">Sub Item 0.3</a></li>
"
"
</nav>

and then for the "selectedul" option inside the initialization code, pass in "#selected" to select it when the page loads:

<script type="text/javascript">

var powerinstance

jQuery(function($){ // on DOM load
 powerinstance = new Powerlistmenu({
  menuid: 'powermenu1', // id of main nav container
  selectedul: '#selected' // <-- no comma after last option
 })
})

</script>

menucontent: 'path_to_ul_file'

defaults to undefined

When this option is defined, the script loads the main UL portion of the menu dynamically and at the location defined inside the "menucontent" option. More info here.
slideduration: milliseconds

defaults to 500

The duration of the slide animation that brings each UL into view, in milliseconds.
easing: 'string'

defaults to 'easeInOutCirc'

The type of slide-in easing effect that should be applied to this instance of Power List menu. There are four string values to choose from:
  • "easeInOutSine"
  • "easeInOutCirc"
  • "easeInQuad"
  • "easeOutBack"

The difference in some of the easing options are subtle, though "easeOutBack" is dramatically different in that it produces a "bounce in" effect.

backarrow: 'string'

defaults to '<span class="right fa fa-angle-right"></span>''

The HTML markup for the "back arrow" that gets inserted inside the "breadcrumb" DIV of each sub menu. You can specify any HTML, such as an image. By default it uses a Font Awesome font icon to let you easily modify the icon size and color using CSS only.
rightarrow: 'string'

defaults to '<span class="right fa fa-angle-right"></span>''

The HTML markup for the "right  arrow" that gets inserted inside each header LI that contains a sub UL. You can specify any HTML, such as an image. By default it uses a Font Awesome font icon to let you easily modify the icon size and color using CSS only.
loadingdiv: 'string'

defaults to '<div class="loadingscreen"><div>Fetching content...</div></div>'

The markup for the overlay DIV that covers the menu while Ajax content (if any) is being loaded.

Ajax loading the initial menu contents

When you first set up the markup of the menu, you have the option of defining the initial menu contents- specifically, the (nested) UL itself-, either inline on the page as shown below:

<nav id="powermenu1" class="powerlistmenu">
<ul>
<li><a href="http://www.dynamicdrive.com">Item 1</a></li>
<li><a href="http://www.dynamicdrive.com">Folder 0</a>
<ul>
 <li><a href="http://www.dynamicdrive.com">Sub Item 0.1</a></li>
 <li><a href="http://www.dynamicdrive.com">Sub Item 0.2</a></li>
 <li><a href="http://www.dynamicdrive.com">Sub Item 0.3</a></li>
</ul>
"
"
</ul>

</nav>

or inside an external file on your server instead (the portion in green):

- pcontents.htm

With the second setup, it means the initial markup on your page should only be the NAV element portion:

<nav id="powermenu1" class="powerlistmenu"></nav>

The menu's initialization code in the 2nd case should utilize the "menucontent" option to specify the path to this external file:

<script type="text/javascript">

var powerinstance

jQuery(function($){ // on DOM load
 powerinstance = new Powerlistmenu({
  menuid: 'powermenu1', // id of main nav container
  menucontent: 'pcontents.htm' // <-- no comma after last option
 })
})

</script>

Demo (menu contents defined inside external file):

Lazy loading a sub UL on demand

Any LI element within a Power List Menu can be set to lazy load a sub menu via Ajax when the LI is clicked on. This makes it possible to only download a large sub menu when it's actually requested. To do this, just give the LI element a "data-lazyload" attribute:

<nav id="powermenu1" class="powerlistmenu">
<ul>
<li><a href="http://www.dynamicdrive.com">Item 1</a></li>
<li data-lazyload="extra.htm"><a href="http://www.dynamicdrive.com">Item 2</a></li>
<li><a href="http://www.dynamicdrive.com">Item 3</a></li>
<li><a href="http://www.dynamicdrive.com">Item 4</a></li>
<li><a href="http://www.dynamicdrive.com">Item 5</a></li>
</ul>
</nav>

"data-lazyload" should point to the path to the sub menu UL from the current directory, in this case, simply "extra.htm". If you examine the contents of this file, its second LI element in itself contains a "data-lazy" attribute pointing to another sub menu, specifically, "extra.htm" again. This creates a never ending chain of sub menus, as seen below.

Demo (infinite lazy loading of sub ULs on demand):

Lazy loading a parent UL on demand

Lazy loading can also occur in the opposite direction. You may initially start with a sub menu, and only load the corresponding parent menu (perhaps a large menu) when the dynamically generated breadcrumb at the top of the sub menu is clicked on.

To lazy load a parent menu, inside the top most UL element of your menu, define two attributes:

  • data-lazyload="path to parent menu file"

  • data-reverseheader="#headerid, header title"

Lets explain the two attributes, particularly the 2nd, through an example. The following initial menu markup specifies a parent menu to be loaded on demand when the breadcrumb is clicked on:

<nav id="powermenu1" class="powerlistmenu">
<ul data-lazyload="lazyparent.htm" data-reverseheader="#dynamicheader, Child Folder">
<li><a href="http://www.dynamicdrive.com">Item 1</a></li>
<li<a href="http://www.dynamicdrive.com">Item 2</a></li>
<li><a href="http://www.dynamicdrive.com">Item 3</a></li>
<li><a href="http://www.dynamicdrive.com">Item 4</a></li>
<li><a href="http://www.dynamicdrive.com">Item 5</a></li>
</ul>
</nav>

Demo (lazy loading of parent UL on demand):

Notice how the two attributes in red are added to the topmost UL of your menu- adding it to any sub UL will have no effect. Because the top UL at this point has to generate a breadcrumb pointing to the yet-to-be-loaded parent menu before it's even downloaded,  the "data-reverseheader" is used to tell the script in advance some information about the promised parent menu, so the breadcrumb can be properly generated. Specifically,  "data-reverseheader" should contain the following two bits of info:

  1. #headerid: The ID of the LI element inside the parent menu that the current sub menu should be associated with, prefixed with "#". Here I've set it to "#dynamicheader"; peek inside "lazyparent.htm" and notice how the 2nd LI element is assigned an ID of this value (without the "#" prefix). This pairs the desired LI header in the yet-to-be-loaded parent menu with our existing sub menu.

  2. header title: The title of the LI header that should be shown inside the breadcrumb of our existing sub menu. Normally this would reflect the actual text inside the parent LI element, but can be set to anything you like.

Like lazy sub menus a lazily loaded parent can in itself lazy load another parent menu, leading to an endless number of ancestors!