Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Rollover Menu Not Quite Right 1

Status
Not open for further replies.

Glowball

Programmer
Oct 6, 2001
373
US
Hi all, I'm having issues with a menu. What I've posted here is a simple example. Basically, there is an active menu item (the page you're on) and the content shown in a block below it corresponds to that item ("Item 1" in my example). If you roll over Item 2 or Item 3, the text associated with those two items is shown in the block below them, instead. That works fine.

The part that I can't get figured out is how to make it so the block stays visible when your mouse is anywhere in the block. In other words, if I roll over Item 2, the block below it should change (as it does), and then if I move my mouse down into the block that block should stay visible as long as I'm in the block.

I can't get the timing right. Help? Is there a better way to do this? Thanks!

Code:
<html>
<head>
	<script language="JavaScript" type="text/javascript">
	function show(shown, active) {
		setTimeout("showIt('" + shown + "', '" + active + "')", 100);
		}
		
	function hide(hidden, active) {
		setTimeout("hideIt('" + hidden + "', '" + active + "')", 100);
		}
	
	function showIt(shown, active) {
		if (document.getElementById) {
			var targetElement = document.getElementById(shown);
			var activeElement = document.getElementById(active);	
			targetElement.style.display = 'block';	
			activeElement.style.display = 'none';
			}
		}
			
	function hideIt(hidden, active) {
		if (document.getElementById) {
			var targetElement = document.getElementById(hidden);
			var activeElement = document.getElementById(active);
			targetElement.style.display = 'none';
			activeElement.style.display = 'block';
			}
		}
	</script>
</head>
<body>

<table width="60%" align="center" style="background-color:pink;margin-top:50px;">
<tr>
	<td><div id="outside" style="width:60%;padding:10px;">
	<table width="100%" cellpadding="0" cellspacing="0">
	<tr>
		<td>Item 1 (Active)</td>
		<td><a href="" onMouseOver="show('bottom_2', 'bottom_1')" onMouseOut="hide('bottom_2', 'bottom_1')">Item 2</a></td>
		<td><a href="" onMouseOver="show('bottom_3', 'bottom_1')" onMouseOut="hide('bottom_3', 'bottom_1')">Item 3</a></td>
	</tr>
	</table>
	<div id="bottom" style="margin-top:0;padding:10px;border:1px solid red;">
		<div id="bottom_1">Item 1 stuff</div>
		<div id="bottom_2" style="display:none" onMouseOver="show('bottom_2', 'bottom_1')" onMouseOut="hide('bottom_2', 'bottom_1')">Item 2 stuff with more stuff</div>
		<div id="bottom_3" style="display:none" onMouseOver="show('bottom_3', 'bottom_1')" onMouseOut="hide('bottom_3', 'bottom_1')">Item 3 items</div>
	</div>
	</div></td>
</tr>
</table>

</body>
</html>
 
there are 2 main reasons most menu systems work seamlessly without the jitter/fight to maintain like you're having..

1) container
2) overlap

container is a div/table whatever everything is in and on mouseout you hide the selections, and on the different menuitems you showsubmenu, hide other menus, almost as you are but hide all but prevalent one in your case.

overlap utilizes the same basic theory, to not break a "hover", you move directly from from one element rightover to a nother because they're overlapped, even 1px will cause a goof, most times this ovrelap is invisible because of padding/margins

that redbox you're using would work nicely for the container, or the whole pink area since it's RIGHT under the links or completely enveloping them


[thumbsup2]DreX
aKa - Robert
if all else fails, light it on fire and do the happy dance!
" I always think outside the 'box', because I'm never in the 'loop' " - DreX 2005
 
So you're saying I need to overlap the two main areas? I'll give that a try, thanks! That makes sense.
 
I've tried overlapping them with different z-index orders but it doesn't seem to be fixing anything. Would you mind making the changes in my example code that you're thinking would help?
 
usually this sort of thing is done with graphics, then the overlaps aren't so visible, so here's 2 examples, the first you can see the overlap, i just placed the red border on the individual divs and changed the positioning slightly, and got rid of the container.
Code:
<html>
<head>
    <script language="JavaScript" type="text/javascript">
    function show(shown, active) {
        setTimeout("showIt('" + shown + "', '" + active + "')", 100);
        }
        
    function hide(hidden, active) {
        setTimeout("hideIt('" + hidden + "', '" + active + "')", 100);
        }
    
    function showIt(shown, active) {
        if (document.getElementById) {
            var targetElement = document.getElementById(shown);
            var activeElement = document.getElementById(active);    
            targetElement.style.display = 'block';    
            activeElement.style.display = 'none';
            }
        }
            
    function hideIt(hidden, active) {
        if (document.getElementById) {
            var targetElement = document.getElementById(hidden);
            var activeElement = document.getElementById(active);
            targetElement.style.display = 'none';
            activeElement.style.display = 'block';
            }
        }
    </script>
