422,946 Members | 1,155 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 422,946 IT Pros & Developers. It's quick & easy.

CSS Navigation Menu - horizontal and keep submenu opened

P: 22
I have this code used for the navigation on an HTML page. It's an accordion style dropdown menu. Everything works fine I just need to change it so that the submenuheader class allows it to be a clickable link. Right now all that happens with for example Home has two submenus of About Us and Quality. When you click home it expands the dropdown. But I want it to expand and also direct to a Home page. thanks in advance!


Expand|Select|Wrap|Line Numbers
  1. var ddaccordion={
  2.  
  3.     contentclassname:{}, //object to store corresponding contentclass name based on headerclass
  4.  
  5.     expandone:function(headerclass, selected){ //PUBLIC function to expand a particular header
  6.         this.toggleone(headerclass, selected, "expand")
  7.     },
  8.  
  9.     collapseone:function(headerclass, selected){ //PUBLIC function to collapse a particular header
  10.         this.toggleone(headerclass, selected, "collapse")
  11.     },
  12.  
  13.     expandall:function(headerclass){ //PUBLIC function to expand all headers based on their shared CSS classname
  14.         var $=jQuery
  15.         var $headers=$('.'+headerclass)
  16.         $('.'+this.contentclassname[headerclass]+':hidden').each(function(){
  17.             $headers.eq(parseInt($(this).attr('contentindex'))).trigger("evt_accordion")
  18.         })
  19.     },
  20.  
  21.     collapseall:function(headerclass){ //PUBLIC function to collapse all headers based on their shared CSS classname
  22.         var $=jQuery
  23.         var $headers=$('.'+headerclass)
  24.         $('.'+this.contentclassname[headerclass]+':visible').each(function(){
  25.             $headers.eq(parseInt($(this).attr('contentindex'))).trigger("evt_accordion")
  26.         })
  27.     },
  28.  
  29.     toggleone:function(headerclass, selected, optstate){ //PUBLIC function to expand/ collapse a particular header
  30.         var $=jQuery
  31.         var $targetHeader=$('.'+headerclass).eq(selected)
  32.         var $subcontent=$('.'+this.contentclassname[headerclass]).eq(selected)
  33.         if (typeof optstate=="undefined" || optstate=="expand" && $subcontent.is(":hidden") || optstate=="collapse" && $subcontent.is(":visible"))
  34.             $targetHeader.trigger("evt_accordion")
  35.     },
  36.  
  37.     expandit:function($targetHeader, $targetContent, config, useractivated){
  38.         $targetContent.slideDown(config.animatespeed, function(){config.onopenclose($targetHeader.get(0), parseInt($targetHeader.attr('headerindex')), $targetContent.css('display'), useractivated)})
  39.         this.transformHeader($targetHeader, config, "expand")
  40.     },
  41.  
  42.     collapseit:function($targetHeader, $targetContent, config, isuseractivated){
  43.         $targetContent.slideUp(config.animatespeed, function(){config.onopenclose($targetHeader.get(0), parseInt($targetHeader.attr('headerindex')), $targetContent.css('display'), isuseractivated)})
  44.         this.transformHeader($targetHeader, config, "collapse")
  45.     },
  46.  
  47.     transformHeader:function($targetHeader, config, state){
  48.         $targetHeader.addClass((state=="expand")? config.cssclass.expand : config.cssclass.collapse) //alternate btw "expand" and "collapse" CSS classes
  49.         .removeClass((state=="expand")? config.cssclass.collapse : config.cssclass.expand)
  50.         if (config.htmlsetting.location=='src'){ //Change header image (assuming header is an image)?
  51.             $targetHeader=($targetHeader.is("img"))? $targetHeader : $targetHeader.find('img').eq(0) //Set target to either header itself, or first image within header
  52.             $targetHeader.attr('src', (state=="expand")? config.htmlsetting.expand : config.htmlsetting.collapse) //change header image
  53.         }
  54.         else if (config.htmlsetting.location=="prefix") //if change "prefix" HTML, locate dynamically added ".accordprefix" span tag and change it
  55.             $targetHeader.find('.accordprefix').html((state=="expand")? config.htmlsetting.expand : config.htmlsetting.collapse)
  56.         else if (config.htmlsetting.location=="suffix")
  57.             $targetHeader.find('.accordsuffix').html((state=="expand")? config.htmlsetting.expand : config.htmlsetting.collapse)
  58.     },
  59.  
  60.     urlparamselect:function(headerclass){
  61.         var result=window.location.search.match(new RegExp(headerclass+"=((\\d+)(,(\\d+))*)", "i")) //check for "?headerclass=2,3,4" in URL
  62.         if (result!=null)
  63.             result=RegExp.$1.split(',')
  64.         return result //returns null, [index], or [index1,index2,etc], where index are the desired selected header indices
  65.     },
  66.  
  67.     getCookie:function(Name){ 
  68.         var re=new RegExp(Name+"=[^;]+", "i") //construct RE to search for target name/value pair
  69.         if (document.cookie.match(re)) //if cookie found
  70.             return document.cookie.match(re)[0].split("=")[1] //return its value
  71.         return null
  72.     },
  73.  
  74.     setCookie:function(name, value){
  75.         document.cookie = name + "=" + value + "; path=/"
  76.     },
  77.  
  78.     init:function(config){
  79.     document.write('<style type="text/css">\n')
  80.     document.write('.'+config.contentclass+'{display: none}\n') //generate CSS to hide contents
  81.     document.write('<\/style>')
  82.     jQuery(document).ready(function($){
  83.         ddaccordion.urlparamselect(config.headerclass)
  84.         var persistedheaders=ddaccordion.getCookie(config.headerclass)
  85.         ddaccordion.contentclassname[config.headerclass]=config.contentclass //remember contentclass name based on headerclass
  86.         config.cssclass={collapse: config.toggleclass[0], expand: config.toggleclass[1]} //store expand and contract CSS classes as object properties
  87.         config.revealtype=/^(click)|(mouseover)$/i.test(config.revealtype)? config.revealtype.replace(/mouseover/i, "mouseenter") : "click"
  88.         config.htmlsetting={location: config.togglehtml[0], collapse: config.togglehtml[1], expand: config.togglehtml[2]} //store HTML settings as object properties
  89.         config.oninit=(typeof config.oninit=="undefined")? function(){} : config.oninit //attach custom "oninit" event handler
  90.         config.onopenclose=(typeof config.onopenclose=="undefined")? function(){} : config.onopenclose //attach custom "onopenclose" event handler
  91.         var lastexpanded={} //object to hold reference to last expanded header and content (jquery objects)
  92.         var expandedindices=ddaccordion.urlparamselect(config.headerclass) || ((config.persiststate && persistedheaders!=null)? persistedheaders : config.defaultexpanded)
  93.         if (typeof expandedindices=='string') //test for string value (exception is config.defaultexpanded, which is an array)
  94.             expandedindices=expandedindices.replace(/c/ig, '').split(',') //transform string value to an array (ie: "c1,c2,c3" becomes [1,2,3]
  95.         var $subcontents=$('.'+config["contentclass"])
  96.         if (expandedindices.length==1 && expandedindices[0]=="-1") //check for expandedindices value of [-1], indicating persistence is on and no content expanded
  97.             expandedindices=[]
  98.         if (config["collapseprev"] && expandedindices.length>1) //only allow one content open?
  99.             expandedindices=[expandedindices.pop()] //return last array element as an array (for sake of jQuery.inArray())
  100.         if (config["onemustopen"] && expandedindices.length==0) //if at least one content should be open at all times and none are, open 1st header
  101.             expandedindices=[0]
  102.         $('.'+config["headerclass"]).each(function(index){ //loop through all headers
  103.             if (/(prefix)|(suffix)/i.test(config.htmlsetting.location) && $(this).html()!=""){ //add a SPAN element to header depending on user setting and if header is a container tag
  104.                 $('<span class="accordprefix"></span>').prependTo(this)
  105.                 $('<span class="accordsuffix"></span>').appendTo(this)
  106.             }
  107.             $(this).attr('headerindex', index+'h') //store position of this header relative to its peers
  108.             $subcontents.eq(index).attr('contentindex', index+'c') //store position of this content relative to its peers
  109.             var $subcontent=$subcontents.eq(index)
  110.             var needle=(typeof expandedindices[0]=="number")? index : index+'' //check for data type within expandedindices array- index should match that type
  111.             if (jQuery.inArray(needle, expandedindices)!=-1){ //check for headers that should be expanded automatically (convert index to string first)
  112.                 if (config.animatedefault==false)
  113.                     $subcontent.show()
  114.                 ddaccordion.expandit($(this), $subcontent, config, false) //Last Boolean value sets 'isuseractivated' parameter
  115.                 lastexpanded={$header:$(this), $content:$subcontent}
  116.             }  //end check
  117.             else{
  118.                 $subcontent.hide()
  119.                 config.onopenclose($(this).get(0), parseInt($(this).attr('headerindex')), $subcontent.css('display'), false) //Last Boolean value sets 'isuseractivated' parameter
  120.                 ddaccordion.transformHeader($(this), config, "collapse")
  121.             }
  122.         })
  123.         $('.'+config["headerclass"]).bind("evt_accordion", function(){ //assign custom event handler that expands/ contacts a header
  124.                 var $subcontent=$subcontents.eq(parseInt($(this).attr('headerindex'))) //get subcontent that should be expanded/collapsed
  125.                 if ($subcontent.css('display')=="none"){
  126.                     ddaccordion.expandit($(this), $subcontent, config, true) //Last Boolean value sets 'isuseractivated' parameter
  127.                     if (config["collapseprev"] && lastexpanded.$header && $(this).get(0)!=lastexpanded.$header.get(0)){ //collapse previous content?
  128.                         ddaccordion.collapseit(lastexpanded.$header, lastexpanded.$content, config, true) //Last Boolean value sets 'isuseractivated' parameter
  129.                     }
  130.                     lastexpanded={$header:$(this), $content:$subcontent}
  131.                 }
  132.                 else{
  133.                     ddaccordion.collapseit($(this), $subcontent, config, true) //Last Boolean value sets 'isuseractivated' parameter
  134.                 }
  135.          })
  136.         $('.'+config["headerclass"]).bind(config.revealtype, function(){
  137.             if (config.revealtype=="mouseenter"){
  138.                 ddaccordion.expandone(config["headerclass"], parseInt($(this).attr("headerindex")))
  139.             }
  140.             else{
  141.                 $(this).trigger("evt_accordion")
  142.                 return false //cancel default click behavior
  143.             }
  144.         })
  145.         config.oninit($('.'+config["headerclass"]).get(), expandedindices)
  146.         $(window).bind('unload', function(){ //clean up and persist on page unload
  147.             $('.'+config["headerclass"]).unbind()
  148.             var expandedindices=[]
  149.             $('.'+config["contentclass"]+":visible").each(function(index){ //get indices of expanded headers
  150.                 expandedindices.push($(this).attr('contentindex'))
  151.             })
  152.             if (config.persiststate==true){ //persist state?
  153.                 expandedindices=(expandedindices.length==0)? '-1c' : expandedindices //No contents expanded, indicate that with dummy '-1c' value?
  154.                 ddaccordion.setCookie(config.headerclass, expandedindices)
  155.             }
  156.         })
  157.     })
  158.     }
  159. }
