Reputation: 316
So I have this drop down menu that is supposed to have slightly delayed drop on hover, but it doesn't drop at all.
My HTML:
<div class="container">
<ul class="menu">
<li class="overflow-hidden">one
<div class="submenu">test</div>
</li>
<li class="overflow-hidden">two</li>
<li class="overflow-hidden">three</li>
</ul>
</div>
CSS
.menu {
display: block;
width: 100%;
margin: 0;
padding: 0;
}
.overflow-hidden {
display: inline-block;
width: 33%;
height: 20px;
text-align: center;
overflow: hidden;
cursor: pointer;
}
.submenu {
display: block;
height: 200px;
background-color: #999;
}
.container {
width: 100%;
}
What have I missed?
Upvotes: 0
Views: 151
Reputation: 337
There are a few things you can do to improve your code and make it work:
Document Ready event. you should initialize your code after the DOM has rendered, otherwise your code may be trying to attach events to things that aren't there yet!
$(document).ready(function(){
menuHover();
$('.submenu').width(menuWidth);
});
Scope. Referring to $(this)
inside the timer object will not be referring to what you think! Define the element you want to refer to at the top of your function, and you can then safely use this explicit definition in any functions defined within the same scope, and you won't have to worry about their own 'this' being something different.
function () {
var $listItem = $(this);
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function () {
$listItem.css('overflow', 'visible');
}, 200);
}
Semantics. Naming your list items overflow-hidden
is semantically bad practice (that is a style not a name!) ... especially when the item is in the overflow-visible
state!. It would be advisable to probably remove this altogether and target your list items by something like .menu li
or giving them their own class eg. menu-item
.
var menuWidth = $('.container').width();
var menuHover = function () {
var timer;
$(".menu li").hover(
function () {
var $listItem = $(this);
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function () {
$listItem.css('overflow', 'visible');
}, 200);
},
function () {
var $listItem = $(this);
clearTimeout(timer);
timer = null;
$listItem.css('overflow', 'hidden');
});};
$(document).ready(function(){
menuHover();
$('.submenu').width(menuWidth);
});
Upvotes: 2
Reputation: 16716
CSS3 Transitions
With the use of transition (-webkit,-moz,-ms) you don't even need javascript.
You can use the class or id to control sub elements.
CSS
#menu{
}
#menu>div{
width:33%;
float:left;
height:20px;
background-color:grey;
}
#menu>div>div:nth-child(1){
line-height:20px;
text-align:center;
}
#menu>div>div:nth-child(2){
overflow:hidden;
height:0px;
transition:height 700ms ease 500ms;
/*
the duration is 700milliseconds and the delay is 500milliseconds
*/
background-color:#cc2;
padding:0 16px;
}
#menu>div:hover>div:nth-child(2){
height:20px;
}
HTML
<div id="menu">
<div><div>one</div><div>1</div></div>
<div><div>two</div><div>2</div></div>
<div><div>three</div><div>3</div></div>
</div>
DEMO
Upvotes: 1
Reputation: 4090
you do not need jquery for this, you can use the pseudo class :hover
See this fiddle: http://jsfiddle.net/yA6Lx/14/
.overflow:hover .submenu{
visibility: visible;
opacity: 1;
}
Upvotes: 0
Reputation: 543
You got two things totally wrong.
First: You're missing the jQuery ready event1.
Second: You didn't think about the scope2. $(this) is not available in setTimeout();
$(function(){ // (1a) jQuery ready start
var menuWidth = $('.container').width();
var menuHover = function(){
var timer;
$(".overflow-hidden").hover(
function(){
if(timer){
clearTimeout(timer);
timer = null;
}
var temporary_element = $(this); // (2a) Store element in temporary variable
timer = setTimeout(function(){
temporary_element.css('overflow', 'visible'); // (2b) Get the stored element from the parent scope
}, 200);
},
function(){
clearTimeout(timer);
timer = null;
$(this).css('overflow', 'hidden');
}
);
};
menuHover();
$('.submenu').width(menuWidth);
}); // (1b) jQuery ready end
Upvotes: 1
Reputation: 51
.menu {
display: block;
width: 100%;
margin: 0;
padding: 0;
background-color: green;
}
.overflow-hidden {
display: inline-block;
width: 33%;
height: 20px;
text-align: center;
position: relative;
cursor: pointer;
}
.submenu {
display: none;
}
.overflow-hidden:hover .submenu {
display: inline-block;
height: 200px;
background-color: #999;
z-index: 1;
width: 100%;
position: absolute;
left: 0;
top: 20px;
}
.container {
width: 100%;
}
Upvotes: 0