sign in | join about | help | sitemap
Connecting Tech Pros Worldwide
Jonathan's Avatar

Adding an additional submenu to a collapsible/expandable menu


Question posted by: Jonathan (Guest) on January 5th, 2007 05:05 PM
Hello All,

I am in the process of creating a 2/3 level collapsible/exspanible menu
(called "nav") where users can click on a category and have the
submenus appear beneath it and so on (allow users to click on another
category and have that expand).

Example:
Quote:
Originally Posted by
>Corp Info
Quote:
Originally Posted by
>>Corp Overview
>>Remote Sites

>Departments
Quote:
Originally Posted by
>>Human Resources
>>HR Staff
>>HR Forms
>>HR Etc.


Currently the code below allows the users to the drill down one level,
but I want it to be able to drill down an additional level. Any help
would be much appreciated.

Jonathan


Current Code:
************************************************** **************************
<style type="text/css">
#nav {width: 170px; height: 500px}
#nav, #nav ul, #nav li {margin: 0; padding: 0; list-style: none;}
#nav li {clear: both;}
#nav li b {display: block; height: 1.2em; color: white; background:
#000033; width: 100%; border-top: thin solid #CCCCCC; padding: 4px;}
#nav li ul li a {display: block; height: 1.2em; width: 100%; padding:
4px; text-decoration: none; color: black; background: #ededed;
border-top: thin solid #CCCCCC;}
#nav li ul li {font-size: 92%; border: #000033; background: none;}
#nav li ul li a:hover {color: #000033; background: orange; }
</style>

<script type="text/javascript">

function setCookie (name, value, path, domain, secure, expires)
{
document.cookie= name + "=" + escape(value) +
((expires) ? "; expires=" + expires.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "");
}

function getCookie (name)
{
var dc = document.cookie;
var prefix = name + "=";
var begin = dc.indexOf("; " + prefix);
if (begin == -1)
{
begin = dc.indexOf(prefix);
if (begin != 0) return null;
}
else
{
begin += 2;
}
var end = document.cookie.indexOf(";", begin);
if (end == -1)
{
end = dc.length;
}
return unescape(dc.substring(begin + prefix.length, end));
}