Dec 1 '08 #1
Share this Question
Share on Google+
17 Replies


Dormilich
Expert Mod 5K+
P: 8,639
@Nyris
but why should it expand when it instantly leads the user to the "home" site without the chance to go to"About Us" or "Quality"? or asked the other way round, how is the user supposed to get to "quality" (despite the fact that he probably couldn't read, that the site is named so).

regards
Dec 1 '08 #2

P: 22
The home page has announcments and what not that are important. So once the user directs him/herself to a different page right now there's no way to get back to the homepage unless you hit the back button however many times you need to.
Dec 1 '08 #3

Dormilich
Expert Mod 5K+
P: 8,639
there are some ways out
- define the top level links unclickable (removing the href attribute), so the onclick will show up the menu. along with this event add the href attribute, so that the element becomes a full working link element.
- use 2 onclick events. the first one to show up the submenu and adding the second event to the top level element (the second event must not be present from the start)
- use a CSS dropdown menu. there you don't need javascript at all (except for the IE hacks)

I recommend the last option.

regards
Dec 2 '08 #4

P: 22
Sorry for the delay! Thanks for the suggestions so far. However, I didn't write this. It was something that was premade and put into the website. Unfortuntely I have absolutely no javascript experience and I'm trying to decipher all this with little sucess. Could you point out the areas where I need to change to add the second onclick event?
Dec 19 '08 #5

Dormilich
Expert Mod 5K+
P: 8,639
If I had a say, I'd switch to CSS dropdown menu. this minimizes javascript to a minimum (it's only needed for IE hacks).

