html - jQuery multi-level accordion menu -
i found accordion menus online either did not support multiple levels, or code quite cryptic , didn't want use it. decided, want write own accordion menu, supports arbitrary number of sub-menus.
here have far:
$(document).ready(function() { // @ beginning top menu items visible $('.multi-level-accordion-menu > li ul').slideup(0); console.log('all elements slid up'); // when menu item not active clicked, show next lower level // when menu item active clicked, hide sub menu items $('.multi-level-accordion-menu li').click(function() { var menu_item = $(this); if (is_active(menu_item)) { console.log('active menu item clicked'); close_menu_item(menu_item); } else { console.log('inactive menu item clicked'); open_menu_item(menu_item); } }); console.log('ready!'); }); function open_menu_item(menu_item) { menu_item.children('ul').slidedown(500); menu_item.addclass('active-menu-item'); } function close_menu_item(menu_item) { console.log('1x'); menu_item.find('ul').each(function(index, elem) { $(elem).slideup(); return false; }); menu_item.removeclass('active-menu-item'); } function is_active(menu_item) { return menu_item.hasclass('active-menu-item'); }
.multi-level-accordion-menu * { margin: 0px; padding: 0px; } .multi-level-accordion-menu { list-style: none; max-width: 200px; } .multi-level-accordion-menu ul { list-style: none; } .multi-level-accordion-menu li { border-color: #eeeeee; border-width: 1px; border-style: solid; background-color: #303030; margin: 2px; padding: 2px; line-height: 30px; font-size: 16px; } .multi-level-accordion-menu { color: #dddddd; } body { background-color: #202020; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body> <div> <ul class='multi-level-accordion-menu'> <li>item 1 <ul> <li>item 1.1 <ul> <li>item 1.1.1</li> <li>item 1.1.2</li> <li>item 1.1.3</li> <li>item 1.1.4</li> </ul> </li> <li>item 1.2</li> <li>item 1.3</li> <li>item 1.4</li> <li>item 1.5</li> <li>item 1.6</li> </ul> </li> <li>item 2</li> <li>item 3 <ul> <li>item 3.1 <ul> <li>item 3.1.1</li> <li>item 3.1.2</li> <li>item 3.1.3</li> <li>item 3.1.4</li> </ul> </li> <li>item 3.2</li> <li>item 3.3</li> <li>item 3.4</li> <li>item 3.5</li> <li>item 3.6</li> </ul> </li> <li>item 4</li> <li>item 5</li> <li>item 6</li> <li>item 7</li> </ul> </div> </body>
http://jsfiddle.net/zelphir/1fp03oyq/1/
clicks on top level menu items work, when click item 1
, item 1.1
becomes obvious, lower levels don't work yet. sub-menu opens somehow @ same time top level closes again.
how can achieve following behavior:
- a click on 'inactive' menu item makes sub-menu items visible
- a click on 'active' menu item hides sub menu items , sub menu items
- at beginning items 'inactive'
this should work you.
$('.multi-level-accordion-menu').click(function(e){ var menu_item = $(e.target); if(is_active(menu_item)) { console.log('active menu item clicked'); close_menu_item(menu_item); } else { console.log('inactive menu item clicked'); open_menu_item(menu_item); } }); function close_menu_item(menu_item) { console.log('1x'); menu_item.find('ul').each(function() { $(this).slideup().find('li').removeclass('active-menu-item'); }); menu_item.removeclass('active-menu-item'); }
or one/two liner
function close_menu_item(menu_item) { console.log('1x'); menu_item.removeclass('active-menu-item').find('ul').slideup(). find('li').removeclass('active-menu-item'); }
in response comment:
in case bubbling causes 'click' method fire on outermost container (.multi-level-accordion-menu).
when click on child element, stored in 'target' property of 'event' object, , click event bubbles until hits outermost container, have defined in jquery selector( again - .multi-level-accordion-menu).
the outermost container sitting there listening 'click' events, when event bubbles it, enters function.
you selecting target element triggered (stored in 'target' property of 'event' object) , performing whatever want on it. since inside function , there no event listeners in there, no more events fire, , there no further bubbling. function completes , no more 'click' events triggered since event has bubbled top.
in original code, listening click events on 'li' elements, when clicked on 'li' element trigger click listener , run function. when function finished event bubble ancestor 'li' element, trigger listener again , run method again. , on.
hope clears bit!
Comments
Post a Comment