PDA

View Full Version : Mouse Over Tabs Menu - questions about selected functionality



jrattinger
01-04-2013, 08:57 AM
) Script Title: mouseover tabs menu

2) Script URL (on DD):
http://www.dynamicdrive.com/dynamicindex1/mouseovertabs.htm

3) Describe problem:

I love the script, but my client wants a few additional options...
- Is it possible to have a selected sub-menu item stay hi-lighted once the site goes to that link? i don't see a "selected" class for the sub menu items>
- Is it possible to only hi-light the main menu item after it has been selected or navigated to, or the "mytabsmenu=0" was used in the URL? Or in other words, my client does not want the main menu to do anything when hovering, only when selected.

Thanks!

vwphillips
01-04-2013, 02:10 PM
this uses a cookie

the days duration is set at the top of the script marked in red


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title></title>
<style type="text/css">
/*<![CDATA[*/
/* ######### CSS for top level tabs ######### */

.tabsmenuclass ul{
overflow: hidden;
width: auto;
margin: 0;
padding: 0;
list-style-type: none;
}

.tabsmenuclass li{
float: left;
}

.tabsmenuclass a{
display: block;
padding: 5px 7px;
background: #E8E8E8;
color: black;
margin-right: 1px;
text-decoration: none;
font: bold 13px Arial;
}

.tabsmenuclass a:hover, .tabsmenuclass a.selected{
background: black;
color: white;
}

/* ######### CSS for sub menu container below ######### */

.tabsmenucontentclass{
clear: left;
background: #E8E8E8;
width: 90%;
height: 24px;
padding: 5px;
border: 1px solid silver;
}

.tabsmenucontentclass ul{
margin: 0;
padding: 0;
list-style-type: none;
}

.tabsmenucontentclass li{
float: left;
margin-right: 1em;
}
/*]]>*/
</style>
<script type="text/javascript">

//Mouseover Tabs Menu: By http://www.dynamicdrive.com
//** Aug 4th, 08': Script creation date

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
days:1, // the number of days persistence
///////No need to edit beyond here//////////////////////

tabsmenutree:{},

