PDA

View Full Version : Delay menu appearence in anylink CSS menu



roylazarovich
02-07-2009, 05:04 PM
1) Script Title: AnyLink CSS Menu v2.0

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

3) Describe problem:

Hello everyone.

I'm looking to delay the menu from opening until the mouse cursor has hovered over the menu link for 1 second, currently the menu opens up instantly when the mouse cursor is over it, even if the mouse cursor is only traveling across it on its way to another menu link below it, in which case the menu covers the desired link, I know about the [click] suffix that can be added to make the menu open onClick but I need the menu to appear on mouse hover.

Thank you very much

Javascript code included below:


var anylinkcssmenu={

menusmap: {},
effects: {delayhide: 200, shadow:{enabled:true, opacity:0.3, depth: [5, 5]}, fade:{enabled:true, duration:400}}, //customize menu effects

dimensions: {},

getoffset:function(what, offsettype){
return (what.offsetParent)? what[offsettype]+this.getoffset(what.offsetParent, offsettype) : what[offsettype]
},

getoffsetof:function(el){
el._offsets={left:this.getoffset(el, "offsetLeft"), top:this.getoffset(el, "offsetTop"), h: el.offsetHeight}
},

getdimensions:function(menu){
this.dimensions={anchorw:menu.anchorobj.offsetWidth, anchorh:menu.anchorobj.offsetHeight,
docwidth:(window.innerWidth ||this.standardbody.clientWidth)-20,
docheight:(window.innerHeight ||this.standardbody.clientHeight)-15,
docscrollx:window.pageXOffset || this.standardbody.scrollLeft,
docscrolly:window.pageYOffset || this.standardbody.scrollTop
}
if (!this.dimensions.dropmenuw){
this.dimensions.dropmenuw=menu.dropmenu.offsetWidth
this.dimensions.dropmenuh=menu.dropmenu.offsetHeight
}
},

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
},

setopacity:function(el, value){
el.style.opacity=value
if (typeof el.style.opacity!="string"){ //if it's not a string (ie: number instead), it means property not supported
el.style.MozOpacity=value
if (el.filters){
el.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity="+ value*100 +")"
}
}
},

showmenu:function(menuid){
var menu=anylinkcssmenu.menusmap[menuid]
clearTimeout(menu.hidetimer)
this.getoffsetof(menu.anchorobj)
this.getdimensions(menu)
var posx=menu.anchorobj._offsets.left + (menu.orientation=="lr"? this.dimensions.anchorw : 0) //base x pos
var posy=menu.anchorobj._offsets.top+this.dimensions.anchorh - (menu.orientation=="lr"? this.dimensions.anchorh : 0)//base y pos
if (posx+this.dimensions.dropmenuw+this.effects.shadow.depth[0]>this.dimensions.docscrollx+this.dimensions.docwidth){ //drop left instead?
posx=posx-this.dimensions.dropmenuw + (menu.orientation=="lr"? -this.dimensions.anchorw : this.dimensions.anchorw)
}
if (posy+this.dimensions.dropmenuh>this.dimensions.docscrolly+this.dimensions.docheight){ //drop up instead?
posy=Math.max(posy-this.dimensions.dropmenuh - (menu.orientation=="lr"? -this.dimensions.anchorh : this.dimensions.anchorh), this.dimensions.docscrolly) //position above anchor or window's top edge
}
if (this.effects.fade.enabled){
this.setopacity(menu.dropmenu, 0) //set opacity to 0 so menu appears hidden initially
if (this.effects.shadow.enabled)
this.setopacity(menu.shadow, 0) //set opacity to 0 so shadow appears hidden initially
}
menu.dropmenu.setcss({left:posx+'px', top:posy+'px', visibility:'visible'})
if (this.effects.shadow.enabled)
menu.shadow.setcss({left:posx+anylinkcssmenu.effects.shadow.depth[0]+'px', top:posy+anylinkcssmenu.effects.shadow.depth[1]+'px', visibility:'visible'})
if (this.effects.fade.enabled){
clearInterval(menu.animatetimer)
menu.curanimatedegree=0
menu.starttime=new Date().getTime() //get time just before animation is run
menu.animatetimer=setInterval(function(){anylinkcssmenu.revealmenu(menuid)}, 20)
}
},

revealmenu:function(menuid){
var menu=anylinkcssmenu.menusmap[menuid]
var elapsed=new Date().getTime()-menu.starttime //get time animation has run
if (elapsed<this.effects.fade.duration){
this.setopacity(menu.dropmenu, menu.curanimatedegree)
if (this.effects.shadow.enabled)
this.setopacity(menu.shadow, menu.curanimatedegree*this.effects.shadow.opacity)
}
else{
clearInterval(menu.animatetimer)
this.setopacity(menu.dropmenu, 1)
menu.dropmenu.style.filter=""
}
menu.curanimatedegree=(1-Math.cos((elapsed/this.effects.fade.duration)*Math.PI)) / 2
},

setcss:function(param){
for (prop in param){
this.style[prop]=param[prop]
}
},

hidemenu:function(menuid){
var menu=anylinkcssmenu.menusmap[menuid]
clearInterval(menu.animatetimer)
menu.dropmenu.setcss({visibility:'hidden', left:0, top:0})
menu.shadow.setcss({visibility:'hidden', left:0, top:0})
},

getElementsByClass:function(targetclass){
if (document.querySelectorAll)
return document.querySelectorAll("."+targetclass)
else{
var classnameRE=new RegExp("(^|\\s+)"+targetclass+"($|\\s+)", "i") //regular expression to screen for classname
var pieces=[]
var alltags=document.all? document.all : document.getElementsByTagName("*")
for (var i=0; i<alltags.length; i++){
if (typeof alltags[i].className=="string" && alltags[i].className.search(classnameRE)!=-1)
pieces[pieces.length]=alltags[i]
}
return pieces
}
},

addEvent:function(targetarr, functionref, tasktype){
if (targetarr.length>0){
var target=targetarr.shift()
if (target.addEventListener)
target.addEventListener(tasktype, functionref, false)
else if (target.attachEvent)
target.attachEvent('on'+tasktype, function(){return functionref.call(target, window.event)})
this.addEvent(targetarr, functionref, tasktype)
}
},

setupmenu:function(targetclass, anchorobj, pos){
this.standardbody=(document.compatMode=="CSS1Compat")? document.documentElement : document.body
var relattr=anchorobj.getAttribute("rel")
var dropmenuid=relattr.replace(/\[(\w+)\]/, '')
var menu=this.menusmap[targetclass+pos]={
id: targetclass+pos,
anchorobj: anchorobj,
dropmenu: document.getElementById(dropmenuid),
revealtype: (relattr.length!=dropmenuid.length && RegExp.$1=="click")? "click" : "mouseover",
orientation: anchorobj.getAttribute("rev")=="lr"? "lr" : "ud",
shadow: document.createElement("div")
}
menu.anchorobj._internalID=targetclass+pos
menu.anchorobj._isanchor=true
menu.dropmenu._internalID=targetclass+pos
menu.shadow._internalID=targetclass+pos
menu.shadow.className="anylinkshadow"
document.body.appendChild(menu.dropmenu) //move drop down div to end of page
document.body.appendChild(menu.shadow)
menu.dropmenu.setcss=this.setcss
menu.shadow.setcss=this.setcss
menu.shadow.setcss({width: menu.dropmenu.offsetWidth+"px", height:menu.dropmenu.offsetHeight+"px"})
this.setopacity(menu.shadow, this.effects.shadow.opacity)
this.addEvent([menu.anchorobj, menu.dropmenu, menu.shadow], function(e){ //MOUSEOVER event for anchor, dropmenu, shadow
var menu=anylinkcssmenu.menusmap[this._internalID]
if (this._isanchor && menu.revealtype=="mouseover" && !anylinkcssmenu.isContained(this, e)){ //event for anchor
anylinkcssmenu.showmenu(menu.id)
}
else if (typeof this._isanchor=="undefined"){ //event for drop down menu and shadow
clearTimeout(menu.hidetimer)
}
}, "mouseover")
this.addEvent([menu.anchorobj, menu.dropmenu, menu.shadow], function(e){ //MOUSEOUT event for anchor, dropmenu, shadow
if (!anylinkcssmenu.isContained(this, e)){
var menu=anylinkcssmenu.menusmap[this._internalID]
menu.hidetimer=setTimeout(function(){anylinkcssmenu.hidemenu(menu.id)}, anylinkcssmenu.effects.delayhide)
}
}, "mouseout")
this.addEvent([menu.anchorobj, menu.dropmenu], function(e){ //CLICK event for anchor, dropmenu
var menu=anylinkcssmenu.menusmap[this._internalID]
if ( this._isanchor && menu.revealtype=="click"){
if (menu.dropmenu.style.visibility=="visible")
anylinkcssmenu.hidemenu(menu.id)
else
anylinkcssmenu.showmenu(menu.id)
if (e.preventDefault)
e.preventDefault()
return false
}
else
menu.hidetimer=setTimeout(function(){anylinkcssmenu.hidemenu(menu.id)}, anylinkcssmenu.effects.delayhide)
}, "click")
},

