Page 1 of 2

Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Fri Nov 05, 2010 11:06 pm
by destinydriven
I recently went through a lot of trouble trying to implement a jquery accordion side menu which could go 3 depths and with some help from Dr.CSS I finally got it up and running. Demo can be found  here http://multiintech.com/default/index.php?page=jquery.  I have included all the relevant code below:
Menu template:

Code: Select all

{if $count > 0}
<ul class="acmenu collapsible">
{foreach from=$nodelist item=node}
{if $node->depth > $node->prevdepth}
{repeat string="<ul class='acmenu menuitem collapsible'>" times=$node->depth-$node->prevdepth}
{elseif $node->depth < $node->prevdepth}
{repeat string="</li></ul>" times=$node->prevdepth-$node->depth}
</li>
{elseif $node->index > 0}</li>
{/if}

{if $node->current == true}
<li><a href="{$node->url}" class="currentpage"{if $node->target ne ""} target="{$node->target}"{/if}> {$node->menutext} </a>

{elseif $node->parent == true && $node->depth == 1 and $node->type != 'sectionheader' and $node->type != 'separator'}
<li class="activeparent"> <a href="{$node->url}" class="activeparent"{if $node->target ne ""} target="{$node->target}"{/if}> {$node->menutext} </a>

{elseif $node->type == 'sectionheader'}
<li class="sectionheader"><a href="#">{$node->menutext}</a>

{else}
<li><a href="{$node->url}"{if $node->target ne ""} target="{$node->target}"{/if}> {$node->menutext} </a>

{/if}

{/foreach}

{repeat string="</li></ul>" times=$node->depth-1}</li>
</ul>
{/if}
Now for the actual accordion menu, you will need jquery-1.4.2.min.js or later and your markup should look like the following:

Code: Select all


<ul class="acmenu [optional class] [optional class]">
<li><a href="#">Sub menu heading</a>
<ul>
<li><a href="http://site.com/">Link</a></li>
<li><a href="http://site.com/">Link</a></li>
<li><a href="http://site.com/">Link</a></li>
...
...
</ul>
<!-- This item is open at page load time -->
<li class="expand"><a href="#">Sub menu heading</a>
<ul>
<li><a href="http://site.com/">Link</a></li>
<li><a href="http://site.com/">Link</a></li>
<li><a href="http://site.com/">Link</a></li>
...
...
</ul>
...
...
</ul>

Here is the js you will need for the menu:

Code: Select all



jQuery.fn.initMenu = function() {
    return this.each(function() {
        $('.menuitem', this).hide();
        $('li.expand > .menuitem', this).show();
        $('li.expand > .menuitem', this).prev().addClass('active');
        $('li a', this).click(function(e) {
            e.stopImmediatePropagation();
            var $this = $(this);
            var theElement = $this.next();
            var parent = $this.parent().parent();
            if (parent.hasClass('noaccordion')) {
                if (theElement[0] === undefined) {
                    window.location.href = this.href;
                }
                theElement.slideToggle('normal', function() {
                    var slideThis = $(this);
                    if (slideThis.is(':visible')) {
                       slideThis.prev().addClass('active');
                    }
                    else {
                       slideThis.prev().removeClass('active');
                    }
                });
                return false;
            }
            else if ( theElement.hasClass('menuitem') ) {
                if (theElement.is(':visible')) {
                    if (parent.hasClass('collapsible')) {
                        $('.menuitem:visible', parent).slideUp('normal', function() {
                            $this.prev().removeClass('active');						
                        });
                        return false;
                    }
                    return false;
                }
                else {
                    $('.menuitem:visible', parent).slideUp('normal', function() {
                        $this.prev().removeClass('active');
                    });
					$('ul.menuitem li:has(ul.menuitem)').addClass('parentMenu');  // add different style for items with children
                    theElement.slideDown('normal', function() {
                        $this.prev().addClass('active');
                    });
                    return false;
                }
            }
        });
    });
};

$(document).ready(function() {
    $('.acmenu').initMenu();
});


