jQuery hover menu not disappearing
- by Nathan Loding
I have a basic menu using some nested UL's, which is pretty standard I think. When hovering over an LI from the "root" menu, I want the UL within that LI to display. Move the mouse off or to another LI, it shows that submenu. Move down to the submenu and it stays while you hover over each element. I had it working with a simple jQuery.hover() set, but then I ran into issues. When on a page, the "root" menu item is given a class of 'current-page' and if that class exists, I want it to display that submenu statically after a mouseout.
Hope I explained that well enough. I just tossed a variable into the hover functions so on the mouseout it ran a .show() on the current-page's submenu. Easy. Except that when I move the mouse between the individual LI's of the submenu, it changes back to the current-page submenu. So I attempted to add a timer element based on another question here. That made things worse -- now the submenus just don't disappear.
Here's my CSS, markup, and JS ... how the heck do I make this work properly?
Markup:
<div id="menu">
<div id="navbar">
<ul id="firstmenu">
<li>
<a href="http://localhost/site/pageone">page one</a>
<ul class="submenu">
<li><a href="http://localhost/site/pageone/subone">subone</a></li>
<li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li>
<li><a href="http://localhost/site/pageone/subthree">subthree</a></li>
<li><a href="http://localhost/site/pageone/subfour">subfour</a></li>
<li><a href="http://localhost/site/pageone/subfive">subfive</a></li>
</ul>
</li>
<li>
<a href="http://localhost/site/pagetwo">barely there</a>
<ul class="submenu">
<li><a href="http://localhost/site/pageone/subone">subone</a></li>
<li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li>
<li><a href="http://localhost/site/pageone/subthree">subthree</a></li>
<li><a href="http://localhost/site/pageone/subfour">subfour</a></li>
<li><a href="http://localhost/site/pageone/subfive">subfive</a></li>
</ul>
</li>
<li class="current-page">
<a href="http://localhost/site/pagetwo">kith & kin</a>
<ul class="submenu">
<li><a href="http://localhost/site/pageone/subone">subone</a></li>
<li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li>
<li><a href="http://localhost/site/pageone/subthree">subthree</a></li>
<li><a href="http://localhost/site/pageone/subfour">subfour</a></li>
<li><a href="http://localhost/site/pageone/subfive">subfive</a></li>
</ul>
</li>
<li>
<a href="http://localhost/site/pagethree">focal point</a>
<ul class="submenu">
<li><a href="http://localhost/site/pageone/subone">subone</a></li>
<li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li>
<li><a href="http://localhost/site/pageone/subthree">subthree</a></li>
<li><a href="http://localhost/site/pageone/subfour">subfour</a></li>
<li><a href="http://localhost/site/pageone/subfive">subfive</a></li>
</ul>
</li>
<li>
<a href="http://localhost/site/pagefour">products</a>
<ul class="submenu">
<li><a href="http://localhost/site/pageone/subone">subone</a></li>
<li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li>
<li><a href="http://localhost/site/pageone/subthree">subthree</a></li>
<li><a href="http://localhost/site/pageone/subfour">subfour</a></li>
<li><a href="http://localhost/site/pageone/subfive">subfive</a></li>
</ul>
</li>
<li>
<a href="http://localhost/site/pagefive">clients</a>
</li>
</ul>
</div></div>
And here's the CSS:
#navbar {
margin: 0;
padding: 0;
border: 0;
text-align: center;
}
#firstmenu {
margin: 6px auto 0 auto;
font-size: 16px;
list-style-type: none;
letter-spacing: -1px;
}
#firstmenu li {
display: inline;
position:relative;
overflow: hidden;
text-align: center;
margin-right: 10px;
padding: 5px 15px;
}
#firstmenu a {
text-decoration: none;
outline: none;
color: black;
font-weight: 700;
width: 75px;
cursor: pointer;
}
.current-page {
color: white;
background: url(../images/down_arrow.png) bottom center no-repeat;
}
.current-page a {
color: white;
border-bottom: 1px solid black;
}
#firstmenu .current-page a {
color: white;
}
#firstmenu li.hover {
color: white;
background: url(../images/down_arrow.png) bottom center no-repeat;
}
#firstmenu li.hover a {
color: white;
border-bottom: 1px solid black;
}
#firstmenu li ul li.hover {
color: white;
background: none;
}
#firstmenu li ul li.hover a {
color: white;
border-bottom: none;
text-decoration: underline;
}
#firstmenu li ul {
width: 900px;
color: white;
font-size: .8em;
margin-top: 3px;
padding: 5px;
position: absolute;
display: none;
}
#firstmenu li ul li {
list-style: none;
display: inline;
width: auto;
}
#firstmenu li ul li a {
color: white;
font-weight: normal;
border: none;
}
.sub-current-page {
font-weight: bold;
text-decoration: underline;
}
#firstmenu li ul li.sub-current-page a {
font-weight: bold;
}
And lastly, my not-at-all-working JS (this is in a $(document).ready(), of course):
// Initialize some variables
var hideSubmenuTimer = null;
var current_page;
$('.current-page ul:first').show();
// Prep the menu
$('#firstmenu li').hover(function() {
// Clear the timeout if it exists
if(hideSubmenuTimer) { clearTimeout(hideSubmenuTimer); }
// Check if there's a current-page class set
if($('li.current-page').length > 0) {
current_page = $('li.current-page');
} else {
current_page = false;
}
// If there's a current-page class, hide it
if(current_page) { current_page.children('ul:first').hide(); }
// Show the new submenu
$(this).addClass('hover').children('ul:first').show();
}, function(){
// Just in case
var self = this;
// Clear the timeout if it exists
if(hideSubmenuTimer) { clearTimeout(hideSubmenuTimer); }
// Check if there's a current-page class set
if($('li.current-page').length > 0) {
current_page = $('li.current-page');
} else {
current_page = false;
}
// Set a timeout on hiding the submenu
hideSubmenuTimer = setTimeout(function() {
// Hide the old submenu
$(self).removeClass('hover').children('ul').hide();
// If there's a current-page class, show it
if(current_page) { current_page.children('ul:first').show(); current_page.css('color', 'white'); }
}, 500);
});
So what am I doing so wrong?
As a side note, I'm using the $('.current-page ul:first').show() because if I gave .current-page any "display" setting in the CSS, it positioned it really weirdly on the page.