EDIT: See this in action here: http://jsbin.com/emobi/5 -- and that's using mouseenter/mouseleave.
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.
The answer is that the script was attempting to run the hover/mouseenter/whatever functions on the LI's of the submenu. By giving each of the root menu LI's their own class, it now works. That way it's not calling the functions on the submenu LI's. Here's the finished function:
$('#firstmenu .root-item').mouseenter(function() {
$(this).addClass('hover').children('ul:first').show();
if($('.current-page').length > 0) {
$('.current-page').children('ul:first').hide();
}
}).mouseleave(function() {
$(this).removeClass('hover').children('ul').hide();
if($('.current-page').length > 0) {
$('.current-page').children('ul:first').show();
}
});
Why are you messing with timeouts? Should you just .toggle()
?
I rewrote it to not use hover, but mouseover and mouseout. Not sure if you like it but here is the code:
$(document).ready(function(){
$(".submenu").hide();
$("li").mouseover(function(){
$(this).find('.submenu').show();
});
$("li").mouseout(function(){
$(this).find('.submenu').hide();
})
});
edit: I took the time to review your code and found the offending line:
#firstmenu li {
display: inline;
Since the nested lists are inside of the first menu div this applies to them too. A nested list inlined cannot be placed and thus no longer placed as a child of its dom parent in the layout engine. The result is that mousing over the submenu is still considered mousing over its dom parent (due to bubbling), but between list items you will no longer be mousing over the dom parent (as it is in the original design). You need to rethink your layout design, because right now its breaking the layout engine.
You should probably also rethink using lists as tables...
精彩评论