init:function(targetclass){
var anchors=this.getElementsByClass(targetclass)
for (var i=0; i<anchors.length; i++){
this.setupmenu(targetclass, anchors[i], i)
}
}

}

jscheuer1
02-07-2009, 06:46 PM
I think one second is too long, about a third of a second would probably be better but you can play with that.

Change (in anylinkcssmenu.js):



this.addEvent([menu.anchorobj, menu.dropmenu, menu.shadow], function(e){ //MOUSEOVER event for anchor, dropmenu, shadow
var menu=anylinkcssmenu.menusmap[this._internalID]
if (this._isanchor && menu.revealtype=="mouseover" && !anylinkcssmenu.isContained(this, e)){ //event for anchor
anylinkcssmenu.showmenu(menu.id)
}
else if (typeof this._isanchor=="undefined"){ //event for drop down menu and shadow
clearTimeout(menu.hidetimer)
}
}, "mouseover")
this.addEvent([menu.anchorobj, menu.dropmenu, menu.shadow], function(e){ //MOUSEOUT event for anchor, dropmenu, shadow
if (!anylinkcssmenu.isContained(this, e)){
var menu=anylinkcssmenu.menusmap[this._internalID]
menu.hidetimer=setTimeout(function(){anylinkcssmenu.hidemenu(menu.id)}, anylinkcssmenu.effects.delayhide)
}
}, "mouseout")

to:


this.addEvent([menu.anchorobj, menu.dropmenu, menu.shadow], function(e){ //MOUSEOVER event for anchor, dropmenu, shadow
var menu=anylinkcssmenu.menusmap[this._internalID]
if (this._isanchor && menu.revealtype=="mouseover" && !anylinkcssmenu.isContained(this, e)){ //event for anchor
anylinkcssmenu.timer=setTimeout(function(){anylinkcssmenu.showmenu(menu.id);}, 300);
}
else if (typeof this._isanchor=="undefined"){ //event for drop down menu and shadow
clearTimeout(menu.hidetimer)
}
}, "mouseover")
this.addEvent([menu.anchorobj, menu.dropmenu, menu.shadow], function(e){ //MOUSEOUT event for anchor, dropmenu, shadow
if (!anylinkcssmenu.isContained(this, e)){
clearTimeout(anylinkcssmenu.timer);
var menu=anylinkcssmenu.menusmap[this._internalID]
menu.hidetimer=setTimeout(function(){anylinkcssmenu.hidemenu(menu.id)}, anylinkcssmenu.effects.delayhide)
}
}, "mouseout")

The red 300 in the above is for about a third of a second delay, 1000 would be a full second delay.

roylazarovich
02-07-2009, 08:47 PM
Thank you very much, jscheuer1.

It worked!, hopefully other users will find this useful too