CSS dropdowns are pretty standard nowadays, see Son of Suckerfish Dropdowns | HTML Dog.

regards
Dec 19 '08 #6

P: 22
Thanks for the link. I see how this works and how it's a lot better than the javascript version. However, I need it to be horizontal and when a certain submenu is opened it stays opened. Is that possible? This was the reason to why I was leaning towards fixing the javascript code.
Dec 19 '08 #7

Dormilich
Expert Mod 5K+
P: 8,639
@Nyris
that's just a matter of the used CSS. see Pure CSS Menus.
@Nyris
what do you mean? the dropdown stays open as long as the mouse hovers over either the submenu or the submenu's parent link.

@Nyris
that's why I recommended it in the first place.

regards
Dec 19 '08 #8

P: 22
The website is FSIP. Take a look at that and you can see what the navigation looks like now.
Dec 19 '08 #9

Dormilich
Expert Mod 5K+
P: 8,639
so you didn't want to go for the nested lists? well, everything is fine, as long as you're satisfied. I'm glad I could help you solve the issue.

regards
Dec 19 '08 #10

P: 22
No no! This is what the navigation looks like now. What I need it to do is when you click on the header menu's I want it to go to that page as well as open up the submenus. I haven't changed anything yet. ^_^b
Dec 19 '08 #11

