www.webdeveloper.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 16

Thread: Drop Down Menu - delay timing + hiding functions

  1. #1
    Join Date
    Nov 2008
    Posts
    8

    Drop Down Menu - delay timing + hiding functions

    Hi everyone,

    I'm new to this forum, and somewhat new to Javascript, so I'd greatly appreciate any help you can provide with my problem.

    I'm working on a drop down menu for a website, and it is supposed to be a vertical dropdown menu where the submenu items appear below the menu item and thereby moving the menu items further down the page. Also there should be a timing element implemented to delay the disappearing of submenu items onmouseout (about a second or two).

    I've implemented a timing element within the JS using setTimeOut which is working fine. However the issue I've come across is when you move the mouse from one menu or submenu item to the next menu item, the next menu will trigger showing the submenu items but the previous submenu items will not disappear. However "logically" one would think that it's because if the submenu items would disappear it would rearrange the location of where the current menu and submenu items would be (moving them up). However I also noticed that if you move off the 2nd triggered menu item the first menu item and submenu items would not disappear. Someone suggested using jquery and using the line $('ul.cssdropdown').css('display', 'none'); to select and hide all the other ul's before showing the new ones. I've tried it out and it's not working. Here is the code before using jQuery. It's easier to see what kind of problem I'm talking about by running this code and playing with the mouseover/out triggers yourselves.

    <html>
    <head>
    <style type="text/css">
    #cssdropdown li.headlink ul { display: none; }
    </style>
    <script language="JavaScript">
    window.onload = function()
    {
    var lis = document.getElementsByTagName('li');
    for(i = 0; i < lis.length; i++)
    {
    var li = lis[i];
    if (li.className == 'headlink')
    {
    var showing = 0;
    li.onmouseover = function() { self = this; showing = i; setTimeout(function(){ if (showing == i) self.getElementsByTagName('ul').item(0).style.display = 'block'; }, 500); }
    li.onmouseout = function() { self = this; showing = 0; setTimeout(function(){ if (showing == 0) self.getElementsByTagName('ul').item(0).style.display = 'none'; }, 1000); }
    }
    }
    }
    </script>

    </head>

    <body>
    <ul id="cssdropdown">
    <li class="headlink"><a href="menu.html" class="headerCssClass">MENU</a>
    <ul>
    <li><a href="submenu1.html" class="itemCssClass">SUBMENU1</a></li>
    <li><a href="submenu2.html" class="itemCssClass">SUBMENU2</a></li>
    <li><a href="submenu3.html" class="itemCssClass">SUBMENU3</a></li>
    </ul>
    </li>
    </ul>
    <ul id="cssdropdown">
    <li class="headlink"><a href="menu.html" class="headerCssClass">MENU</a>
    <ul>
    <li><a href="submenu1.html" class="itemCssClass">SUBMENU1</a></li>
    <li><a href="submenu2.html" class="itemCssClass">SUBMENU2</a></li>
    <li><a href="submenu3.html" class="itemCssClass">SUBMENU3</a></li>
    </ul>
    </li>
    </ul>
    <ul id="cssdropdown">
    <li class="headlink"><a href="menu.html" class="headerCssClass">MENU</a>
    <ul>
    <li><a href="submenu1.html" class="itemCssClass">SUBMENU1</a></li>
    <li><a href="submenu2.html" class="itemCssClass">SUBMENU2</a></li>
    <li><a href="submenu3.html" class="itemCssClass">SUBMENU3</a></li>
    </ul>
    </li>
    </ul>
    </body>
    </html>

  2. #2
    Join Date
    Feb 2008
    Posts
    1,666
    I did this and got better behavior:
    HTML Code:
    <script type="text/javascript">
    var currentMenu = null;
    window.onload = function()
    {
        var lis = document.getElementsByTagName('li');
        for(i = 0; i < lis.length; i++)
        {
            var li = lis[i];
            if (li.className == 'headlink')
            {
                li.onmouseover = function()
                {
                    if (currentMenu) currentMenu.getElementsByTagName('ul').item(0).style.display = 'none';
                    var that = currentMenu = this;
                    setTimeout(function() { if (currentMenu==that) that.getElementsByTagName('ul').item(0).style.display = 'block'; }, 500);
                }
                li.onmouseout = function()
                {
                    var that = currentMenu = this;
                    setTimeout(function() { if (currentMenu==that) that.getElementsByTagName('ul').item(0).style.display = 'none'; currentMenu = null; }, 1000);
                }
            }
        }
    }
    </script>

  3. #3
    Join Date
    Nov 2008
    Posts
    8
    really? I tried using your code and I was getting very strange behaviour. What I saw was that when I moused over it would pop up for about half a second and then disappear without me moving the mouse at all. Even when I tried to mouse onto the newly triggered items, they would disappear before I could reach them.
    does this not happen with you?

    note: I basically copied and pasted your script over the corresponding section on my html script.
    Any suggestions?

  4. #4
    Join Date
    Feb 2008
    Posts
    1,666
    Yes, there is an issue of mousing off of the menu selection to the submenu selection which has to be dealt with using a timer cancellation mechanism. But when mousing just from the bottom menu selection immediately to the one above, you should see much better behavior. Also, there is one correction to what I posted:
    Code:
                li.onmouseout = function()
                {
                    var that = currentMenu = this;
                    setTimeout(function() { if (currentMenu==that) { that.getElementsByTagName('ul').item(0).style.display = 'none'; currentMenu = null; } }, 1000);
                }

  5. #5
    Join Date
    Nov 2008
    Posts
    8
    from the code you suggested, I'm still not seeing a fix in the problem. When I mouse on to the "menu" item, the submenu will pop up but disappear before I move my mouse. I can't see what you're saying about moving from the last item to the one above as there isn't anything above since it just flashes and disappears as mentioned.

    the entire code I'm using right now (with your modifications) is as follows:
    Code:
    <html>
    <head>
    <style type="text/css">
        #cssdropdown li.headlink ul { display: none; }
    </style>
    <script type="text/javascript">
    var currentMenu = null;
    window.onload = function()
    {
        var lis = document.getElementsByTagName('li');
        for(i = 0; i < lis.length; i++)
        {
            var li = lis[i];
            if (li.className == 'headlink')
            {
                li.onmouseover = function()
                {
                    if (currentMenu) currentMenu.getElementsByTagName('ul').item(0).style.display = 'none';
                    var that = currentMenu = this;
                    setTimeout(function() { if (currentMenu==that) that.getElementsByTagName('ul').item(0).style.display = 'block'; }, 500);
                }
                li.onmouseout = function()
                {
                    var that = currentMenu = this;
                    setTimeout(function() { if (currentMenu==that) { that.getElementsByTagName('ul').item(0).style.display = 'none'; currentMenu = null; } }, 1000);
                }
            }
        }
    }
    </script>
    
    </head>            
    
    <body>
    <ul id="cssdropdown">
          <li class="headlink"><a href="menu.html" class="headerCssClass">MENU</a>
          <ul>
                          <li><a href="submenu1.html" class="itemCssClass">SUBMENU1</a></li>
                          <li><a href="submenu2.html" class="itemCssClass">SUBMENU2</a></li>
                          <li><a href="submenu3.html" class="itemCssClass">SUBMENU3</a></li>
          </ul>
          </li> 
    </ul>
    <ul id="cssdropdown">
          <li class="headlink"><a href="menu.html" class="headerCssClass">MENU</a>
          <ul>
                          <li><a href="submenu1.html" class="itemCssClass">SUBMENU1</a></li>
                          <li><a href="submenu2.html" class="itemCssClass">SUBMENU2</a></li>
                          <li><a href="submenu3.html" class="itemCssClass">SUBMENU3</a></li>
          </ul>
          </li> 
    </ul>
    <ul id="cssdropdown">
          <li class="headlink"><a href="menu.html" class="headerCssClass">MENU</a>
          <ul>
                          <li><a href="submenu1.html" class="itemCssClass">SUBMENU1</a></li>
                          <li><a href="submenu2.html" class="itemCssClass">SUBMENU2</a></li>
                          <li><a href="submenu3.html" class="itemCssClass">SUBMENU3</a></li>
          </ul>
          </li> 
    </ul>
    </body>
    </html>

  6. #6
    Join Date
    Feb 2008
    Posts
    1,666
    This is the problem you described:
    Quote Originally Posted by pham View Post
    However the issue I've come across is when you move the mouse from one menu or submenu item to the next menu item, the next menu will trigger showing the submenu items but the previous submenu items will not disappear.
    I copied your code and tested it. The problem I noticed was when moving from the last MENU item to the MENU item above it. The submenu items for the last MENU item would not disappear when the submenu items for the second to last MENU item appeared. So, that is the issue I addressed. There is still an issue when going downward because the appearing and disappearing of submenu items plays havoc with the mouse position when you get several elements moving in and out of range without moving the mouse at all. But, as I said, applying a timer cancellation mechanism between menu item and submenu items is the fix for that. You know how to cancel timers?

    timer = setTimeout(...);

    clearTimeout(timer);

  7. #7
    Join Date
    Nov 2008
    Posts
    8
    I see... thanks for that clear up.

    No I don't really know how to put up a cancellation mechanism. Where would I apply those codes you listed at the bottom of your last post? Could you just copy/paste the JS section to make it clear?

  8. #8
    Join Date
    Feb 2008
    Posts
    1,666
    Basically, the mouseout setTimeout you've already got needs to start saving a pointer to its timer. That is the first line I posted. Then, you'd need a mouseover event for the submenu items. In that event is where you place the second line of code I posted in order to prevent the mouseout of the main menu entry from closing the submenu item entries.

  9. #9
    Join Date
    Nov 2008
    Posts
    8
    Quote Originally Posted by MrNobody View Post
    Basically, the mouseout setTimeout you've already got needs to start saving a pointer to its timer. That is the first line I posted. Then, you'd need a mouseover event for the submenu items. In that event is where you place the second line of code I posted in order to prevent the mouseout of the main menu entry from closing the submenu item entries.
    I see what you mean... but I'm not quite understanding where to put them. I'm guessing the timer = setTimeout function has to be within the setTimeout function of both onmouseover and onmouseout am I right? Could you show me what you mean with the sample code I've posted previously? Please and thanks.

  10. #10
    Join Date
    Feb 2008
    Posts
    1,666
    No, the mouseover event timer you have doesn't need to be saved -- just the mouseout event timer. Then you need a new event for the submenu items in which you'll place the timer cancellation.

  11. #11
    Join Date
    Nov 2008
    Posts
    8
    Quote Originally Posted by MrNobody View Post
    No, the mouseover event timer you have doesn't need to be saved -- just the mouseout event timer. Then you need a new event for the submenu items in which you'll place the timer cancellation.
    so how would i go about implementing a new event for the submenu items? any suggestions. Sorry if I really sound amateurish/childish here. Really haven't got a clue.

  12. #12
    Join Date
    Feb 2008
    Posts
    1,666
    So I take you didn't write the code you've got?

  13. #13
    Join Date
    Nov 2008
    Posts
    8
    admittedly, nail on the head sir

    I based it off of an online tutorial which wasn't very descriptive.

  14. #14
    Join Date
    Feb 2008
    Posts
    1,666
    OK, here it is:
    HTML Code:
    <script type="text/javascript">
    var currentMenu = null;
    var timer = null;
    window.onload = function()
    {
    	var lis = document.getElementsByTagName('li');
    	for(i = 0; i < lis.length; i++)
    	{
    		var li = lis[i];
    		if (li.className == 'headlink')
    		{
    			li.onmouseover = function()
    			{
    				if (currentMenu)
    				{
    				    if (timer) window.clearTimeout(timer);
    				    currentMenu.getElementsByTagName('ul').item(0).style.display = 'none';
    				}
    				var that = currentMenu = this;
    				window.setTimeout(function()
    				{
    				    if (currentMenu==that) that.getElementsByTagName('ul').item(0).style.display = 'block';
    				}, 500);
    				return true;
    			}
    			li.onmouseout = function()
    			{
    				var that = currentMenu = this;
    				timer = window.setTimeout(function()
    				{
    				    if (currentMenu==that)
    				    {
    				        that.getElementsByTagName('ul').item(0).style.display = 'none';
    				        currentMenu = null;
    				    }
    				}, 1000);
    				return true;
    			}
    			var lu = li.getElementsByTagName('ul').item(0);
    			lu.onmouseover = function(e)
    			{
    				if (timer) window.clearTimeout(timer);
    				if (e) e.cancelBubble = true;
    				else event.cancelBubble = true;
    				return true;
    			}
    		}
    	}
    }
    </script>

  15. #15
    Join Date
    Nov 2008
    Posts
    8
    thanks for the code there...

    I tried it out but I'm seeing an issue when mousing off the first/second set of submenu items. The submenu items should be delayed as you mouse onto the next set of menu+submenu items and then disappear afterwards. The only case where this works as expected is with the last menu+submenu set.

    the script is as follows:

    Code:
    <html>
    <head>
    <style type="text/css">
        #cssdropdown li.headlink ul { display: none; }
    </style>
    <script type="text/javascript">
    var currentMenu = null;
    var timer = null;
    window.onload = function()
    {
    	var lis = document.getElementsByTagName('li');
    	for(i = 0; i < lis.length; i++)
    	{
    		var li = lis[i];
    		if (li.className == 'headlink')
    		{
    			li.onmouseover = function()
    			{
    				if (currentMenu)
    				{
    				    if (timer) window.clearTimeout(timer);
    				    currentMenu.getElementsByTagName('ul').item(0).style.display = 'none';
    				}
    				var that = currentMenu = this;
    				window.setTimeout(function()
    				{
    				    if (currentMenu==that) that.getElementsByTagName('ul').item(0).style.display = 'block';
    				}, 1000);
    				return true;
    			}
    			li.onmouseout = function()
    			{
    				var that = currentMenu = this;
    				timer = window.setTimeout(function()
    				{
    				    if (currentMenu==that)
    				    {
    				        that.getElementsByTagName('ul').item(0).style.display = 'none';
    				        currentMenu = null;
    				    }
    				}, 3000);
    				return true;
    			}
    			var lu = li.getElementsByTagName('ul').item(0);
    			lu.onmouseover = function(e)
    			{
    				if (timer) window.clearTimeout(timer);
    				if (e) e.cancelBubble = true;
    				else event.cancelBubble = true;
    				return true;
    			}
    		}
    	}
    }
    </script>
    
    </head>            
    
    <body>
    <ul id="cssdropdown">
          <li class="headlink"><a href="menu.html" class="headerCssClass">MENU</a>
          <ul>
                          <li><a href="submenu1.html" class="itemCssClass">SUBMENU1</a></li>
                          <li><a href="submenu2.html" class="itemCssClass">SUBMENU2</a></li>
                          <li><a href="submenu3.html" class="itemCssClass">SUBMENU3</a></li>
          </ul>
          </li> 
          <li class="headlink"><a href="menu.html" class="headerCssClass">MENU</a>
          <ul></lu>
                          <li><a href="submenu1.html" class="itemCssClass">SUBMENU1</a></li>
                          <li><a href="submenu2.html" class="itemCssClass">SUBMENU2</a></li>
                          <li><a href="submenu3.html" class="itemCssClass">SUBMENU3</a></li>
          </ul>
          </li> 
          <li class="headlink"><a href="menu.html" class="headerCssClass">MENU</a>
          <ul>
                          <li><a href="submenu1.html" class="itemCssClass">SUBMENU1</a></li>
                          <li><a href="submenu2.html" class="itemCssClass">SUBMENU2</a></li>
                          <li><a href="submenu3.html" class="itemCssClass">SUBMENU3</a></li>
          </ul>
          </li> 
    </ul>
    </body>
    </html>
    May it's just me, I don't really notice much of a difference between this and the original code.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles