I've written a javascript drop down navigation menu where the drop down layers slide down (using CSS clipping). The problem I've noticed is the drop downs seem to slide up and down at different speeds depending on how I move the mouse around, and sometimes get stuck although I can't pinpoint what the exact conditions are when they get stuck. I have a test sample of the page online. If anyone could tell me if there's any mistakes I'm making in my code, that'd be great (I'm still pretty new to Javascript). Here's the code (hope it's not too much - I'll edit it down if so):
Code:
<html>
<head>
<title>DropDown Menu using Javascript Objects</title>
<script language="Javascript">
<!--
function init()
	{
	ns4 = (document.layers)? true:false;
	ie4 = (document.all)? true:false;
	compliant = (!document.all && document.getElementById)? true:false;
	isOverMenu = false;
	wipeSpeed = 5;
	menu1 = new layerObject("menu1Div");
	menu1.name = "menu1";
	menu2 = new layerObject("menu2Div");
	menu2.name = "menu2";
	}

function layerObject(id)
	{
	if (ns4) this.css = document.layers[id];
	if (ie4) this.css = document.all[id].style;
	if (compliant) this.css = document.getElementById(id).style;
	this.hideMenu = hideMenu;
	this.showMenu = showMenu;
	this.clipValues = clipValues;
	this.clipTo = clipTo;
	this.clipBy = clipBy;
	this.startWipeOff = startWipeOff;
	this.wipeOff = wipeOff;
	this.startWipeOn = startWipeOn;
	this.wipeOn = wipeOn;
	this.height = parseInt(this.css.height);
	this.width = parseInt(this.css.width);
	}

function showMenu()
	{
	if (ns4)			// For Netscape browsers
		this.css.visibility="show";
	else if (ie4)	// For IE browsers
		this.css.visibility="visible";
	else if (compliant)
		this.css.visibility="visible";
	}

function hideMenu()
	{
	if (ns4)			// For Netscape browsers
		this.css.visibility="hide";
	else if (ie4)	// For IE browsers
		this.css.visibility="hidden";
	else if (compliant)
		this.css.visibility="hidden";
	}

function clipValues(which)
	{
	if (ns4)
		{
		if (which=="t") return this.css.clip.top
		if (which=="r") return this.css.clip.right
		if (which=="b") return this.css.clip.bottom
		if (which=="l") return this.css.clip.left
		}
	else if (ie4)
		{
		var clipv = this.css.clip.split("rect(")[1].split(")")[0].split("px")
		if (which=="t") return Number(clipv[0])
		if (which=="r") return Number(clipv[1])
		if (which=="b") return Number(clipv[2])
		if (which=="l") return Number(clipv[3])
		}
	}

function clipTo(t,r,b,l)
	{
	if (ns4)
		{
		this.css.clip.top = t
		this.css.clip.right = r
		this.css.clip.bottom = b
		this.css.clip.left = l
		}
	else if (ie4)
		this.css.clip = "rect("+t+"px "+r+"px "+b+"px "+l+"px)"
	}

function clipBy(t,r,b,l)
	{
	if (ns4)
		{
		this.css.clip.top = this.clipValues('t') + t
		this.css.clip.right = this.clipValues('r') + r
		this.css.clip.bottom = this.clipValues('b') + b
		this.css.clip.left = this.clipValues('l') + l
		}
	else if (ie4)
		this.css.clip = "rect("+(this.clipValues('t')+t)+"px "+(this.clipValues('r')+r)+"px "+
		Number(this.clipValues('b')+b)+"px "+Number(this.clipValues('l')+l)+"px)"
	}

function startWipeOn()
	{
	this.isOpen = true;					// indicate this current menu is open
	if (this.hideTimer)
		clearTimeout(this.hideTimer);	// if there was a timer set to hide a menu, stop it
	if (this.WipingOnActive) return; // if wipe on is already in progress, don't start new wipe
	this.WipingOnActive = true;			// indicate a new wipe on is now in progress
	//this.clipTo(0,this.width,0,0);	// set clipping to 0 height
	this.showMenu();					// make layer visible
	this.wipeOn();						// gentlemen, start your wiping!
	}

function wipeOn()
	{
	if (this.clipValues('b') < 100)
		{
		this.clipBy(0,0,wipeSpeed,0);
		setTimeout(this.name+".wipeOn()",1);
		}
	else
		{
		this.WipingOnActive = false;
		if (!this.isOpen)
			this.startWipeOff();
		}
	}

function startWipeOff()
	{
	this.isOpen = false;					// indicate current menu is off
	if (this.WipingOnActive || this.WipingOffActive) return; // if wipe in progress, don't start new wipe
	this.WipingOffActive = true;			// indicate a new wipe off is now in progress
	//this.clipTo(0,this.width,this.height,0);	 // set clipping to full height of layer
	this.showMenu();						// make layer visible
	this.hideTimer = setTimeout(this.name+".wipeOff()",20);  // wait 20 milliseconds then start wiping
	}

function wipeOff()
	{
	if (!this.isOpen)		// only start wiping off if the menu is still off
		{		// in case user moves mouse back over menu after mousing out
		if (this.clipValues('b') > 0)
			{
			this.clipBy(0,0,-wipeSpeed,0);
			setTimeout(this.name+".wipeOff()",1);
			}
		else
			this.WipingOffActive = false;
		}
	}
//-->
</script>
</head>
<body bgcolor="#FFFFFF" text="#000000" onLoad="init()">
<table align=center>
  <tr>
    <td width=90>
	  <a href="#" onmouseover="menu1.startWipeOn()" onmouseout="menu1.startWipeOff()">menu1</a><br>
	  <div id="menu1Div" onmouseover="menu1.startWipeOn()" onmouseout="menu1.startWipeOff()" 
	  style="background: #dddddd; position:absolute; visibility:hidden; width:90; height:100; 
          clip:rect(0,90,0,0)">menu 1 contents</div>
    </td>
	<td width=90>
	  <a href="#" onmouseover="menu2.startWipeOn()" onmouseout="menu2.startWipeOff()">menu2</a><br>
	  <div id="menu2Div" onmouseover="menu2.startWipeOn()" onmouseout="menu2.startWipeOff()" 
	  style="background: #dddddd; position:absolute; visibility:hidden; width:90; height:100; 
          clip:rect(0,90,0,0)">menu 2 contents</div>
	</td>
  </tr>
</table>
</body>
</html>