Popup menu problems

A

Aaron

I'm having problems getting my popup menu to work correctly, and was
hoping someone here could point me in the right direction. I have the
following script:

<script>
var activeMenu="";

function getObject(id) {
var object=eval("document.getElementById('"+id+"')");
return object;
}

function PopMenu(M) {
clearTimeout();
HideActive();
getObject(M).style.visibility="visible";
activeMenu=M;
}

function HideActive() {
if (activeMenu !="") {
getObject(activeMenu).style.visibility="hidden";
activeMenu="";
}
}

function menuTimeout() {
setTimeout("HideActive()", 2000);
}
</script>

which goes with the following html:

<div id="menuhead" onMouseOver="PopMenu('menu')">
<img src="menuhead.gif" />
</div>
<div id="menu" onMouseOut="menuTimeout()">
<a href="test1.htm">Test 1</a>
<a href="test2.htm">Test 2</a>
<a href="test3.htm">Test 3</a>
</div>


The menu opens perfectly, but it closes 2 sec after I mouseOut() of
'menuhead' instead of the actual 'menu'. Also, if I repeatly
mouseOver() the 'menuhead', the timing gets thrown off, as if
clearTimeout() is being called irregularly. Could someone with more
experience give me a hand?

Thanks,
Aaron
 
J

Janwillem Borleffs

Aaron said:
I'm having problems getting my popup menu to work correctly, and was
hoping someone here could point me in the right direction. I have the
following script:

Here's an alternative approach:

<style type="text/css">
#menu {
position: absolute;
clip: rect(auto auto 15px auto)
}
</style>
....
<div id="menu"
onmouseout="style.clip='rect(auto auto 15px auto)'"
onmouseover="style.clip='rect(auto auto auto auto)'">
Show menu<br />
<a href="test1.htm">Test 1</a>
<a href="test2.htm">Test 2</a>
<a href="test3.htm">Test 3</a>
</div>


JW
 
A

Aaron

Here's an alternative approach:
<style type="text/css">
#menu {
position: absolute;
clip: rect(auto auto 15px auto)
}
</style>
...
<div id="menu"
onmouseout="style.clip='rect(auto auto 15px auto)'"
onmouseover="style.clip='rect(auto auto auto auto)'">
Show menu<br />
<a href="test1.htm">Test 1</a>
<a href="test2.htm">Test 2</a>
<a href="test3.htm">Test 3</a>
</div>

This works great...thanks so much, JW. Now, to get the setTimeout(),
I've changed it to the following:

<style type="text/css">
#menu {position: absolute;
clip: rect(auto auto 15px auto);
}
</style>


<script type="text/javascript">
function getObject(id) {
var object=eval("document.getElementById('"+id+"')");
return object;
}
function openMenu(id) {
var name=getObject(id);
name.style.clip='rect(auto auto auto auto)';
}
function closeMenu(id) {
var name=getObject(id);
name.style.clip='rect(auto auto 15px auto)';
}
function menuTimeout(id) {
setTimeout("closeMenu(id)", 2000);
}
</script>


<div id="menu" onmouseout="menuTimeout('menu')"
onmouseover="openMenu('menu')">
<p>Show menu</p>
<ul>
<li><a href="test1.htm">Test 1</a></li>
<li><a href="test2.htm">Test 2</a></li>
<li><a href="test3.htm">Test 3</a></li>
</ul>
</div>



Passing the id name to the menuTimeout() function doesn't seem to work
at all. What am I doing wrong here?

Thanks,
Aaron
 
L

Lasse Reichstein Nielsen

Aaron said:
I'm having problems getting my popup menu to work correctly, and was
hoping someone here could point me in the right direction. I have the
following script:

I'll try to give some suggestions that you can try.

The "type" attribute is required in HTML.
var activeMenu="";

function getObject(id) {
var object=eval("document.getElementById('"+id+"')");

You *never* need to use eval for accessing elements by name. You
probably never need to use eval at all, and shouldn't, since there are
more efficient and less error prone alternatives. This function can
just be written:

return document.getElementById(id);
return object;
}

function PopMenu(M) {
clearTimeout();

The function "clearTimeout" takes an argument: the value returned by
the call to setTimeout that you want to cancel.
<URL:http://www.mozilla.org/docs/dom/domref/dom_window_ref8.html#1016919>
<URL:http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/cleartimeout.asp>

Make a global variable outside the function,
var timeout_id;
and call
clearTimeout(timeout_id);
timeout_id = null;
and set it again when you call setTimeout.
HideActive();
getObject(M).style.visibility="visible";
activeMenu=M;
}

function HideActive() {
if (activeMenu !="") {
getObject(activeMenu).style.visibility="hidden";
activeMenu="";
}
}

function menuTimeout() {
setTimeout("HideActive()", 2000);

first clear the existing timeout, if any:
if (timeout_id != null) { clearTimeout(timeout_id); }
This avoids having two timeouts running at the same time,
when you can only cancel one.

and then start a new countdown:
timeout_id = setTimeout("HideActive()",2000):
(or even
timeout_id = setTimeout(HideActive, 2000);
in modern browsers)
}
</script>

which goes with the following html:

<div id="menuhead" onMouseOver="PopMenu('menu')">
<img src="menuhead.gif" />

You should not write "/>" in HTML. It is only for XHTML, which you
don't seem to use (attribute names are all lower case in XHTML).
The menu opens perfectly, but it closes 2 sec after I mouseOut() of
'menuhead' instead of the actual 'menu'.

Not for me. When I try your code in IE 6 (without the image :),
the submenu starts visible. When I put the mouse over it and leaves
again, the submenu disappears after two seconds (even if I am, at that
point, over the menuhead ... most likely because clearTimeout fails to
do anything).
Also, if I repeatly
mouseOver() the 'menuhead', the timing gets thrown off, as if
clearTimeout() is being called irregularly.

clearTimeout, as you call it, does nothing, so every mouseout will
schedule a hide, with the only limit to how many you can have pending
being how fast you can twiddle your moust.

Good luck.
/L
 
L

Lasse Reichstein Nielsen

Aaron said:
<style type="text/css">
#menu {position: absolute;
clip: rect(auto auto 15px auto);

I would recommend changing "15px" to "1.2em" (or whatever the line
height is). To see why, try adding:
font-size: large;
That can happen to people with different default font settings too.
function menuTimeout(id) {
setTimeout("closeMenu(id)", 2000);

This won't work. The code
closeMenu(id)
will be executed in the global context, and will not have access
to the local variables of the menuTimeout function, including "id".

You can either use:
setTimeout("closeMenu('"+id+"');", 2000);
(i.e., build the id into the expression as a string literal) or
setTimeout(function(){closeMenu(id);}, 2000);
(use a closure to capture the value of "id").

See my other reply for other suggestions.
/L
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,002
Messages
2,570,261
Members
46,858
Latest member
FlorrieTuf

Latest Threads

Top