www.webdeveloper.com
Results 1 to 10 of 10

Thread: onmouseout executed although mouse doesn't leave

  1. #1
    Join Date
    Jun 2010
    Posts
    4

    onmouseout executed although mouse doesn't leave

    OK that's my HTML:

    Code:
    	<div id="menubar" onmouseover="show_menu()" onmouseout="hide_menu()">
    				<p id="current">Welcome</p>
    				<ul id="menu">
    					<li><a href="#">Blah</a></li>
    					<li><a href="#">Halb</a></li>
    				</ul>
    			</div>
    and I have two JS functions.
    The unexpected behavior-problem is that wherever the pointer moves between the the <li> elements (next or previous), the whole hide_menu() and show_menu() is executed as if the pointer got out of the div space and re-entered.
    Any idea why this happens?

    Testing on Safari 5 and FF 3.58

  2. #2
    Join Date
    Mar 2010
    Posts
    2,803
    sounds really strange unless it is some browser specific "feature".

    If you post all your html, js and css hopefully we will see what else might be going on.

  3. #3
    Join Date
    Mar 2010
    Posts
    23
    This is known as bubbling. More information here: http://www.quirksmode.org/js/events_order.html

  4. #4
    Join Date
    Jun 2010
    Posts
    4
    Ok let me show the code first, although it doesn't really matter:

    HTML
    Code:
    <div id="menubar" onmouseover="show_menu()" onmouseout="hide_menu()">
    <p id="current">Καλώς ήλθατε. Βρίσκεστε στην αρχική σελίδα.</p>
    <ul id="menu">
    	<li><a href="#">Blah</a></li>
    	<li><a href="#">Halb</a></li>
    </ul>
    </div>
    CSS:
    Code:
    div#menubar p#current
    {
    	display: inline;
    
    }
    div#menubar ul#menu
    {
    	display: none;
    }
    /* rest is styling */
    /* PS: div size is fixed */
    JS:
    Code:
    function show_menu()
    {
    	document.getElementById('current').style.display = 'none';
    	menu = document.getElementById('menu');
    	menu.style.visibility = 'hidden';
    	menu.style.display = 'block';
    	set_opacity(menu, 0);
    	menu.style.visibility = 'visible';
    	fade_in('menu', 0, 30);
    }
    
    function hide_menu()
    {
    	document.getElementById('menu').style.display = 'none';
    	document.getElementById('current').style.display = '';
    }

    Representation:
    +覧覧覧覧覧覧+
    || That's my div. No matter what's displayed in the
    +覧覧覧覧覧覧+ DIV, either the <p> or the <ul>, as long as the mouse doesn't leave the block is shouldn't run the js again and again.

    So, when my DIV is like
    +覧覧覧覧覧覧+
    |LI~LI~LI~LI~LI~LI~LI~LI|
    +覧覧覧覧覧覧+
    when the mouse goes from one LI to another, the JS is run again and again. Why?

    There is no hint of bubbling or capturing, as the is only one handler, the one of the DIV.

  5. #5
    Join Date
    Jun 2004
    Location
    Portsmouth UK
    Posts
    2,668
    as Awais-Muzaffar said

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    
    <head>
      <title></title>
    <script type="text/javascript">
    /*<![CDATA[*/
    
    function hide_menu(obj){
     var e=window.event||arguments.callee.caller.arguments[0];
     if (e){
      var eobj=e.relatedTarget||e.toElement;
      if (eobj){
       while (eobj.parentNode){
        if (eobj==obj){
         return false;
        }
        eobj=eobj.parentNode;
       }
      }
     }
     document.Show.Show0.value=vic++;
    }
    
    /*]]>*/
    </script>
    
    </head>
    
    <body>
    <div id="menubar" onmouseout="hide_menu(this)">
    <p id="current">Καλώς ήλθατε. Βρίσκεστε στην αρχική σελίδα.</p>
    <ul id="menu">
    	<li><a href="#">Blah</a></li>
    	<li><a href="#">Halb</a></li>
    </ul>
    </div>
    <script> vic=0; </script>
    <form name=Show id=Show style="position:absolute;visibility:visible;top:420px;left:0px;" >
    <input size=100 name=Show0 >
    <input size=10 name=Show1 >
    <input size=10 name=Show2 >
    <input size=10 name=Show3 >
    <input size=10 name=Show4 >
    <input size=10 name=Show5 >
    <input size=10 name=Show6 >
    <input size=10 name=Show7 >
    <input size=10 name=Show8 >
    <input size=10 name=Show9 ><br>
    <textarea name=TA rows=1 cols=100 ></textarea>
    </form>
    </body>
    
    </html>
    Vic

    God loves you and will never love you less.

    http://www.vicsjavascripts.org/Home.htm
    If my post has been useful please donate to http://www.operationsmile.org.uk/

  6. #6
    Join Date
    Jul 2007
    Posts
    386
    The problem might be that when you open the menu. If the menu opens under the mouse then you are effectively leaving the <li> since the mouse just entered the menu's <div>.

  7. #7
    Join Date
    Jun 2010
    Posts
    4
    OK but since the menu thing is contained in another div, no matter if I leave the LI space, it shouldn't execute, since the handlers are for leaving the container div space.

    Right?

  8. #8
    Join Date
    Jul 2007
    Posts
    386
    Thing is, even if the menu is contained within the <div> with the event, moving the mouse over that <li>, or <ul> or <p> triggers the mouse out.

    Remember each HTML element is like a layer (w/o involving CSS position and z-index).

    The <div> is at the lowest level while the <p> and <ul> are above it. Even if they are within <div> they are a different element, therefore triggering the mouse out event of the <div>.

  9. #9
    Join Date
    Jun 2010
    Posts
    4
    Oh, I see.
    Any idea on how to overcome that?

  10. #10
    Join Date
    Jul 2007
    Posts
    386
    Yes, like vwphillips shows, you have to use event propagation. That is, when the mouse out is detected check to see whether is that element belongs or not to the one who called it.

    Check the script made by vwphillips:
    Code:
    function hide_menu(obj)
    {
        var e = window.event || arguments.callee.caller.arguments[0];
        
        if (e)
        {
            var eobj = e.relatedTarget || e.toElement;
            
            if (eobj)
            {
                while (eobj.parentNode)
                {
                    if (eobj==obj)
                    {
                         return false;
                    }
                    
                    eobj = eobj.parentNode;
                }
            }
        }
        
        document.Show.Show0.value = vic++;
    }
    Works as follows:
    When the mouseout event is called grab the window.event and lets see who called it (obj).
    Now, let's see which element was focused that triggered the mouseout event (eObj).

    While eObj has a parentNode, cycle through them. If at any point you find that eObj is contained withing obj (eObj == obj), then stop the script (return false), other wise, close the menu.
    Last edited by SparoHawk; 06-16-2010 at 11:44 AM.

Thread Information

Users Browsing this Thread

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

Tags for this Thread

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