Solved

Mouse-over tabs website navigation / Javascript

Posted on 2009-05-08
6
1,491 Views
Last Modified: 2013-11-19
I am using a navigation menu script on a website that enables mouse-over of tabs to display a sub-menu beneath. Currently, when removing the mouse from the tab, the sub-menu disappears again, which is correct. However, what I need is for the initial sub-menu to re-instate. It's difficult to describe, but is obvious when viewing the page:
http://www.cybersentinel.co.uk/test/

Hover over any one of the navigation tabs and you'll see the sub-menu display beneath (correctly). Remove the mouse from the tabs and the sub-nav is then blank - what needs to happen is for it to re-set to the 'homepage' sub-nav (with the 'home' tab highlighted white) as it was on the initial page load.

The JS script is here:
http://www.cybersentinel.co.uk/test/Scripts/mouseovertabs.js

The CSS is here:
http://www.cybersentinel.co.uk/test/Scripts/mouseovertabs.css

Any advice would be much appreciated.
0
Comment
Question by:beverleydunster
  • 3
  • 3
6 Comments
 
LVL 8

Expert Comment

by:Bobaran98
ID: 24342564
Take a look at the javascript below... I made some edits, and this should replace the entirety of your mouseovertabs.js file.

I'd like to think it'll work, but you'll just have to throw it out there and see-- obviously I can't really test it myself.  Regardless, I very carefully commented all of my changes (look for the text "Bobaran98", so maybe you can tweak it if you receive any error messages.  However, you're welcome to post any error messages here and we can tackle them together.  If we get it working, I don't care if you remove my comments-- it's not originally my code, after all!

Hope it works!

//Mouseover Tabs Menu: By http://www.dynamicdrive.com

//** Aug 4th, 08': Script creation date

//CHANGES: 5/9/2009 Bobaran98 - to reset tabs to original state on mouseout event
 

var uberSelected;	//added by Bobaran98 5/9/2009
 

var mouseovertabsmenu={
 

disappeardelay: 250, //set delay in miliseconds before sub menu disappears onmouseout

ajaxloadingmsg: 'Loading Sub Menu Contents...', //Message to show inside sub menu while fetching contents
 

///////No need to edit beyond here//////////////////////
 

tabsmenutree:{},
 

initializetabs:function(tabsmenuid, submenuid, tabcontentsLength, disappearBool){

	var tabmenu=document.getElementById(tabsmenuid)

	var tablinks=tabmenu.getElementsByTagName("a")

	var submenu=document.getElementById(submenuid)

	var selected=null, tablinks_count=0

	for (var i=0; i<tablinks.length; i++){

		tablinks[i]._parentid=tabsmenuid

		var relattr=tablinks[i].getAttribute("rel")

		if (/^gotsubmenu/i.test(relattr) && tablinks_count<tabcontentsLength){ //if "rel" attribute starts with="gotsubmenu" and a tab content exists for this tab based on its order

			tablinks[i]._pos=tablinks_count //remember position of this tab relative to its active peers

			if (relattr.indexOf("[selected]")!=-1){

				selected=tablinks_count

			}

			this.addEvent(tablinks[i], function(){

				var tabsmenutree=mouseovertabsmenu.tabsmenutree[this._parentid]

				mouseovertabsmenu.clearhidetimer(tabsmenutree.submenu.hidetimer)

				mouseovertabsmenu.showsubmenu(this)

			}, "mouseover")

			tablinks_count++

			this.tabsmenutree[tabsmenuid].tabs.push(tablinks[i]) //add this tab to tab collection

		}

		else{ //else for regular tab links (with no "rel" attribute)

			this.addEvent(tablinks[i], function(){

				mouseovertabsmenu.hidesubmenu(this._parentid)

			}, "mouseover")

		}

	}

	this.addEvent(submenu, function(e){

		mouseovertabsmenu.clearhidetimer(this.hidetimer)

	}, "mouseover")

	if (disappearBool==true){

		this.addEvent(submenu, function(e){ //hide submenu contents when mouse rolls out of submenu DIV

			if (!mouseovertabsmenu.isContained(this, e)){

				var cursubmenuobj=this

				// commented out by Bobaran98 5/9/2009:

				//this.hidetimer=setTimeout(function(){mouseovertabsmenu.hidesubmenu(cursubmenuobj._parentid)}, mouseovertabsmenu.disappeardelay)

				// added by Bobaran98 5/9/2009:

				this.hidetimer=setTimeout(function(){resettabs(cursubmenuobj._parentid,uberSelected)}, mouseovertabsmenu.disappeardelay)

			}

		}, "mouseout")

	}

	var urlselected=this.urlparamselect(tabsmenuid)

	//return position of selected tab (relative to its peers), or null

	return typeof urlselected=="number"? urlselected : document.getElementById(urlselected)? document.getElementById(urlselected)._pos : selected

},
 

resettabs:function(hidemenuID, showmenuID){		//function added by Bobaran98 5/9/2009

	mouseovertabsmenu.hidesubmenu(hidemenuID)

	innerdivs[showmenuID].style.display="block"

	this.css(tabsmenutree.tabs[showmenuID], "selected", "add")

	tabsmenutree.submenu._prevselected=showmenuID

},
 

ajaxload:function(tabsmenuid, submenuid, disappearBool, url){

	var page_request = false

	if (window.ActiveXObject){ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)

		try {

		page_request = new ActiveXObject("Msxml2.XMLHTTP")

		} 

		catch (e){

			try{

			page_request = new ActiveXObject("Microsoft.XMLHTTP")

			}

			catch (e){}

		}

	}

	else if (window.XMLHttpRequest) // if Mozilla, Safari etc

		page_request = new XMLHttpRequest()

	else

		return false

	var tabsmenutree=this.tabsmenutree[tabsmenuid]

	tabsmenutree.submenu.innerHTML=this.ajaxloadingmsg

	var ajaxfriendlyurl=url.replace(/^http:\/\/[^\/]+\//i, "http://"+window.location.hostname+"/") 

	page_request.onreadystatechange=function(){

		mouseovertabsmenu.ajaxpopulate(page_request, tabsmenuid, submenuid, disappearBool, ajaxfriendlyurl)

	}

	var bustcache=(ajaxfriendlyurl.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime()

	page_request.open('GET', ajaxfriendlyurl+bustcache, true)

	page_request.send(null)

},
 

ajaxpopulate:function(page_request, tabsmenuid, submenuid, disappearBool, url){

	if (page_request.readyState == 4 && (page_request.status==200 || window.location.href.indexOf("http")==-1)){

		var tabsmenutree=this.tabsmenutree[tabsmenuid]

		tabsmenutree.submenu.innerHTML=page_request.responseText

		var innerdivs=tabsmenutree.submenu.getElementsByTagName("div")

		for (var i=0; i<innerdivs.length; i++){

			if (/tabsmenucontent/i.test(innerdivs[i].className)){

				tabsmenutree.submenu_divs.push(innerdivs[i])

			}

		}

		var selected=this.initializetabs(tabsmenuid, submenuid, tabsmenutree.submenu_divs.length, disappearBool)

		if (selected!=null && selected<tabsmenutree.submenu_divs.length){

			uberSelected = selected;	//added by Bobaran98 5/9/2009

			innerdivs[selected].style.display="block"

			this.css(tabsmenutree.tabs[selected], "selected", "add")

			tabsmenutree.submenu._prevselected=selected

		}

	}

},
 

showsubmenu:function(linkobj){

	var tabsmenutree=this.tabsmenutree[linkobj._parentid]

	this.hidesubmenu(linkobj._parentid)

	var selected=parseInt(linkobj._pos)

	tabsmenutree.submenu_divs[selected].style.display="block"

	this.css(tabsmenutree.tabs[selected], "selected", "add")

	tabsmenutree.submenu._prevselected=selected

},
 

hidesubmenu:function(tabsmenuid){

	var tabsmenutree=this.tabsmenutree[tabsmenuid]

	var prevselectedindex=tabsmenutree.submenu._prevselected

	if (typeof prevselectedindex!="undefined"){

		tabsmenutree.submenu_divs[prevselectedindex].style.display="none"

		this.css(tabsmenutree.tabs[prevselectedindex], "selected", "remove")

	}

},
 

clearhidetimer:function(timerid){

	if (timerid)

		clearTimeout(timerid)

},
 

css:function(el, targetclass, action){

	var needle=new RegExp("(^|\\s+)"+targetclass+"($|\\s+)", "ig")

	if (action=="check")

		return needle.test(el.className)

	else if (action=="remove")

		el.className=el.className.replace(needle, "")

	else if (action=="add" && !needle.test(el.className))

		el.className+=" "+targetclass

},
 

isContained:function(m, e){

	var e=window.event || e

	var c=e.relatedTarget || ((e.type=="mouseover")? e.fromElement : e.toElement)

	while (c && c!=m)try {c=c.parentNode} catch(e){c=m}

	if (c==m)

		return true

	else

		return false

},
 

urlparamselect:function(tabsmenuid){

	var result=window.location.search.match(new RegExp(tabsmenuid+"=(\\w+)", "i")) //check for "?tabsmenuid=id_or_pos_of_selected_tab" in URL

	var selectedtabstr=RegExp.$1

	return /^\d+$/.test(selectedtabstr)? parseInt(selectedtabstr) : selectedtabstr //return position or ID of selected tab (or null if niether found)

},
 
 

addEvent:function(target, functionref, tasktype){

	if (target.addEventListener)

		target.addEventListener(tasktype, functionref, false);

	else if (target.attachEvent)

		target.attachEvent('on'+tasktype, function(){return functionref.call(target, window.event)});

},
 

init:function(tabsmenuid, submenuid, disappearBool){

	this.tabsmenutree[tabsmenuid]={} 

	this.tabsmenutree[tabsmenuid].tabs=[] //array referencing the active tab links in this menu (ones with a "rel=gotsubmenu" attr)

	this.tabsmenutree[tabsmenuid].submenu=null //reference submenu DIV for this menu

	this.tabsmenutree[tabsmenuid].submenu_divs=[] //array referencing the submenu contents (external DIVs with class="tabsmenucontent")

	var submenu=document.getElementById(submenuid)

	submenu._parentid=tabsmenuid

	this.tabsmenutree[tabsmenuid].submenu=submenu //remember this DIV as menu's submenu container

	var remoteurl=submenu.getElementsByTagName("a")[0].getAttribute("href")

	this.ajaxload(tabsmenuid, submenuid, disappearBool, remoteurl)

}
 

}
 

document.write('<style type="text/css">\n.tabsmenucontent{display:none}\n</style>')

Open in new window

0
 

Author Comment

by:beverleydunster
ID: 24343362
Hi

Thanks very much for this - it seems to have had an effect - but not quite the right one. The entire .js file has been updated with your code - see the result here:
http://www.cybersentinel.co.uk/test/

I'm getting two JS errors in the browser, as below...

Webpage error details

User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; Sky Broadband; GTB6; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; InfoPath.2; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Timestamp: Sat, 9 May 2009 11:45:53 UTC


Message: Object expected
Line: 53
Char: 42
Code: 0
URI: http://www.cybersentinel.co.uk/test/Scripts/mouseovertabs.js


Message: Object expected
Line: 53
Char: 42
Code: 0
URI: http://www.cybersentinel.co.uk/test/Scripts/mouseovertabs.js


0
 

Author Comment

by:beverleydunster
ID: 24344249
... I should just add that it does seem to maintain the sub-navigation when you mouse-out - but it's maintaining the sub-nav of the last tab hovered over - rather than reverting to the sub-navigation of the active tab.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 8

Expert Comment

by:Bobaran98
ID: 24344283
Yep, I've got it figured out.  My changes don't make for the cleanest code in history, mostly because I haven't taken the time to figure out what every line of code does, but this should meet your needs just fine.  I did take a few minutes to setup a test bed here with your files, so I was able to test it and it works just fine.  So down below should be the fully operational JS file!

And just so you understand, this will work such that the navigation always defaults to your initially selected option-- it's not hardcoded to HOMEPAGE.  It just looks for whichever link option has:

rel="gotsubmenu[selected]"

Let me know if you have any more problems!
//Mouseover Tabs Menu: By http://www.dynamicdrive.com

//** Aug 4th, 08': Script creation date

//CHANGES: 5/9/2009 Bobaran98 - to reset tabs to original state on mouseout event; simple worakarounds only!

 

var uberSelected;	//added by Bobaran98 5/9/2009

var uberInnerDiv;	//added by Bobaran98 5/9/2009

var uberTabsMenuTree;	//added by Bobaran98 5/9/2009

 

var mouseovertabsmenu={

 

disappeardelay: 250, //set delay in miliseconds before sub menu disappears onmouseout

ajaxloadingmsg: 'Loading Sub Menu Contents...', //Message to show inside sub menu while fetching contents

 

///////No need to edit beyond here//////////////////////

 

tabsmenutree:{},

 

initializetabs:function(tabsmenuid, submenuid, tabcontentsLength, disappearBool){

	var tabmenu=document.getElementById(tabsmenuid)

	var tablinks=tabmenu.getElementsByTagName("a")

	var submenu=document.getElementById(submenuid)

	var selected=null, tablinks_count=0

	for (var i=0; i<tablinks.length; i++){

		tablinks[i]._parentid=tabsmenuid

		var relattr=tablinks[i].getAttribute("rel")

		if (/^gotsubmenu/i.test(relattr) && tablinks_count<tabcontentsLength){ //if "rel" attribute starts with="gotsubmenu" and a tab content exists for this tab based on its order

			tablinks[i]._pos=tablinks_count //remember position of this tab relative to its active peers

			if (relattr.indexOf("[selected]")!=-1){

				selected=tablinks_count

			}

			this.addEvent(tablinks[i], function(){

				var tabsmenutree=mouseovertabsmenu.tabsmenutree[this._parentid]

				mouseovertabsmenu.clearhidetimer(tabsmenutree.submenu.hidetimer)

				mouseovertabsmenu.showsubmenu(this)

			}, "mouseover")

			tablinks_count++

			this.tabsmenutree[tabsmenuid].tabs.push(tablinks[i]) //add this tab to tab collection

		}

		else{ //else for regular tab links (with no "rel" attribute)

			this.addEvent(tablinks[i], function(){

				mouseovertabsmenu.hidesubmenu(this._parentid)

			}, "mouseover")

		}

	}

	this.addEvent(submenu, function(e){

		mouseovertabsmenu.clearhidetimer(this.hidetimer)

	}, "mouseover")

	if (disappearBool==true){

		this.addEvent(submenu, function(e){ //hide submenu contents when mouse rolls out of submenu DIV

			if (!mouseovertabsmenu.isContained(this, e)){

				var cursubmenuobj=this

				// commented out by Bobaran98 5/9/2009:

				//this.hidetimer=setTimeout(function(){mouseovertabsmenu.hidesubmenu(cursubmenuobj._parentid)}, mouseovertabsmenu.disappeardelay)

				// added by Bobaran98 5/9/2009:

				this.hidetimer=setTimeout(function(){mouseovertabsmenu.resettabs(cursubmenuobj._parentid,uberSelected)}, mouseovertabsmenu.disappeardelay)

			}

		}, "mouseout")

	}

	var urlselected=this.urlparamselect(tabsmenuid)

	//return position of selected tab (relative to its peers), or null

	return typeof urlselected=="number"? urlselected : document.getElementById(urlselected)? document.getElementById(urlselected)._pos : selected

},
 

resettabs:function(hidemenuID, showmenuID){		//function added by Bobaran98 5/9/2009

	mouseovertabsmenu.hidesubmenu(hidemenuID)

	uberInnerDiv[showmenuID].style.display="block"

	this.css(uberTabsMenuTree.tabs[showmenuID], "selected", "add")

	uberTabsMenuTree.submenu._prevselected=showmenuID

},

 

ajaxload:function(tabsmenuid, submenuid, disappearBool, url){

	var page_request = false

	if (window.ActiveXObject){ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)

		try {

		page_request = new ActiveXObject("Msxml2.XMLHTTP")

		} 

		catch (e){

			try{

			page_request = new ActiveXObject("Microsoft.XMLHTTP")

			}

			catch (e){}

		}

	}

	else if (window.XMLHttpRequest) // if Mozilla, Safari etc

		page_request = new XMLHttpRequest()

	else

		return false

	var tabsmenutree=this.tabsmenutree[tabsmenuid]

	tabsmenutree.submenu.innerHTML=this.ajaxloadingmsg

	//var ajaxfriendlyurl=url.replace(/^http:\/\/[^\/]+\//i, "http://"+window.location.hostname+"/") 

	var ajaxfriendlyurl=url.replace(/^http:\/\/[^\/]+\//i, "http://www.cybersentinel.co.uk/")		//put me back the way i was!

	page_request.onreadystatechange=function(){

		mouseovertabsmenu.ajaxpopulate(page_request, tabsmenuid, submenuid, disappearBool, ajaxfriendlyurl)

	}

	var bustcache=(ajaxfriendlyurl.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime()

	page_request.open('GET', ajaxfriendlyurl+bustcache, true)

	page_request.send(null)

},

 

ajaxpopulate:function(page_request, tabsmenuid, submenuid, disappearBool, url){

	if (page_request.readyState == 4 && (page_request.status==200 || window.location.href.indexOf("http")==-1)){

		var tabsmenutree=this.tabsmenutree[tabsmenuid]

		tabsmenutree.submenu.innerHTML=page_request.responseText

		var innerdivs=tabsmenutree.submenu.getElementsByTagName("div")

		for (var i=0; i<innerdivs.length; i++){

			if (/tabsmenucontent/i.test(innerdivs[i].className)){

				tabsmenutree.submenu_divs.push(innerdivs[i])

			}

		}

		var selected=this.initializetabs(tabsmenuid, submenuid, tabsmenutree.submenu_divs.length, disappearBool)

		if (selected!=null && selected<tabsmenutree.submenu_divs.length){

			uberSelected = selected;	//added by Bobaran98 5/9/2009

			uberInnerDiv = innerdivs;	//added by Bobaran98 5/9/2009

			uberTabsMenuTree = tabsmenutree;	//added by Bobaran98 5/9/2009

			innerdivs[selected].style.display="block"

			this.css(tabsmenutree.tabs[selected], "selected", "add")

			tabsmenutree.submenu._prevselected=selected

		}

	}

},

 

showsubmenu:function(linkobj){

	var tabsmenutree=this.tabsmenutree[linkobj._parentid]

	this.hidesubmenu(linkobj._parentid)

	var selected=parseInt(linkobj._pos)

	tabsmenutree.submenu_divs[selected].style.display="block"

	this.css(tabsmenutree.tabs[selected], "selected", "add")

	tabsmenutree.submenu._prevselected=selected

},

 

hidesubmenu:function(tabsmenuid){

	var tabsmenutree=this.tabsmenutree[tabsmenuid]

	var prevselectedindex=tabsmenutree.submenu._prevselected

	if (typeof prevselectedindex!="undefined"){

		tabsmenutree.submenu_divs[prevselectedindex].style.display="none"

		this.css(tabsmenutree.tabs[prevselectedindex], "selected", "remove")

	}

},

 

clearhidetimer:function(timerid){

	if (timerid)

		clearTimeout(timerid)

},

 

css:function(el, targetclass, action){

	var needle=new RegExp("(^|\\s+)"+targetclass+"($|\\s+)", "ig")

	if (action=="check")

		return needle.test(el.className)

	else if (action=="remove")

		el.className=el.className.replace(needle, "")

	else if (action=="add" && !needle.test(el.className))

		el.className+=" "+targetclass

},

 

isContained:function(m, e){

	var e=window.event || e

	var c=e.relatedTarget || ((e.type=="mouseover")? e.fromElement : e.toElement)

	while (c && c!=m)try {c=c.parentNode} catch(e){c=m}

	if (c==m)

		return true

	else

		return false

},

 

urlparamselect:function(tabsmenuid){

	var result=window.location.search.match(new RegExp(tabsmenuid+"=(\\w+)", "i")) //check for "?tabsmenuid=id_or_pos_of_selected_tab" in URL

	var selectedtabstr=RegExp.$1

	return /^\d+$/.test(selectedtabstr)? parseInt(selectedtabstr) : selectedtabstr //return position or ID of selected tab (or null if niether found)

},

 

 

addEvent:function(target, functionref, tasktype){

	if (target.addEventListener)

		target.addEventListener(tasktype, functionref, false);

	else if (target.attachEvent)

		target.attachEvent('on'+tasktype, function(){return functionref.call(target, window.event)});

},

 

init:function(tabsmenuid, submenuid, disappearBool){

	this.tabsmenutree[tabsmenuid]={} 

	this.tabsmenutree[tabsmenuid].tabs=[] //array referencing the active tab links in this menu (ones with a "rel=gotsubmenu" attr)

	this.tabsmenutree[tabsmenuid].submenu=null //reference submenu DIV for this menu

	this.tabsmenutree[tabsmenuid].submenu_divs=[] //array referencing the submenu contents (external DIVs with class="tabsmenucontent")

	var submenu=document.getElementById(submenuid)

	submenu._parentid=tabsmenuid

	this.tabsmenutree[tabsmenuid].submenu=submenu //remember this DIV as menu's submenu container

	var remoteurl=submenu.getElementsByTagName("a")[0].getAttribute("href")

	this.ajaxload(tabsmenuid, submenuid, disappearBool, remoteurl)

}

 

}

 

document.write('<style type="text/css">\n.tabsmenucontent{display:none}\n</style>')

Open in new window

0
 
LVL 8

Accepted Solution

by:
Bobaran98 earned 500 total points
ID: 24344312
By the way, I noticed at least one word in your keywords listing for which we Americans have a variant spelling (paedophile/pedophile).  I'm not sure just how effective meta tags are these days in terms of influencing search results, but it can't hurt to include variants, at least if you've got any interest in generating sales across the pond.

Search engine optimization (or SEO) isn't at all my area of expertise, but if you're interested, I think we've got a fair amount of activity on EE discussing the topic.  Just searching for "search engine optimization" or "SEO" will get you a fair number of results, and if you've got specific questions, you could either search for them or ask.

I know, I know, unasked for advice. :-)  Good luck on your venture!
0
 

Author Closing Comment

by:beverleydunster
ID: 31579370
Bobaran98 - a real helpful expert. Never thought I'd get a solution to this but it works perfectly. Thank you so much for your help!
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
Styling your websites can become very complex. Here I'll show how SASS can help you better organize, maintain and reuse your CSS code.
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will receive an overview of the basics of CSS showing inline styles. In the head tags set up your style tags: (CODE) Reference the nav tag and set your properties.: (CODE) Set the reference for the UL element and styles for it to ensu…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now