</head>
<body>

<table width="60%" align="center" style="background-color:pink;margin-top:50px;">
<tr>
    <td><div id="outside" style="width:60%;padding:10px; border-style:solid;border-width:1px;bord">
    <table width="100%" cellpadding="0" cellspacing="0">
    <tr>
        <td>Item 1 (Active)</td>
        <td><span style=" border-style:solid;border-width:1px;border-color:black;"onMouseOver="show('bottom_2', 'bottom_1')" onMouseOut="hide('bottom_2', 'bottom_1')"><a href="">Item 2</a></span></td>
        <td><a href="" onMouseOver="show('bottom_3', 'bottom_1')" onMouseOut="hide('bottom_3', 'bottom_1')">Item 3</a></td>
    </tr>
    </table>
        <div id="bottom_1" style="padding:10px;border:1px solid red;position:relative;top:-3px;">Item 1 stuff</div>
        <div id="bottom_2" style="display:none;padding:10px;border:1px solid red;position:relative;top:-3px;" onMouseOver="show('bottom_2', 'bottom_1')" onMouseOut="hide('bottom_2', 'bottom_1')">Item 2 stuff with more stuff</div>
        <div id="bottom_3" style="display:none;padding:10px;border:1px solid red;position:relative;top:-3px;" onMouseOver="show('bottom_3', 'bottom_1')" onMouseOut="hide('bottom_3', 'bottom_1')">Item 3 items</div>
    </div></td>
</tr>
</table>

</body>
</html>
second example i modded the code slightly for you to get you a decent start it uses basically a "last accessed" value and displays that in the output, so even if they got jiggly hands they can get the subgroup to still show.
and also to compensate for the gaps.
Code:
<html>
<head>
    <script language="JavaScript" type="text/javascript">
    var baseElem = 'bottom_1';
    var activeElem = 'bottom_1';
    function show(obj) {
        var objV = (typeof(obj)=='object') ? obj : document.getElementById(obj);
        if (objV) {
            if (objV.id != baseElem) {
              activeElem = objV.id;
              hide(baseElem);
            }
            else {
              hide(activeElem);
            }
            objV.style.display = ''; 
          }
        }
            
    function hide(obj) {
        var objV = (typeof(obj)=='object') ? obj : document.getElementById(obj);
        if (objV) {
            objV.style.display = 'none';
          }
        }
    </script>
</head>
<body>

<table width="60%" align="center" style="background-color:pink;margin-top:50px;">
<tr>
    <td><div id="outside" style="width:60%;padding:10px; border-style:solid;border-width:1px;bord">
    <table width="100%" cellpadding="0" cellspacing="0">
    <tr>
        <td>Item 1 (Active)</td>
        <td><a href="" onMouseOver="show('bottom_2')" onMouseOut="show(baseElem);">Item 2</a></td>
        <td><a href="" onMouseOver="show('bottom_3')" onMouseOut="show(baseElem);">Item 3</a></td>
    </tr>
    </table>
    <div id="bottom" style="padding:10px;border:1px solid red;" onMouseOver="show(activeElem);" onMouseOut="show(baseElem);">
        <div id="bottom_1">Item 1 stuff</div>
        <div id="bottom_2" style="display:none;">Item 2 stuff with more stuff</div>
        <div id="bottom_3" style="display:none;">Item 3 items</div>
    </div></td>
</tr>
</table>

</body>
</html>

lastly with your original method you had some setTimeouts in there for display/hide, if you always assign those to the same values you can cancel your previous call to set a timeout, and in turn override a hide. which is what i think you were goin for but will act fairly....jiggy when mousing over, which is just a barely modified version of your original

so here's example 3:
Code:
<html>
<head>
    <script language="JavaScript" type="text/javascript">
    [b][blue]var thisAction;[/blue][/b]
    function show(shown, active) {
        [b][blue]thisAction = [/blue][/b]setTimeout("showIt('" + shown + "', '" + active + "')", 200);
        }
        
    function hide(hidden, active) {
        [b][blue]thisAction = [/blue][/b]setTimeout("hideIt('" + hidden + "', '" + active + "')", 200);
        }
    
    function showIt(shown, active) {
        if (document.getElementById) {
            var targetElement = document.getElementById(shown);
            var activeElement = document.getElementById(active);    
            targetElement.style.display = 'block';    
            activeElement.style.display = 'none';
            }
        }
            
    function hideIt(hidden, active) {
        if (document.getElementById) {
            var targetElement = document.getElementById(hidden);
            var activeElement = document.getElementById(active);
            targetElement.style.display = 'none';
            activeElement.style.display = 'block';
            }
        }
    </script>
