I have a sliding navbar that works fine until the mouse is moved too quickly over the links. Each link expands onmouseover and contracts onmouseout. The problem is, the onmouseout event is missed sometimes and then the link doesn't contract. Does anyone have a way to ensure that links are always conctracted when the mouse leaves? I've been trying to fix this for hours with no luck.

navbar = {
	links: [],
	init: function() {
		var Navigation = document.getElementById('navbar');
		cleanWhitespace(Navigation);
		for(i = 0; i < Navigation.getElementsByTagName('div').length; i++) {
			this.links[i] = Navigation.getElementsByTagName('div')[i];
			this.links[i].expanding = false;
			this.links[i].onmouseover = function(){navbar.slide(this, 1);navbar.cancel(this)};
			this.links[i].onmouseout = function(){
				this.hide = setTimeout((function(link){return function() {navbar.slide(link, -1);}}(this)), 50);}
			for(c = 0; c < this.links[i].childNodes.length; c++) {
				if(this.links[i].childNodes[c].nodeType == 1) {
					this.links[i].childNodes[c].onmouseover = function() {
						navbar.cancel(this.parentNode);}}}}},
	slide: function(link, d) {
		if(link.expanding == false) {
			if(d > 0) link.expanding = true;
			link.expander = setInterval((function(link, d){
				return function() {
					if(d > 0 && link.offsetWidth <= 158 || d < 0 && link.offsetWidth >= 91 && link.expanding == false) {
						link.style.width = (link.offsetWidth + 18 * d) + "px";}
					else {
						clearInterval(link.expander);
						if(d > 0) link.expanding = false;}
					}}(link, d)), 25);}
		},

	cancel: function(link) {
		clearTimeout(link.hide);
		link.exapnding = false;;}
	}

Recommended Answers

All 4 Replies

Here is a little toy

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
  <head>
    <meta name="generator" content=
    "HTML Tidy for Windows (vers 25 March 2009), see www.w3.org">
    <title></title>
    <style type="text/css">
	div {float:left; height:100px; width:100px}
    </style>
    <script type="text/javascript">
</script>
  </head>
  <body>
    <div onmouseover="this.style.width='200px'" onmouseout="this.style.width='100px'" style="background-color:red"></div>
    <div onmouseover="this.style.width='200px'" onmouseout="this.style.width='100px'" style="background-color:green"></div>
    <div onmouseover="this.style.width='200px'" onmouseout="this.style.width='100px'" style="background-color:blue"></div>
    <div onmouseover="this.style.width='200px'" onmouseout="this.style.width='100px'" style="background-color:black"></div>
  </body>
</html>

that does what I understood you were describing.

I think you will find that the blocks change size properly no matter how fast you move the mouse.

The problem you are having is almost certainly the result of the fact that you can only do so much in an event handler without interfering with the recognition/handling of other events. Major manipulation of the DOM certainly falls into the category of 'too much'.

Although it is possible to increase the size of the event queue in at least some browsers (so events that arrive 'too quickly' are delayed and handled later instead of being skipped entirely), I doubt that you [or your users] can stand the resulting sluggishness.

I must confess that I didn't read your navbar function but there is probably a way to reduce it to text and then animate it using css changes as my toy does (eliminating all dynamic DOM changes from the event handler part of your code).

I can achieve the above (no animation) with pure css, and have a css version for those with scripting turned off. The main problem comes in when the divs have child elements, that must have their own event to cancel the onmouseout event of the parent. I guess I'm going to look into setting this up with jquery, as it will most likely provide a quicker and more reliable solution than what I have now.

problem comes in when the divs have child elements, that must have their own event to cancel the onmouseout event of the parent

Could you give an example?

Sorry, I should have been more specific:
The largest problem with sliding navbar is event bubbling. The onmouseout event fires when the mouse passes onto a child element. I tried fixing this with the e.relatedTarget and/or e.toElement, but the script seemed to bypass the conditions I set and go right on ahead with the function, no matter what the condtions were; ie. checking if the element was a child of the parent, exclusion by name and/or className. With the current script, the onmouseout event has a 50 ms timeout. The time out is canceled onmouseover by each childNode and by the div itself. The problem with the current code (see above) is that it fires too many events (slowing the script) and the tabs don't get contracted consistently.
[IMG]http://www.adambombhq.com/navbar.jpg[/IMG]
In the above image, the each tab is div, with the icons, the spans (Home, Forum, etc.), and the anchors (the dropdown links) as child nodes. The tab itself is a bg image. This is fine in pure css - the menu works wonderfully. But css doesn't do sliding and animated glow effects, thus the javascript. The css just simply sets the height to auto, the width to 176px, and switches the bg img with the :hover pseudo class.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.