function deleteCookie (name, path, domain)
{
if (getCookie(name))
{
document.cookie = name + "=" +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
"; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
}


function addLoadEvent (func)
{
var oldonload = window.onload;
if (typeof window.onload != 'function')
{
window.onload = func;
}
else
{
window.onload = function()
{
oldonload();
func();
}
}
}

</script>

<script type="text/javascript">

function menu_init ()
{
var menu = document.getElementById('nav');
var subs = menu.childNodes;

var j = 0;

for (var i=0 ; subs[i]; i++)
{
if (subs[i].tagName=='LI')
{
hs = subs[i].getElementsByTagName('B');
heading = hs[0];
ss = subs[i].getElementsByTagName('UL');
submenu = ss[0];

j++;

heading.onclick = function () { menu_toggle(this); };

if (getCookie('menu'+j)=='1')
submenu.style.display = 'block';
else if (getCookie('menu'+j)=='0')
submenu.style.display = 'none';
else if (j==1)
submenu.style.display = 'block';
else
submenu.style.display = 'none';
}
}
}

function menu_toggle (heading)
{
var section = heading.parentNode;
var submenus = section.getElementsByTagName('UL');
var submenu = submenus[0];

if (submenu.style.display=='none')
submenu.style.display = 'block';
else
submenu.style.display = 'none';

var j = 0;

var menu = document.getElementById('nav');
var subs = menu.childNodes;
for (var i=0 ; subs[i]; i++)
{
if (subs[i].tagName=='LI')
{
hs = subs[i].getElementsByTagName('B');
h = hs[0];
j++;

if (h==heading && submenu.style.display=='none')
setCookie('menu'+j, '0', '/');
else if (h==heading)
setCookie('menu'+j, '1', '/');
}
}


}

addLoadEvent(menu_init);

</script>

<!--[if IE 6]>
<script type="text/javascript">
// Suckerfish-like code to get B:hover working in IE 6.
function sucker_bold ()
{
bs = document.getElementById("nav").getElementsByTagName('B');
for (i=0; bs[i]; i++)
{
node = bs[i];
node.onmouseover=function() { this.className+=" over"; }
node.onmouseout=function() { this.className=this.className.replace("
over", ""); }
}
}
addLoadEvent(sucker_bold);
</script>
<![endif]-->

<DIV id=leftNavContainer>
<ul id="nav">
<li>
<b>Corporate Information</b>
<ul>
<li><a href="#">Corporate
Overview</a></li>
<li><a href="#">Remote Sites</a></li>
</ul>
</li>
<li>
<b>Departments</b>
<!--<ul>-->
<ul>
<li><a href="#">Human
Resources</a></li>
<!-- <li><a href="">HR Staff</a></li>
<li><a href="">HR Forms</a></li>
<li><a href="">Benefits</a></li>
</ul>-->
<li><a
href="#">Accounting</a></li>
<!-- <ul>
<li><a href="">Accounting
Staff</a></li>
<li><a href="">Organizational
Chart</a></li>
</ul>-->
</ul>
</li>

</ul>
</div>
************************************************** ************************************************** *****

5 Answers Posted
Toby Inkster's Avatar
Guest - n/a Posts
#2: Re: Adding an additional submenu to a collapsible/expandable menu

Jonathan wrote:
Quote:
Originally Posted by
Currently the code below allows the users to the drill down one level,
but I want it to be able to drill down an additional level. Any help
would be much appreciated.


This looks startlingly like an old script of mine.

I've not tried it with three nav levels, but I *believe* the key is to
replace this:

subs = menu.childNodes();

with this:

subs = menu.getElementsByTagName('LI');

--
Toby A Inkster BSc (Hons) ARCS
Contact Me ~ http://tobyinkster.co.uk/contact

Jonathan N. Little's Avatar
Jonathan N. Little January 5th, 2007 08:25 PM
Guest - n/a Posts
#3: Re: Adding an additional submenu to a collapsible/expandable menu

Toby Inkster wrote:
Quote:
Originally Posted by
Jonathan wrote:
>
Quote:
Originally Posted by
>Currently the code below allows the users to the drill down one level,
>but I want it to be able to drill down an additional level. Any help
>would be much appreciated.

>
This looks startlingly like an old script of mine.
>
I've not tried it with three nav levels, but I *believe* the key is to
replace this:
>
subs = menu.childNodes();
>
with this:
>
subs = menu.getElementsByTagName('LI');
>


I did up a demo for someone here recently that is a little more modern
for attaching the events and degrades to a fully expanded list if
JavaScript is disabled

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>template</title>
<style type="text/css">
#sm1,#sm2,#sm3 {
display: block;
}
</style>

<script type="text/javascript">
var buf='<style type="text/css">#sm1, #sm2, #sm3 { display: none;
}</style>';
document.write(buf);
</script>

<script type="text/javascript">

var menus=new Array('m1', 'm2', 'm3');

function toggle(e){
var me;
if(!e) var e=window.event;
if(e.target) me=e.target; // W3C
else if(e.srcElement) me=e.srcElement; // MSIE
if(me.nodeType == 3) me=me.parentNode; // Safari bug on elements
with TEXT

var id='s' + me.id;
var submenu=document.getElementById(id);
me.flag =! me.flag;
if(me.flag) submenu.style.display="block";
else submenu.style.display="none";
}

function initMenus(){
for( var i=0; i<menus.length; i++){
var menu=document.getElementById(menus[i]);

//alert('Init ' + menus[i] + ' which is ' + menu.tagName );

menu.flag=false;

if(menu.addEventListener){
menu.addEventListener('click', toggle, false);
}
else if(menu.attachEvent){ //MS IE support
menu.attachEvent('onclick', toggle);
}
}
}

// attach event after page loads
if( window.addEventListener ) {
window.addEventListener('load',initMenus,false); //legacy
} else if( document.addEventListener ) {
document.addEventListener('load',initMenus,false); //proper
} else if( window.attachEvent ) {
window.attachEvent("onload", initMenus); //IE only
}

</script>

</head>
<body>

<ul>
<li><a href="#" id="m1">Menu 1</a>
<ul id="sm1">
<li>Submenu 1.1</li>
<li>Submenu 1.2</li>
<li>Submenu 1.3</li>
</ul>
</li>
<li><a href="#" id="m2">Menu 2</a>
<ul id="sm2">
<li>Submenu 2.1</li>
<li>Submenu 2.2</li>
<li>Submenu 2.3</li>
<li>Submenu 2.4</li>
</ul>
</li>
<li><a href="#" id="m3">Menu 3</a>
<ul id="sm3">
<li>Submenu 3.1</li>
<li>Submenu 3.2</li>
</ul>
</li>
<ul>

</body>
</html>

--
Take care,

Jonathan
-------------------
LITTLE WORKS STUDIO
http://www.LittleWorksStudio.com
Jonathan's Avatar
Guest - n/a Posts
#4: Re: Adding an additional submenu to a collapsible/expandable menu

Jonathan,

Is there anything special that I need to do to view your example? I
saved your code (as an new html file) and attempted to view it to no
avail. What would you suggest me to do to view your example. Thanks
for your assistance.

Jonathan

Jonathan N. Little wrote:
Quote:
Originally Posted by
Toby Inkster wrote:
Quote:
Originally Posted by
Jonathan wrote:
Quote:
Originally Posted by
Currently the code below allows the users to the drill down one level,
but I want it to be able to drill down an additional level. Any help
would be much appreciated.


This looks startlingly like an old script of mine.

I've not tried it with three nav levels, but I *believe* the key is to
replace this:

subs = menu.childNodes();

with this:

subs = menu.getElementsByTagName('LI');

>
I did up a demo for someone here recently that is a little more modern
for attaching the events and degrades to a fully expanded list if
JavaScript is disabled
>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>template</title>
<style type="text/css">
#sm1,#sm2,#sm3 {
display: block;
}
</style>
>
<script type="text/javascript">
var buf='<style type="text/css">#sm1, #sm2, #sm3 { display: none;
}</style>';
document.write(buf);
</script>
>
<script type="text/javascript">
>
var menus=new Array('m1', 'm2', 'm3');
>
function toggle(e){
var me;
if(!e) var e=window.event;
if(e.target) me=e.target; // W3C
else if(e.srcElement) me=e.srcElement; // MSIE
if(me.nodeType == 3) me=me.parentNode; // Safari bug on elements
with TEXT
>
var id='s' + me.id;
var submenu=document.getElementById(id);
me.flag =! me.flag;
if(me.flag) submenu.style.display="block";
else submenu.style.display="none";
}
>
function initMenus(){
for( var i=0; i<menus.length; i++){
var menu=document.getElementById(menus[i]);
>
//alert('Init ' + menus[i] + ' which is ' + menu.tagName );
>
menu.flag=false;
>
if(menu.addEventListener){
menu.addEventListener('click', toggle, false);
}
else if(menu.attachEvent){ //MS IE support
menu.attachEvent('onclick', toggle);
}
}
}
>
// attach event after page loads
if( window.addEventListener ) {
window.addEventListener('load',initMenus,false); //legacy
} else if( document.addEventListener ) {
document.addEventListener('load',initMenus,false); //proper
} else if( window.attachEvent ) {
window.attachEvent("onload", initMenus); //IE only
}
>
</script>
>
</head>
<body>
>
<ul>
<li><a href="#" id="m1">Menu 1</a>
<ul id="sm1">
<li>Submenu 1.1</li>
<li>Submenu 1.2</li>
<li>Submenu 1.3</li>
</ul>
</li>
<li><a href="#" id="m2">Menu 2</a>
<ul id="sm2">
<li>Submenu 2.1</li>
<li>Submenu 2.2</li>
<li>Submenu 2.3</li>
<li>Submenu 2.4</li>
</ul>
</li>
<li><a href="#" id="m3">Menu 3</a>
<ul id="sm3">
<li>Submenu 3.1</li>
<li>Submenu 3.2</li>
</ul>
</li>
<ul>
>
</body>
</html>
>
--
Take care,
>
Jonathan
-------------------
LITTLE WORKS STUDIO
http://www.LittleWorksStudio.com