</head>
<body>

<table width="60%" align="center" style="background-color:pink;margin-top:50px;">
<tr>
    <td><div id="outside" style="width:60%;padding:10px;">
    <table width="100%" cellpadding="0" cellspacing="0">
    <tr>
        <td>Item 1 (Active)</td>
        <td><a href="" onMouseOver="show('bottom_2', 'bottom_1')" onMouseOut="hide('bottom_2', 'bottom_1')">Item 2</a></td>
        <td><a href="" onMouseOver="show('bottom_3', 'bottom_1')" onMouseOut="hide('bottom_3', 'bottom_1')">Item 3</a></td>
    </tr>
    </table>
    <div id="bottom" style="margin-top:0;padding:10px;border:1px solid red;">
        <div id="bottom_1">Item 1 stuff</div>
        <div id="bottom_2" style="display:none" onMouseOver="show('bottom_2', 'bottom_1')" onMouseOut="hide('bottom_2', 'bottom_1')">Item 2 stuff with more stuff</div>
        <div id="bottom_3" style="display:none" onMouseOver="show('bottom_3', 'bottom_1')" onMouseOut="hide('bottom_3', 'bottom_1')">Item 3 items</div>
    </div>
    </div></td>
</tr>
</table>

</body>
</html>

the slight changes in bold

[thumbsup2]DreX
aKa - Robert
if all else fails, light it on fire and do the happy dance!
" I always think outside the 'box', because I'm never in the 'loop' " - DreX 2005
 
I second the timer, as shown in these posts:

thread216-1462097 (with working code example)

thread216-1514335 (description of how to implemenet)

thread216-1096755 (possibly useful)

Dan



Coedit Limited - Delivering standards compliant, accessible web solutions

Dan's Page [blue]@[/blue] Code Couch:
Code Couch Tech Snippets & Info:
 
Your second example is perfect, thank you! It's so simple, and it does exactly what I needed. The approach is much cleaner and much more straightforward. Thank you for taking the time to put that together.
 
There is one bit of weirdness and I'm not sure how to stop it. Using the second example, roll over "Item 2" and then back out. The red-outlined box will go back to showing "Item 1 stuff", which is great. Then put your mouse pointer in the "Item 1 stuff" box and it will say the text related to Item 2 again, even though you haven't rolled over the Item 2 link.

How would I prevent that? I've been messing with it but I'm not having any luck. It seems like the bottom DIV can't have the same onMouseOut because it needs to reset everything to the way it was at the beginning. Right?
 
correct, and beacase the way that one works, it'll be goofy like that, the reason it works is it keeps track of the last one you hovered, so that when you bridge the gaps it still displays it, which still applies even after goin way outside, now the entire container everything sits in, we can put an onmouseout of resetting everything to start. but the problem is any gaps lead to a hover of the overall container and a resetting at that point, so it will revert relentlessly to item1, even if you've just hovered item2


this is the reason alot of websites use the vertical style menus, directly below or directly to the side of a hover item.

now you can get into using examples of floating divs, checking if there's an active setTimeout, cancelling it and replacing it with another, and so on, then your menus can float whereever and give you time to get the mouse to them without closing them etc.. but usually you want your hover commands on the higher level containers, not the individuals, like in your examples above the mouseover and mouseouts are on the wrappers, so they are easier to catch, but the problem with this is when you hover the container no problem , when you hover the actual div that holds the text, it counts as a mouseout of the container, so it reverts, then you move off that and back over the container, it flips back, etc, viscious cycle.

there are lots of examples of hover menu styles, scripts etc, but following the similar format you're working with is fairly limited, you need some of the extra scripting to handle alot of that.

[thumbsup2]DreX
aKa - Robert
if all else fails, light it on fire and do the happy dance!
" I always think outside the 'box', because I'm never in the 'loop' " - DreX 2005
 
The navigation sits both above and below other sections of the site, so I set up a "reset" function to put everything back to the way it was when the page was first loaded whenever the mouse moves to those sections. It's a little weird but it works. I think I'm good -- thanks for the discussion. It definitely helps!
 
this is probably the closest i've fond to the "style" of menu you're trying to make :


[thumbsup2]DreX
aKa - Robert
if all else fails, light it on fire and do the happy dance!
" I always think outside the 'box', because I'm never in the 'loop' " - DreX 2005
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top