We help IT Professionals succeed at work.

Hiding multiple divs using setTimeOut

Rouchie
Rouchie asked
on
588 Views
Last Modified: 2010-07-27
In an effort to improve my javaScript skills I've written a *basic* script to show popup menu's underneath a row of hyperlinks.  The idea is that once the cursor moves away from the hyperlink/displayed menu, then after a short delay the menu disappears.

The problem is that if I hover over 1 link, then immediately hover over another, the first popup menu never disappears because the first timer gets overwritten by the second timer.

Therefore, can anyone help me fine tune this script to correct make each popup menu disappear after a given time delay?

<script type="text/javascript">
            /* <![CDATA[ */
            var counterVar;
            
            function displayMenu(hoverMenuID, linkID){
                  var menu = document.getElementById(hoverMenuID);
                  if (menu) {
                        var positionToShowArray = findPos(linkID);
                        menu.style.left = positionToShowArray[0] + 'px';
                        menu.style.top = positionToShowArray[1] + 'px';
                        menu.style.display = '';
                        window.clearTimeout(counterVar);
                  }
            }
            
            function startCountDownForHidingMenu(hoverMenuID){
                  if (document.getElementById(hoverMenuID)) {
                        counterVar = window.setTimeout("hideMenu('"+hoverMenuID+"')", 1000);
                  }
            }
            
            function hideMenu(hoverMenuID){
                  var menu = document.getElementById(hoverMenuID);
                  if (menu) {
                        menu.style.display = 'none';
                  }
            }
            
            function findPos(obj) {
                  // omitted for brevity
            }
            /* ]]> */
      </script>
Comment
Watch Question

Commented:
Maybe this is a stupid question, but why does the timeout need to be cleared when you mouse over the new menu item?  It seems like if you just let the timeout happen, it'd make the old menu disappear after a second, and your mouseover could happen by itself.

The only case I can see where it might be an issue would be if you mouseover the item that you just moused out of, but off the top of my head, I figure you can probably add a check for the ID's to prevent that.

Or is there something I'm overlooking?
CERTIFIED EXPERT

Author

Commented:
>> The only case I can see where it might be an issue would be if you mouseover the item that you just moused out of, but off the top of my head

Yes that was the reason.  I didn't want menu's popping up that refused to disappear again!  My JS skills aren't too great so I was trying to keep it simple, but as long as I understand any answers here that make it work better then that's great!

Commented:
>> I didn't want menu's popping up that refused to disappear again!
I think the issue would actually be the opposite.  Since the timeout is set, it would hide the menu after a second, even if you just finished mousing back over that item.

So, I'd suggest keeping the ID of the item that's going to disappear.  If it matches the ID of the item you moused over, then you clear the timeout.  Otherwise, you can leave the timeout alone, and it'll do its thing.

Give this a shot as a means to implement that:
<script type="text/javascript">
            /* <![CDATA[ */
            var counterVar;
            var idToBeHidden;
           
            function displayMenu(hoverMenuID, linkID){
                  var menu = document.getElementById(hoverMenuID);
                  if (menu) {
                        var positionToShowArray = findPos(linkID);
                        menu.style.left = positionToShowArray[0] + 'px';
                        menu.style.top = positionToShowArray[1] + 'px';
                        menu.style.display = '';
                        if (hoverMenuID == idToBeHidden)
                        {
                          window.clearTimeout(counterVar);
                          idToBeHidden = null;
                        }
                  }
            }
           
            function startCountDownForHidingMenu(hoverMenuID){
                  if (document.getElementById(hoverMenuID)) {
                        counterVar = window.setTimeout("hideMenu('"+hoverMenuID+"')", 1000);
                        idToBeHidden = hoverMenuID;
                  }
            }
           
            function hideMenu(hoverMenuID){
                  var menu = document.getElementById(hoverMenuID);
                  if (menu) {
                        menu.style.display = 'none';
                  }
            }
           
            function findPos(obj) {
                  // omitted for brevity
            }
            /* ]]> */
      </script>

I haven't had time to test the above (sorry, it's been a hectic day), but the idea is that you set a global ID variable whenever you set the timeout.  When you go to mouse over, you only clear the timeout if the ID of the item you moused over matches the global ID variable.  If they don't match, then you're dealing with separate menu items, and it's safe to hide.  

If you have issues, let us know.  Regardless, hope that helps.
CERTIFIED EXPERT

Author

Commented:
Hi dakyd,
Thanks for the post.  It does correctly hide the menus as I hoped, but there is one small problem:

The menus disappear when the mouse is hovered over the links within them.  So, the hover menu appears okay, but when you hover over a hover-menu link, the menu disappears (if that makes sense?)

It might be caused by the way I call the functions, but I'm confused...!

Commented:
What does the HTML look like for one of the menu items?  Also, how are the functions being called?  I can take a few educated guesses about the javascript, but not the HTML.
CERTIFIED EXPERT

Author

Commented:
Link to make the hover menu appear:

<a id="navbarLink05" onmouseover="displayMenu('about_hover', this)" onmouseout="startCountDownForHidingMenu('about_hover')" href="aboute4.aspx">About</a>

The hover menu div is like this:

<div id="products_hover" style="display:none;" onmouseover="displayMenu(this, 'navbarLink05')">
 <ul>
  <li>Link01</li>
  <li>Link02</li>
  <li>Link03</li>
 </ul>      
</div>

Commented:
So where is the <a> in relation to the <div> that contains the sub-menu?

It looks like you're already using a list for the sub-menu items, is the <a> also a part of a list structure?
CERTIFIED EXPERT

Author

Commented:
Yes the link is part of a list of links.  There are 2 hover menu div's, and these are directly underneath the link-list in the code, although their CSS rules dictate they obviously aren't shown.    The function called findPos(obj) places and displays each hover menu is the correct place.
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
CERTIFIED EXPERT

Author

Commented:
The problem is that the suckerfish menu seems to rely on the list items being floated left.  The sub-menus can then appear directly underneath.  Normally this would be great but because my list is centered, the menus don't appear in the correct place.

I will investigate a padding attribute on the lists to see if I can correct it using the suckerfish script, but I would prefer my original script to correctly hide the menus if that's possible??
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.