...

DOM drop downs

sidvorak
03-30-2004, 05:57 PM
Ok, I just tried to make this post and got logged out when I hit preview, so this time around it's gonna be much shorter as my patience has run out.

...Over at gazingus.org (http://gazingus.org/html/Using_Lists_for_DHTML_Menus.html) there is a sweet little bit of code that uses the DOM to make dropdown menus.

I have altered the code (see below) to make the menus appear on the first mousover instead of the onClick event.

However, they never go away. I'm trying to figure out how make the last menu open disappear after a short delay. I've already tried this

actuator.onmouseout=function(){

if(currentMenu){
setTimeout('currentMenu.style.visibility = "hidden";',2000);
}
}
However, it doesn't work. The delayed code events pile up on each other if menus are continually moused over and out. (Say the user can't decide what menu they're looking for and runs the mouse left...then right...then left...)

The result is that after the 2000ms the menus close instantly....

any ideas?
Cheers,
Simon Dvorak (http://www.simondvorak.com)


/*
* menuDropdown.js - implements an dropdown menu based on a HTML list
* Author: Dave Lindquist (http://www.gazingus.org)
*/

var currentMenu = null;

if (!document.getElementById)
document.getElementById = function() { return null; }

function initializeMenu(menuId, actuatorId,position) {
var menu = document.getElementById(menuId);
var actuator = document.getElementById(actuatorId);

if (menu == null || actuator == null) return;

if (window.opera) return; // I'm too tired

actuator.onmouseover = function() {
if (currentMenu == null) {
this.showMenu(position);
}
else if(currentMenu) {
currentMenu.style.visibility = "hidden";
this.showMenu(position);
}
return false;
}

actuator.onmouseout = function() {
if(currentMenu){
setTimeout('currentMenu.style.visibility = "hidden";',2000);
return false;}}


actuator.showMenu = function(position) {
if (document.all){
menu.style.left = this.offsetLeft + 80 - position + "px";
}
else {
menu.style.left = this.offsetLeft - position + "px";
}
menu.style.top = this.offsetTop + this.offsetHeight + 2 + "px";
menu.style.visibility = "visible";
currentMenu = menu;
}
}

sad69
03-30-2004, 07:50 PM
Well I didn't really look at your code, I just downloaded it myself and altered it the way I thought it should be.

It seems to work. I've attached the menuDropdown.js

Hope that helps,
Sadiq.

sidvorak
03-30-2004, 08:06 PM
Thanks for the effort. However, having the onmouseout function like that doesn't let you choose anything from the menus as they disappear as soon as the mouse leaves the activating button.

That is one reason for needing a delay. I guess it should probably be a mouseout event on the menu instead of the button...

Still stuck,
Simon

sad69
03-30-2004, 08:22 PM
Hehe, oops...

Ok I'll work on it..

Sadiq.

sad69
03-30-2004, 09:09 PM
Wowzas! I think I've finally got it down.

I think I ran into a similar situation as you (the actuator wasn't disappearing).

My solution was to add another actuator after that one, and just keep it empty. I've attached the whole thing for you. Let me know how it works out for you and if you have any troubles.

Sadiq.

sidvorak
03-31-2004, 01:48 AM
Thanks sad69. Unfortunately, the menus still don't disappear if a user mouses out on a menu.

I was able to get it to work by adding mouseover and mouseout events to the menus as well and tracking whether or not another mouseover event has happened. here is the code.

Thanks again!
Simon (http://www.simondvorak.com)


var currentMenu = null;
if (!document.getElementById)
document.getElementById = function() { return null; }

function initializeMenu(menuId, actuatorId,position) {
var menu = document.getElementById(menuId);
var actuator = document.getElementById(actuatorId);
if (menu == null || actuator == null) return;
if (window.opera) return; // I'm too tired

actuator.onmouseover = function() {
if (currentMenu == null) {
this.showMenu(position);
}
else if(currentMenu) {
currentMenu.style.visibility = "hidden";
this.showMenu(position);
}
a=0;
return false;
}
actuator.onmouseout = function() {
a=1;
setTimeout('if(a==1){currentMenu.style.visibility = "hidden"};',10000);
}
menu.onmouseover = function(){
a=0;
}
menu.onmouseout = function() {
a=1;
setTimeout('if(a==1){currentMenu.style.visibility = "hidden"};',10000);
}
actuator.showMenu = function(position) {
if (document.all){
menu.style.left = this.offsetLeft + 80 - position + "px";
}
else {
menu.style.left = this.offsetLeft - position + "px";
}
menu.style.top = this.offsetTop + this.offsetHeight + 2 + "px";
menu.style.visibility = "visible";
currentMenu = menu;
}
}

sad69
03-31-2004, 02:26 AM
Well as long as you got it working!

That's odd that my code doesn't work for you, since it works for me. What browser are you using? I could only test mine on IE...

Sadiq.

sidvorak
03-31-2004, 05:50 AM
I'm using IE6 and Firefox .08...

The code you sent worked when I moused out over the activator but not when I ended by mousing out over one of the menu dropdowns...

Cheers,
Simon

sad69
03-31-2004, 07:02 AM
So when you mouse out of a drop down menu you want that drop down menu to disappear? I didn't know that.. but whatever, if you've got it working then bravo!

Cheers,
Sadiq.

DHTML Kitchen
04-11-2004, 11:37 PM
However, it doesn't work.
...
The result is that after the 2000ms the menus close instantly...

The menu should not be hidden in 2000ms if the user has activated the menu.

Clear the timer.

First you need a timer id.

actuator.timer = setTimeout("hideMenu("'+actuator.id + "')", 500);


Then in your mouseover functions (one for menu and one for actuator), clear the timer:
clearTimeout(actuator.timer);

iatek
10-03-2004, 07:58 PM
I think the timer is only a Window object...

var currentMenu = null;

if (!document.getElementById)
document.getElementById = function() { return null; }

function initializeMenu(menuId, actuatorId) {
var menu = document.getElementById(menuId);
var actuator = document.getElementById(actuatorId);
var timer;

if (menu == null || actuator == null) return;

actuator.onmouseover = function() {
window.clearTimeout(timer);
if (currentMenu) {
currentMenu.style.visibility = "hidden";
menu.style.left ="";
menu.style.top = "";
this.showMenu();
}
}

actuator.onmouseout = function() {
window.clearTimeout(timer);
if (currentMenu != menu) {
menu.style.left ="";
menu.style.top = "";
this.showMenu();
}
}

menu.onmouseout = function() {
if (currentMenu != null) {
timer = window.setTimeout('currentMenu.style.visibility = "hidden"',2000)
}
else {
window.clearTimeout(timer);
}
}

menu.onmouseover = function() {
window.clearTimeout(timer);
}

actuator.showMenu = function() {
tmph = menu.offsetTop;
menu.style.left = this.offsetLeft + "px";
menu.style.top = tmph + (this.offsetTop + this.offsetHeight) + "px";
menu.style.visibility = "visible";
currentMenu = menu
}
}

brothercake
10-04-2004, 09:14 PM
You don't need a delay to acheive this...

There's a method in IE (bear with me) called contains() which can be used to evaluate the relationship between two objects - it returns whether one contains the other. That's exactly what you need - examine the mouseout event to determine whether the menu tree contains it - if it does then do nothing, if it doesn't then send hide the menu.

Okay that's IE only, but it's simple to prototype using this nifty code courtesy of jkd:

HTMLElement.prototype.contains = function(node) {
if (node == null)
return false;
if (node == this)
return true;
else
return this.contains(node.parentNode);
}

Now only mozilla supports HTMLElement prototyping, but since the script is object oriented that doesn't matter - you can prototype contains() as a method of the menu actuator itself:

actuator.contains = function(node)
{
if (node == null) { return false; }
if (node == this) { return true; }
else { return this.contains(node.parentNode); }
}

Check this out to see it in action: http://www.brothercake.com/scripts/listmenu/



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum