SitePoint Sponsor

User Tag List

Results 1 to 11 of 11
  1. #1
    SitePoint Evangelist
    Join Date
    Jan 2005
    Posts
    425
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Help with displaying/hiding div drop down

    The code below is from my test page at:
    http://www.mgdsventures.com/test-pop.html

    When someone clicks the "Categories" the list of categories is displayed (working!). However the list is meant to hide when the mouse is moved off the DIV. The list vanish with any mouse movement - this isn't working. (tested in FF3)

    Would love to know why.
    Correct functionality:
    Click: expand div to show category list. (working)
    Mouse OFF div: reduce size of div to hide category list (not working)


    Code HTML4Strict:
     
    <!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">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Untitled Document</title>
     
    <script type="text/javascript">
     
    function categories(mode) {
    	if (mode == 1) {		
    		for (var i = 20;i<120;i++) {
    			document.getElementById('cat_list').style.height = i + 'px';
    		}
    	}
    	if (mode == 0) {		
    		for (var i = 120;i>20;i--) {
    			document.getElementById('cat_list').style.height = i + 'px';
    		}
    	}
     
    	return false;
    }
     
    </script>
     
    </head>
     
    <body>
     
     
    yada yada yada
    <div style="height:20px;"> 
    <div id="cat_list" style="height:20px;width:200px;border:1px solid #000000;overflow:hidden;position:absolute;;z-index:90;background-color:red" onmouseout="return categories(0);">
    <a href="#" onclick="return categories(1);">Categories</a><br>
    1<br>
    2<br>
    3<br>
    </div>
    </div>
    yada yada yada
     
    </body>
    </html>

    Thanks!

  2. #2
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Because your link is inside the div, when it fires a mouseout event, that event bubbles up to the div's mouseout handler. To deal with that you can either stop the event bubbling from the link or determine which element is the source of the event when the div's handler fires.

    Here's the first version:
    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">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Untitled Document</title>
     
    <script type="text/javascript">
     
    function categories(mode) {
        if (mode == 1) {        
            for (var i = 20;i<120;i++) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
        if (mode == 0) {        
            for (var i = 120;i>20;i--) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
        
        return false;
    }
     
    </script>
     
    </head>
     
    <body>
     
     
    yada yada yada
    <div style="height:20px;"> 
    <div id="cat_list" style="height:20px;width:200px;border:1px solid #000000;overflow:hidden;position:absolute;;z-index:90;background-color:red">
    <a href="#" id="link">Categories</a><br>
    1<br>
    2<br>
    3<br>
    </div>
    </div>
    yada yada yada
    
    <script type="text/javascript">
    var link = document.getElementById("link");
    link.onclick = function() {
      categories(1);
      return false;
    }
    link.onmouseout = function(e) {
      e = e || window.event;
      if (typeof e.stopPropagation != 'undefined') e.stopPropagation();
      else e.cancelBubble = true;
    }
    document.getElementById("cat_list").onmouseout = function(){categories(0);};
    </script>
    </body>
    </html>
    Be careful though, if there is no space between the link and the edge of the div then moving the mouse straight out of the div from the link may not fire the div's onmouseout handler.

  3. #3
    SitePoint Evangelist
    Join Date
    Jan 2005
    Posts
    425
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, though you lost me about the bubble and stopPropagation part. But it works, and yes problems arise if no space between link and end of div. But lucky I have padding.

    Anyway of making it increment the height (like currently doing) but stopping once all the divs content has been revealed - rather than passing in a variable to increase height of div by (this won't work if the content of the div is of varying size).

    Hope that makes sense.

  4. #4
    SitePoint Evangelist
    Join Date
    Jan 2005
    Posts
    425
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have attempted it, and it seems to work ok in FF3, IE, Opera - but NOT Safari (for Win):
    http://www.mgdsventures.com/test-pop.html

    The code is:
    Code HTML4Strict:
    <!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">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Untitled Document</title>
     
    <script type="text/javascript">
     
     
    function categories(mode) {	
    	min_height = document.getElementById('container').style.height;
    	min_height = min_height.split('p');
    	min_height = parseInt(min_height[0]);
     
    	max_height = document.getElementById('categories').style.height;
    	max_height = max_height.split('p');
    	max_height = parseInt(max_height[0]) + min_height;
     
        if (mode == 1) {        
            for (var i = min_height;i <= max_height; i++) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
        if (mode == 0) {        
            for (var i = max_height;i >= min_height;i--) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
     
        return false;
    }
     
    </script>
     
    </head>
     
    <body>
     
     
    yada yada yada
    <div id="container" style="height:20px;padding:10px 0 10px 0"> 
    <div id="cat_list" style="height:20px;width:200px;border:1px solid #000000;overflow:hidden;position:absolute;z-index:90;background-color:red;padding:5px 0 0 5px">
    <a href="#" id="link">Categories</a><br>
    <div id = "categories" style="height:500px;">
    1<br>
    2<br>
    3<br>
    </div>
    </div>
    </div>
    yada yada yada
     
    <script type="text/javascript">
    var link = document.getElementById("link");
    link.onclick = function() {
      categories(1);
      return false;
    }
    link.onmouseout = function(e) {
      e = e || window.event;
      if (typeof e.stopPropagation != 'undefined') e.stopPropagation();
      else e.cancelBubble = true;
    }
    document.getElementById("cat_list").onmouseout = function(){categories(0);};
    </script>
    </body>
    </html>

    Any idea what is wrong with it? How to improve it?

    In Safari the DIV reduces size as soon as you move the mouse off the link. This "error" doesn't happen in the other browsers I tested.

    Also, it is a bit jumpy/non-smooth scroll the longer the div gets.

  5. #5
    SitePoint Evangelist
    Join Date
    Jan 2005
    Posts
    425
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually as soon as you add links in the drop down div it breaks in all broswers

    Code HTML4Strict:
    <!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">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Untitled Document</title>
     
    <script type="text/javascript">
     
     
    function categories(mode) {	
    	min_height = document.getElementById('container').style.height;
    	min_height = min_height.split('p');
    	min_height = parseInt(min_height[0]);
     
    	max_height = document.getElementById('categories').style.height;
    	max_height = max_height.split('p');
    	max_height = parseInt(max_height[0]) + min_height;
     
        if (mode == 1) {        
            for (var i = min_height;i <= max_height; i++) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
        if (mode == 0) {        
            for (var i = max_height;i >= min_height;i--) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
     
        return false;
    }
     
    </script>
     
    </head>
     
    <body>
     
     
    yada yada yada
    <div id="container" style="height:20px;padding:10px 0 10px 0"> 
    <div id="cat_list" style="height:20px;width:200px;border:1px solid #000000;overflow:hidden;position:absolute;z-index:90;background-color:red;padding:5px 0 0 5px">
    <a href="#" id="link">Categories</a><br>
    <div id = "categories" style="height:500px;">
    <a href="http://www.yada.com">yada yada</a><br>
    <a href="http://www.yada.com">yada yada yada</a><br>
    <a href="http://www.yada.com">yada yada yada yada</a><br>
    </div>
    </div>
    </div>
    yada yada yada
     
    <script type="text/javascript">
    var link = document.getElementById("link");
    link.onclick = function() {
      categories(1);
      return false;
    }
    link.onmouseout = function(e) {
      e = e || window.event;
      if (typeof e.stopPropagation != 'undefined') e.stopPropagation();
      else e.cancelBubble = true;
    }
    document.getElementById("cat_list").onmouseout = function(){categories(0);};
    </script>
    </body>
    </html>

  6. #6
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You've introduced a new div inside the menu!

    The new div will fire a mouseout event whenever the mouse leaves it. Because the new div is nested inside other elements it will pass that event on to those elements it is within to see if they want to handle it in any way. This process is called event bubbling or event propagation. To stop it happening you would have to set an onmouseout handler on the new div as well to stop it triggering the menu collapse.

    So, that shows us the other setup is better as it copes with changes to nested elements. We set a mouseout handler on the main menu div but check that it was actually the div that set off the event, not a child element.

    Code:
    <script type="text/javascript">
    var link = document.getElementById("link");
    link.onclick = function() {
      categories(1);
      return false;
    }
    
    document.getElementById("cat_list").onmouseout = function(e){
      e = e || window.event;
      var target = e.target || e.srcElement;
      if (target === this) {
        categories(0);
      }
    };
    </script>
    </body>
    This should sort out the links problem as well.

  7. #7
    SitePoint Evangelist
    Join Date
    Jan 2005
    Posts
    425
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    See: http://www.mgdsventures.com/test-pop.html

    Replace the lower <script> with the <script> you provide, doesn't seem to work for me well (in FF).
    When you leave the DIV it either doesn't close, or is very slow to close.

    Am I missing anything else?
    Code HTML4Strict:
    <!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">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Untitled Document</title>
     
    <script type="text/javascript">
     
     
    function categories(mode) {	
    	min_height = document.getElementById('container').style.height;
    	min_height = min_height.split('p');
    	min_height = parseInt(min_height[0]);
     
    	max_height = document.getElementById('categories').style.height;
    	max_height = max_height.split('p');
    	max_height = parseInt(max_height[0]) + min_height;
     
        if (mode == 1) {        
            for (var i = min_height;i <= max_height; i++) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
        if (mode == 0) {        
            for (var i = max_height;i >= min_height;i--) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
     
        return false;
    }
     
    </script>
     
    </head>
     
    <body>
     
     
    yada yada yada
    <div id="container" style="height:20px;padding:10px 0 10px 0"> 
    <div id="cat_list" style="height:20px;width:200px;border:1px solid #000000;overflow:hidden;position:absolute;z-index:90;background-color:red;padding:5px 0 0 5px">
    <a href="#" id="link">Categories</a><br>
    <div id = "categories" style="height:500px;">
    <a href="http://www.yada.com">yada yada</a><br>
    <a href="http://www.yada.com">yada yada yada</a><br>
    <a href="http://www.yada.com">yada yada yada yada</a><br>
    </div>
    </div>
    </div>
    yada yada yada
     
    <script type="text/javascript">
    var link = document.getElementById("link");
    link.onclick = function() {
      categories(1);
      return false;
    }
     
    document.getElementById("cat_list").onmouseout = function(e){
      e = e || window.event;
      var target = e.target || e.srcElement;
      if (target === this) {
        categories(0);
      }
    };
    </script>
     
     
    </body>
    </html>

    I added the new div to assist with the resize of the outer div. As it uses the new div height to add to the outer div. I'm happy to do away with the new div, if there is another way of doing it. Span?

  8. #8
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's a simpler way.

    Add this style to the head section
    Code:
    <style type="text/css">
    div#cat_list a {
      display:block;
      width:100&#37;;
    }
    </style>
    delete the br tags after the links, and change the script at the bottom:
    Code:
    <style type="text/css">
    div#cat_list a {
      display:block;
      width:100%;
    }
    </style>
    <script type="text/javascript">
    
    
    document.getElementById("cat_list").onmouseout = function(e){
        categories(0);
    };
     
    document.getElementById("cat_list").onmouseover = function(e){
      categories(1);
    };
    </script>

  9. #9
    SitePoint Evangelist
    Join Date
    Jan 2005
    Posts
    425
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks but that doesn't seem to work for me.

    It is meant to be onclick (not onmouseover) that the drop down is displayed, and onmouseout that it is hidden.

    I tried replacing onmouseover with onclick, but that failed.
    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">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Untitled Document</title>
    <style type="text/css">
    div#cat_list a {
      display:block;
      width:100%;
    }
    </style>
    <script type="text/javascript">
    
     
    function categories(mode) {	
    	min_height = document.getElementById('container').style.height;
    	min_height = min_height.split('p');
    	min_height = parseInt(min_height[0]);
    	
    	max_height = document.getElementById('categories').style.height;
    	max_height = max_height.split('p');
    	max_height = parseInt(max_height[0]) + min_height;
    	
        if (mode == 1) {        
            for (var i = min_height;i <= max_height; i++) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
        if (mode == 0) {        
            for (var i = max_height;i >= min_height;i--) {
                document.getElementById('cat_list').style.height = i + 'px';
            }
        }
        
        return false;
    }
     
    </script>
     
    </head>
     
    <body>
     
     
    yada yada yada
    <div id="container" style="height:20px;padding:10px 0 10px 0"> 
    <div id="cat_list" style="height:20px;width:200px;border:1px solid #000000;overflow:hidden;position:absolute;z-index:90;background-color:red;padding:5px 0 0 5px">
    <a href="#" id="link">Categories</a><br>
    <div id = "categories" style="height:500px;">
    <a href="http://www.yada.com">yada yada</a><br>
    <a href="http://www.yada.com">yada yada yada</a><br>
    <a href="http://www.yada.com">yada yada yada yada</a><br>
    </div>
    </div>
    </div>
    yada yada yada
    
    <script type="text/javascript">
    document.getElementById("cat_list").onmouseout = function(e){
        categories(0);
    };
     
    document.getElementById("cat_list").onclick = function(e){
      categories(1);
    };
    </script>
    
    </body>
    </html>

  10. #10
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay, here's a way that counts mouseovers and mouseouts, starting with a click. If the mouse has left the building the count will drop to zero and we can collapse the menu.
    Code:
    <script type="text/javascript">
    var catList = document.getElementById("cat_list");
    var catLink = document.getElementById("link");
    
    var inCount = 0;
    
    catLink.onclick = function(){
      inCount = 1;
      setMenu();
      catList.onmouseover = function() {
        inCount++;
        setMenu();
      }
    }
    
    catList.onmouseout = function() {
      inCount--;
      setTimeout(function(){
        setMenu();
      }, 100);
    }
    
    function setMenu(){
      if (inCount > 0) {
        categories(1);
      }
      else {
        categories(0);
        catList.onmouseover = null;
      }
    }
    
    categories(0);
    </script> 
    </body>
    Moving the mouse from one link to the next down the menu will fire a mouseout followed by a mouseover. The mouseout will take the count down to zero but the mouseover will take it back to 1. A setTimeout is used to give the mouseover a chance to fire before the menu collapses.

  11. #11
    SitePoint Evangelist
    Join Date
    Jan 2005
    Posts
    425
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks mate, that works well.


Bookmarks

Posting Permissions

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