/** * @file menu.js * @version 20170907 ms * @type JS */ /** * @class KMenu * @constructor * @param callback */ function KMenu(callback){ this.o; this.oX; this.oY; this.vigin; this.table; this.callback=callback; this.parent; this.sub; this.v=0; this.Clear(); } /** * @fn Clear */ KMenu.prototype.Clear=function(){ this.items=[]; } /** * @fn Count * @returns {int} items.length */ KMenu.prototype.Count=function(){ return this.items.length; } /** * @fn GetAbsLeft * @memberof KMenu * @param o * @return * Private static method. */ KMenu.GetAbsLeft=function(o){ return o.getBoundingClientRect().left+pageXOffset; } /** * @fn GetAbsTop * @memberof KMenu * @param {object} o * @return * Private static method. */ KMenu.GetAbsTop=function(o){ return o.getBoundingClientRect().top+pageYOffset; } /** * @fn WindowWidth * @memberof KMenu * @return {int} * Private static method. */ KMenu.WindowWidth=function(){ return window.innerWidth && document.documentElement.clientWidth? Math.min(window.innerWidth, document.documentElement.clientWidth) : window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; }; /** * @fn WindowHeight * @memberof KMenu * @return {int} * Private static method. */ KMenu.WindowHeight=function(){ return window.innerHeight && document.documentElement.clientHeight? Math.min(window.innerHeight, document.documentElement.clientHeight) : window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; }; /** * @fn Html2Object * @memberof KMenu * @param {string} html * @return {HTMLElement::div} * Private static method. * create a div-container with html from param and returns the firstChild of div-Node */ KMenu.Html2Object=function(html){ var p=document.createElement("div");p.innerHTML=html; return p.firstChild; } /** * @fn Insert * @memberof KMenu * @param popFuncName: dynamically load sub-menu; uses target, funcParam and funcParam2 as parameters */ KMenu.prototype.Insert=function(caption,icon,target,funcName,funcParam,funcParam2,index,subMenu,popFuncName){ if(typeof index!="number") index=this.items.length; this.items.splice(index,0,{caption:caption,icon:icon,target:target,funcName:funcName,funcParam:funcParam,funcParam2:funcParam2,sub:popFuncName?true:subMenu,pop:popFuncName}); } /** * @fn InsertSub * @memberof KMenu * @params caption,icon,subMenu,index,popFuncName */ KMenu.prototype.InsertSub=function(caption,icon,subMenu,index,popFuncName){ if(typeof index=="undefined") index=this.items.length; this.items.splice(index,0,{caption:caption,sub:popFuncName?true:subMenu,pop:popFuncName}); } /** * @fn HookEvent * @memberof KMenu * @params o,eventName,target,funcName,funcParam,funcParam2 */ KMenu.HookEvent=function(o,eventName,target,funcName,funcParam,funcParam2){ o.addEventListener(eventName,function(){target[funcName](funcParam,funcParam2)}); } /** * @fn Pop * @memberof KMenu * @param */ KMenu.prototype.Pop=function(oX,oY,parent,oWidth){ if(!this.items.length) return; if(this.o) this.Close(); this.oX=oX;this.oY=oY;this.vigin=true; this.o=KMenu.Html2Object(this.Template.bg); this.o.style.position="absolute";this.o.style.zIndex="9999"; this.o.oncontextmenu=function(e){e.preventDefault()}; this.table=document.createElement("table");this.table.style.borderSpacing="0";this.table.style.borderCollapse="collapse";this.o.firstChild.appendChild(this.table); var m=this; for(var a=0;aKMenu.WindowHeight()){ y-=h;if(yKMenu.WindowHeight()){var st=this.o.firstChild.style;st.height=KMenu.WindowHeight()+"px";st.overflowY="scroll";} } var x=oX;if(oWidth) x+=oWidth; var w=this.o.offsetWidth; if(x+w-pageXOffset>KMenu.WindowWidth()) x=Math.max(0,oX-w); this.o.style.left=x+"px"; this.o.style.top=y+"px"; this.parent=parent; if(!parent) this.dmml=document.addEventListener("mousemove",function(e){m.MouseMove(e)}); return this; } /** * @fn ShowSub * @memberof KMenu * @param i * @return */ KMenu.prototype.ShowSub=function(i){ var o=this.table.rows[i]; var oX=KMenu.GetAbsLeft(this.o); var oY=KMenu.GetAbsTop(this.o)+o.offsetTop-(this.o.firstChild.scrollTop?this.o.firstChild.scrollTop:0); var oWidth=this.o.offsetWidth; this.v++; if(this.items[i].pop){ var item=this.items[i]; item.target[item.pop](item.funcParam,item.funcParam2,this,oX,oY,oWidth,this.v); }else this.PopSub(this.items[i].sub,oX,oY,oWidth,this.v); } /** * @fn PopSub * @memberof KMenu * @params menu,oX,oY,oWidth,v) * @return */ KMenu.prototype.PopSub=function(menu,oX,oY,oWidth,v){ if(v==this.v){ this.CloseSub(); this.sub=menu.Pop(oX,oY,this,oWidth); } } /** * @fn CloseSub * @memberof KMenu * @return */ KMenu.prototype.CloseSub=function(){ if(this.sub){this.sub.Close();this.sub=null} } /** * @fn LeaveSub * @memberof KMenu */ KMenu.prototype.LeaveSub=function(){ if(this.sub) this.sub.Leave(); } /** * @fn Leave * @memberof KMenu * @return */ KMenu.prototype.Leave=function(){ if(this.parent) this.parent.Leave(); var m=this; if(!this.CloseTimer) this.CloseTimer=setTimeout(function(){m.Close()},300); } /** * @fn Hold * @memberof KMenu */ KMenu.prototype.Hold=function(){ this.vigin=false; if(this.parent) this.parent.Hold(); if(this.CloseTimer){clearTimeout(this.CloseTimer);this.CloseTimer=0} } /** * @fn Close * @memberof KMenu * @param hit */ KMenu.prototype.Close=function(hit){ this.Hold(); if(this.parent) this.parent.vigin=true; if(this.dmml) document.removeEventListener("mousemove",this.dmml); this.CloseSub(); if(this.o){this.o.parentNode.removeChild(this.o);this.o=null} if(hit && this.parent) this.parent.Close(true); if(this.callback) this.callback.MenuClosed(); } /** * @fn Hit * @memberof KMenu */ KMenu.prototype.Hit=function(){ this.Close(true); } /** * @fn MouseMove * @memberof KMenu * @param {event} e */ KMenu.prototype.MouseMove=function(e){ if(this.vigin && (Math.abs(this.oX-(e.clientX+pageXOffset))>5 || Math.abs(this.oY-(e.clientY+pageYOffset))>5)) this.Leave(); } /// @var {array} Template /// @see KMenu.Pop KMenu.prototype.Template={ bg:"
", item:"
{content}
", sub:"
{content} ►
", gap:"
", hooverBgColor:"#D3E1E7" }