Dormilich
Expert Mod 5K+
P: 8,639
in the CSS dropdown the submenu will open if the mouse pointer touches the appropriate link (the last link had a working sample, as I recall). so boldly speaking CSS dropdown doesn't depend on click events.

by speaking of opening the submenus—where do you want the submenus to show up (there's a whole lot of possibilities, only limited by you imagination)?
Dec 19 '08 #12

P: 22
I would like to expand beneath the header like it does now. That's what the boss wants! haha
Dec 19 '08 #13

Dormilich
Expert Mod 5K+
P: 8,639
should be possible, you have to play around with the CSS a bit, though.
Dec 19 '08 #14

acoder
Expert Mod 15k+
P: 16,027
Nyris, are you going the CSS route or are you sticking to JavaScript? If you're changing to CSS, I'll move this thread over to the HTML/CSS forum.
Dec 19 '08 #15

P: 22
I want to try it with CSS, yes. Though I'll probably need some help with it. I know absolutely nothing about Javascript. Trying to edit the file now to get it to do what I want is less likely to happen haha.
Dec 22 '08 #16

acoder
Expert Mod 15k+
P: 16,027
Moved thread to the HTML/CSS forum and edited the title to reflect the change in direction.

Moderator.
Dec 22 '08 #17

drhowarddrfine
Expert 5K+
P: 7,435
The only way to have the submenu open is if you send the html that way. CSS will not do this automatically.
Dec 23 '08 #18

Post your reply

Sign in to post your reply or Sign up for a free account.