CMS Made Simple Forums
https://forum.cmsmadesimple.org/

Multilevel (3 depth) jQuery Accordion Side Menu
https://forum.cmsmadesimple.org/viewtopic.php?f=4&t=48733
Page 1 of 2

Author:  destinydriven [ Fri Nov 05, 2010 11:06 pm ]
Post subject:  Multilevel (3 depth) jQuery Accordion Side Menu

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:
{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:

<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:


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:

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!

Author:  nockenfell [ Sat Nov 06, 2010 8:49 am ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

Thanks for the demo.  :)

Author:  destinydriven [ Tue Nov 09, 2010 12:49 pm ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

You're welcome. No probz :D

Author:  boby [ Thu Nov 18, 2010 2:00 am ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

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

Author:  Dr.CSS [ Thu Nov 18, 2010 6:19 am ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

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...

Author:  nicmare [ Thu Nov 18, 2010 12:14 pm ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

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

Author:  boby [ Thu Nov 18, 2010 12:46 pm ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

That's what I was looking for!

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

Author:  nicmare [ Thu Nov 18, 2010 2:37 pm ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

you need a simple menu template like this:
Code:
{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:
.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:
<div class="navi">{menu}</div>

now embed javascript library:
Code:
<__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:
<__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>

Author:  boby [ Thu Nov 18, 2010 3:12 pm ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

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

Author:  nicmare [ Thu Nov 18, 2010 4:22 pm ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

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

Author:  concentre [ Tue Dec 21, 2010 4:57 am ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

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.

Author:  nicmare [ Tue Dec 21, 2010 10:33 am ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

if you post a link to the site i could take a look…

Author:  concentre [ Tue Dec 21, 2010 12:51 pm ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

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?

Author:  nicmare [ Tue Dec 21, 2010 1:20 pm ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

what happens when u edit this line
Code:
$('ul.accordion li a').not('ul ul a').click(

to
Code:
$('ul.accordion li a').click(

?

Author:  concentre [ Tue Dec 21, 2010 1:26 pm ]
Post subject:  Re: Multilevel (3 depth) jQuery Accordion Side Menu

Nothing. It stays exactly the same.

Page 1 of 2 All times are UTC
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/