And here is some sample css to style the menu:

Code: Select all


ul.acmenu, ul.acmenu ul {
  list-style-type:none;
  margin: 0;
  padding: 0;
  width: 15em;
}

ul.acmenu a {
  display: block;
  text-decoration: none;	
}

ul.acmenu li {
  margin-top: 1px;
}

ul.acmenu li a, ul.acmenu ul.acmenu li a {
  background: #333;
  color: #fff;	
  padding: 0.5em;
}

ul.acmenu li a:hover, ul.acmenu ul.acmenu li a:hover {
  background: #000; /*level 1 background hover*/
}

ul.acmenu li ul li a, ul.acmenu ul.acmenu li ul li a {
  background: #ccc;
  color: #000;
  padding-left: 20px;
}

ul.acmenu li ul li a:hover, ul.acmenu ul.acmenu li ul li a:hover {
  background: #aaa;  /* level 3 highlight colour */
  border-left: 5px #000 solid;
  padding-left: 15px;
}
ul.acmenu ul.acmenu li a:hover {
    border-left: 0;
    padding-left: 0.5em;
}
ul.acmenu ul.acmenu {
    border-left: 5px #f00 solid; /* level 3 border highlight*/
}
ul.acmenu a.active, ul.acmenu ul.acmenu li a.active, ul.acmenu a.active:hover, ul.acmenu ul.acmenu li a.active:hover {
    text-decoration: underline;
    background: #c00;  /* active menu background colour */
}


ul.acmenu div.panel a, ul.acmenu div.panel li a:hover  {
    display :inline;
    color: #666;
    background: none;
    margin: 0;
    padding: 0;
    border: none;
    font-weight: bold;
}
ul.acmenu div.panel a:hover {
    color: #000;
    text-decoration: underline;
}

N.B. This menu is not to be used with separators. Actual top level parent menu items are not clickable to carry you to target pages (best used with section headers).

Hope this helps someone with intentions to implement similar functionality in cmsms. Happy developing! Peace!

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Sat Nov 06, 2010 8:49 am
by nockenfell
Thanks for the demo.  :)

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Tue Nov 09, 2010 12:49 pm
by destinydriven
You're welcome. No probz :D

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Thu Nov 18, 2010 2:00 am
by boby
This is great, just what I was looking for.

The only thing when I click on a page link, the menu closes itself.

Is it posible to get the menu open to the current page?

May be I missed something... is it easy to emplement?

thanks for any help

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Thu Nov 18, 2010 6:19 am
by Dr.CSS
More than likely there may be a way to use one of the calls they have for keeping it open when going to a page, I would have to look thru the JS to see if/what they use to make a menu open to a specific place, they have it in the demo this JS came from...

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Thu Nov 18, 2010 12:14 pm
by nicmare
Just as a little addition. I realized my own Accordion jquery Script:
http://www.smomkenya.org/
The Advantage: the menu saves its state. if you open a specific page, then the menu link will be opened at startup. maybe this helps someone

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Thu Nov 18, 2010 12:46 pm
by boby
That's what I was looking for!

Can you share the code?
I 'm not doing great with JS
thanks

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Thu Nov 18, 2010 2:37 pm
by nicmare
you need a simple menu template like this:

Code: Select all

{if $count > 0}
<ul class="menu" id="menu">
{foreach from=$nodelist item=node}
{if $node->depth > $node->prevdepth}
			{repeat string="<ul>" times=$node->depth-$node->prevdepth}
{elseif $node->depth < $node->prevdepth}{repeat string="</li></ul>" times=$node->prevdepth-$node->depth}</li>{elseif $node->index > 0}</li>
{/if}

{if $node->current == true || $node->parent == true}
			<li class="selected"><a href="{$node->url}">{$node->menutext}</a>

{else}
			<li><a href="{$node->url}">{$node->menutext}</a>{/if}{/foreach}{repeat string="</li></ul>" times=$node->depth-1}</li>