initializetabs:function(tabsmenuid, submenuid, tabcontentsLength, disappearBool){
var lst=this.cookie(tabsmenuid);
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 (lst==i||(lst<0&&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
this.hidetimer=setTimeout(function(){mouseovertabsmenu.hidesubmenu(cursubmenuobj._parentid)}, 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
},

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){
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
this.cookieset(linkobj._parentid,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")
}
this.cookieset(tabsmenuid,-1)
},

cookie:function(nme){
var re=new RegExp(nme+'=[^;]+','i');
if (document.cookie.match(re)){
return document.cookie.match(re)[0].split("=")[1];
}
return -1;
},

cookieset:function(nme,nu){
if (typeof(this.days)=='number'){
document.cookie=nme+'='+nu+';expires='+(new Date(new Date().getTime()+this.days*86400000).toGMTString())+';path=/';
}
},

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>')

</script>

</head>

<body>
<div id="mytabsmenu" class="tabsmenuclass">
<ul>
<li><a href="http://www.javascriptkit.com" rel="gotsubmenu[selected]">JavaScript Kit</a></li>
<li><a href="http://www.cssdrive.com" rel="gotsubmenu">CSS Drive</a></li>
<li><a href="http://www.codingforums.com">No Sub Menu</a></li>
</ul>
</div>

<div id="mysubmenuarea" class="tabsmenucontentclass">

<!--1st link within submenu container should point to the external submenu contents file-->
<a href="submenucontents.htm" style="visibility:hidden">Sub Menu contents</a>

</div>

<script type="text/javascript">
//mouseovertabsmenu.init("tabs_container_id", "submenu_container_id", "bool_hidecontentsmouseout")
mouseovertabsmenu.init("mytabsmenu", "mysubmenuarea", true)

</script>
</body>

</html>

jrattinger
01-04-2013, 03:10 PM
Hi Vic,

Thanks for your response!

I inserted your script, but i don't see any difference in the behavior. I do see the cookie and it is saving the correct main tab index. Either i'm missing something, or perhaps wasn't clear about my requirements...

On the main tab, i would like to not have the item hovered on, to be hi-lighted. Only when the link is followed, would i like that menu item to be hi-lighted. I know this is not intuitive, but what the client wants.

Additionally, and more importantly, i want the sub menu items to be hi-lighted after the sub menu link is followed.

Does this require more work or use of the cookie?

Thanks,
John

vwphillips
01-05-2013, 12:53 PM
try


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title></title>
<style type="text/css">
/*<![CDATA[*/
/* ######### CSS for top level tabs ######### */

.tabsmenuclass ul{
overflow: hidden;
width: auto;
margin: 0;
padding: 0;
list-style-type: none;
}

.tabsmenuclass li{
float: left;
}

.tabsmenuclass a{
display: block;
padding: 5px 7px;
background: #E8E8E8;
color: black;
margin-right: 1px;
text-decoration: none;
font: bold 13px Arial;
}

.tabsmenuclass a:hover, .tabsmenuclass a.selected{
background: black;
color: white;
}

/* ######### CSS for sub menu container below ######### */

.tabsmenucontentclass{
clear: left;
background: #E8E8E8;
width: 90%;
height: 24px;
padding: 5px;
border: 1px solid silver;
}

.tabsmenucontentclass ul{
margin: 0;
padding: 0;
list-style-type: none;
}

.tabsmenucontentclass li{
float: left;
margin-right: 1em;
}
/*]]>*/
</style>
<script type="text/javascript">

//Mouseover Tabs Menu: By http://www.dynamicdrive.com
//** Aug 4th, 08': Script creation date

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
days:1, // the number of days persistence
///////No need to edit beyond here//////////////////////

tabsmenutree:{},

initializetabs:function(tabsmenuid, submenuid, tabcontentsLength, disappearBool,tab){
var lst=tab||this.cookie(tabsmenuid);
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&&lst<0)||lst==i)&&!selected){
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
this.hidetimer=setTimeout(function(){mouseovertabsmenu.hidesubmenu(cursubmenuobj._parentid)}, 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
},

ajaxload:function(tabsmenuid, submenuid, disappearBool, url,tab){
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,tab)
}
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,tab){
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,tab)
if (selected!=null && selected<tabsmenutree.submenu_divs.length){
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
this.cookieset(linkobj._parentid,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")
}
this.cookieset(tabsmenuid,-1)
},

cookie:function(nme){
var re=new RegExp(nme+'=[^;]+','i');
if (document.cookie.match(re)){
return document.cookie.match(re)[0].split("=")[1];
}
return -1;
},

cookieset:function(nme,nu){
if (typeof(this.days)=='number'){
document.cookie=nme+'='+nu+';expires='+(new Date(new Date().getTime()+this.days*86400000).toGMTString())+';path=/';
}
},

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,tab){
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,tab?-1:false)
}

}

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

</script>

</head>

<body>
<div id="mytabsmenu" class="tabsmenuclass">
<ul>
<li><a href="http://www.javascriptkit.com" rel="gotsubmenu[selected]">JavaScript Kit</a></li>
<li><a href="http://www.cssdrive.com" rel="gotsubmenu">CSS Drive</a></li>
<li><a href="http://www.codingforums.com">No Sub Menu</a></li>
</ul>
</div>

<div id="mysubmenuarea" class="tabsmenucontentclass">

<!--1st link within submenu container should point to the external submenu contents file-->
<a href="submenucontents3.htm" style="visibility:hidden">Sub Menu contents</a>

</div>

<script type="text/javascript">
//mouseovertabsmenu.init("tabs_container_id", "submenu_container_id", "bool_hidecontentsmouseout", true = do not use cookie = forced to use selected)
mouseovertabsmenu.init("mytabsmenu", "mysubmenuarea",'',true);
</script>
</body>

</html>

jrattinger
01-20-2013, 02:06 AM
Hi Vic,
Thanks for you help so far. I tried to enhance your script a bit, but ran into a lot of problems (I'm not exactly a javascript guru...lol). Anyway, my requirements have changed a little bit. I have just created a new post that is a little different than this one and hopefully a little clearer too. you can find it here - http://www.dynamicdrive.com/forums/showthread.php?72677-Mouse-Over-Tabs-Menu-current-vs-selected-menu-items

Thanks!