Jonathan N. Little's Avatar
Jonathan N. Little January 5th, 2007 10:25 PM
Guest - n/a Posts
#5: Re: Adding an additional submenu to a collapsible/expandable menu

Jonathan wrote:
Quote:
Originally Posted by
Jonathan,
>
Is there anything special that I need to do to view your example? I
saved your code (as an new html file) and attempted to view it to no
avail. What would you suggest me to do to view your example. Thanks
for your assistance.


Nope only that your have JavaScript enabled and DOM1 browser. Mind you
this just just a strip down example. When first loaded should only see
the three main menu items. Click one on and the submenu should expand...

--
Take care,

Jonathan
-------------------
LITTLE WORKS STUDIO
http://www.LittleWorksStudio.com
BootNic's Avatar
Guest - n/a Posts
#6: Re: Adding an additional submenu to a collapsible/expandable menu

[snip]
Quote:
Originally Posted by
Quote:
Originally Posted by
> var buf='<style type="text/css">#sm1, #sm2, #sm3 { display: none;
>}</style>';

watch for line wrap
[snip]
Quote:
Originally Posted by
Quote:
Originally Posted by
> if(me.nodeType == 3) me=me.parentNode; // Safari bug on
>elements with TEXT

watch for line wrap
[snip]
Quote:
Originally Posted by
Jonathan <jonathan.crowder@gmail.comwrote:
news: Join Bytes!
Jonathan,
>
Is there anything special that I need to do to view your example? I
saved your code (as an new html file) and attempted to view it to no
avail. What would you suggest me to do to view your example. Thanks
for your assistance.


Fix the line wrap and perhaps it will work for you.

--
BootNic Friday, January 05, 2007 11:54 PM

Optimism and humor are the grease and glue of life. Without both of
them we would never have survived our captivity.
*Philip Butler, Vietnam POW*

 
Not the answer you were looking for? Post your question . . .
196,932 members ready to help you find a solution.
Join Bytes.com

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over 196,932 network members.
Post your question now . . .
It's fast and it's free

Popular Articles

Top Community Contributors