Marek
Marek

Reputation: 316

drop down menu with delay - not working

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

Answers (5)

dSkech
dSkech

Reputation: 337

There are a few things you can do to improve your code and make it work:

  1. 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);
    });
    
  2. 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);
    }
    
  3. 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

cocco
cocco

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

http://jsfiddle.net/95wM2/

Upvotes: 1

Jose Paredes
Jose Paredes

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

Sven Finger
Sven Finger

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

Norbrecht
Norbrecht

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

Related Questions