</ul>
{/if}
make sure, its the default template.
and some stylesheet

Code: Select all

.navi li a {
	display:block;
	font-family:Georgia, "Times New Roman", Times, serif;
	background:#8D8D8D;
	margin-bottom:2px;
	color:#fff;
	font-size:1.4em;
	font-weight:normal;
	text-decoration:none;
	padding:12px 12px 4px 12px;}
	
.navi li a:hover {
	background:#666}
	
.navi ul ul {
	border-top:1px solid #8D8D8D;}
	
.navi ul ul a {
	background:#ededed url(images/bullet.gif) no-repeat 20px center;
	color:#8D8D8D;
	margin:0;
	font-family:arial, verdana;
	border-bottom:2px solid #fff;
	padding:10px 8px 8px 32px;
	font-size:1.2em;}
	
.navi ul ul a:hover {
	color:#8D8D8D;
	background:#d8d8d8 url(images/bullet.gif) no-repeat 20px center}
	
.navi ul ul li.selected a {
	background:#fff url(images/bullet.gif) no-repeat 20px center}
now call the menu in your maintemplate. i wrapped a div around it.

Code: Select all

<div class="navi">{menu}</div>
now embed javascript library:

Code: Select all

<__script__ type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></__script>	
put it in your own site(template) before .

after that code, insert the javascript call in the template:

Code: Select all

<__script__ type="text/javascript">
/* <![CDATA[ */
$(document).ready(function(){ 
	$('ul.menu ul').hide();
	$('ul.menu').find("li.selected").parent().show();
	$('ul.menu li a').not('ul ul a').click(
		function() {
			var checkElement = $(this).next();
			var parent = this.parentNode.parentNode.id;
			if($('#' + parent).hasClass('noaccordion')) {
				if((String(parent).length > 0) && (String(this.className).length > 0)) {
					$(this).next().slideToggle('normal');
				}
			}
			if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
				if($('#' + parent).hasClass('collapsible')) {
					$('#' + parent + ' ul:visible').slideUp('normal');
				}
				return false;
			}
			if((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
				$('#' + parent + ' ul:visible').slideUp('normal');
				checkElement.slideDown('normal');
				return false;
			}

		}
	);
})
/* ]]> */
</__script>

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Thu Nov 18, 2010 3:12 pm
by boby
Thanks Nicmare!!!

It works like a charm.

It's a two depth level but just fine for me and for SEO.

My Jquery tabs don't work anymore but I'll have a siesta and check it later on.
Thanks

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Thu Nov 18, 2010 4:22 pm
by nicmare
keep care that you embed jquery library just one time! so if you have already jquery in your template, then leave the jquery google link!
you can easly add more depths. you just have to write more CSS ;-)

PS: Sorry, you do not need the cookie javascript. its a long time ago i developed the site ;-)

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Tue Dec 21, 2010 4:57 am
by concentre
Nicmare -- your accordion menu is exactly what I have been looking for. I've got it working, but am a newbie and am wondering how to add another sub level? You said add more CSS, I tried this and the menu will not display the 3rd level. Do I need to add something to the javascript?

Any help you can offer would be very appreciated.

Thx.

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Tue Dec 21, 2010 10:33 am
by nicmare
if you post a link to the site i could take a look…

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Tue Dec 21, 2010 12:51 pm
by concentre
Here's the link to the site in development:

http://dev.concentre.us/federalcms/inde ... d-overview

There are 5 links that should be below Bakery & Deli. Ideally, when you click Bakery & Deli the next level would drop down. The way it stands the menu wont display this level at all.

Any suggestions?

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Tue Dec 21, 2010 1:20 pm
by nicmare
what happens when u edit this line

Code: Select all

$('ul.accordion li a').not('ul ul a').click(
to

Code: Select all

$('ul.accordion li a').click(
?

Re: Multilevel (3 depth) jQuery Accordion Side Menu

Posted: Tue Dec 21, 2010 1:26 pm
by concentre
Nothing. It stays exactly the same.