/* DynAPI Distribution HTMLMenu Class - based on Cascading Menu script from The JavaScript Source!! (http://javascript.internet.com) The DynAPI Distribution is distributed under the terms of the GNU LGPL license. Requires: HTMLComponent */ function HTMLMenu(css,orientation){ this.HTMLComponent = HTMLComponent; this.HTMLComponent(css); this._menu = []; // store menu items this._menuLink = []; // store menu link ids this._mnuTmr = 0; this._litNow = []; this._vertOrient = (orientation && orientation=='vert')? true:false; this.onCreate(this._assignElm); // necessary as menus needs to be created after page loads }; HTMLMenu._addItem = function(css,text,linkId,callback,length,spacing,backCol,selBgCol,cssText){ var itm = {}; var len = this._src._menu[this._mnuid].length; itm.id = this.id+len; itm.lid = linkId; if(typeof(text)!='object') { itm.text = text||''; itm.image = null; itm.contMode = (dynapi.ua.def)? true:false; } else { itm.image=text.image; itm.text=text.text||''; itm.contMode = text.contMode; // container mode }; itm.callback = (!callback && linkId)? false:callback; itm.length = length||this.height||this._src.mnuItmHeight; itm.cssName = css||this._src.cssMenuItem; itm.cssTextName = cssText||this._src.cssMenuText; itm.spacing = spacing||0; itm.backCol = backCol||this._src.backCol; itm.selBgCol = selBgCol||this._src.selBgCol; this._src._menu[this._mnuid][len] = itm; return itm.id; }; var p = dynapi.setPrototype('HTMLMenu','HTMLComponent'); // Design Properties p.backCol = '#003366'; p.selBgCol = '#336699'; p.cssMenuItem = 'HCMNUItm'; p.cssMenuText = 'HCMNUItmText'; p.mnuItmWidth = 40; p.mnuItmHeight = 20; p.mnuArrow = dynapi.functions.getImage(dynapi.library.path+'gui/images/menuarrow.gif',8,9).getHTML(); // Methods p._assignElm = function(elm){ var i,c,id,lyr,plyr; var mnu,itmName; if(!this._created) return; for (i = 0; i < this._menu.length; i++) { id = this.id+'Mnu' + i + 'Div'; if(i==0){ // assign root menu css plyr = this.HC.getLayerById(id,this.parent.doc); if(!plyr) { this._created = false; // not yet created return; } plyr.setVisible(true); mnu = this._menu[i][0]; mnu.elm = plyr; mnu.css = (dynapi.ua.ns4)? plyr:plyr.style; this.elm = plyr; this.css = (dynapi.ua.ns4)? plyr:plyr.style; this.doc = plyr.document; } else { // create other menu items inside document if(this['Menu'+i+'Embedded']) plyr = this['Menu'+i+'Embedded']; else { plyr = this._buildMenu(i); mnu = this._menu[i][0]; mnu.elm = plyr; mnu.css = (dynapi.ua.ns4)? plyr:plyr.style; this['Menu'+i+'Embedded'] = plyr; // menu item now exist inside the document } } // setup menu items for (c = 1; c < this._menu[i].length; c++) { itmName = this.id+'Mnu' + i + 'Itm' + c; lyr = this.HC.getLayerById(itmName,plyr.document); this._menu[i][c].elm =lyr; this._menu[i][c].css = (!dynapi.ua.ns4)? lyr.style:plyr.document[itmName]; } } //this._showOnly(0); }; p._buildMenu = function(currMenu){ var mnuImage,mnuImgAlg; var targetMenu; var w,h,itemID,mnu = this._menu[currMenu]; var str = '', itemX = 0, itemY = 0; if(!mnu) return ''; if(currMenu>0) mnu[0].css=null; // reset css to force _assignElm during TM generate // Items start from 1 in the array (0 is menu object itself, above). // Also use properties of each item nested in the other with() for construction. for (var currItem = 1; currItem < mnu.length; currItem++) with (mnu[currItem]) { itemID = this.id + 'Mnu' + currMenu + 'Itm' + currItem; // The width and height of the menu item - dependent on orientation! w = (!mnu[0].isRoot ? mnu[0].width : length); h = (!mnu[0].isRoot ? length : mnu[0].width); // In IE4 width must be a miniumum of 3 pixels. if (dynapi.ua.def) { str += '
'; // Setup menu image var imgParams if(!image) mnuImage =''; else { imgParams = image.params; mnuImgAlg = (imgParams && imgParams.align)? imgParams.align:'absmiddle'; mnuImage = '' } // Setup Image Text Direction dir = (imgParams && imgParams.textdir)? imgParams.textdir:'W'; dir = (dir+'').toUpperCase(); if(dir=='E') text = text+mnuImage; if(dir=='N') text = mnuImage+'
'+text; if(dir=='S') text = text+'
'+mnuImage; else text = mnuImage+text; // In IE/NS6+, add padding if there's a border to emulate NS4's layer padding. str += ''; if(lid && this._menuLink[lid]) { // Set target's parents to this menu item. linkMnu=this._menuLink[lid]; this._menu[linkMnu][0].parentMnu = currMenu; this._menu[linkMnu][0].parentItm = currItem; // Add popout indicator. if(currMenu!=0) str += ''; } str += '
' + (contMode? text:'' + text + '') +''+this.mnuArrow+'
' + (dynapi.ua.ns4 ? '' : '
'); if (!mnu[0].isRoot) itemY += length + spacing; else itemX += length + spacing; } var id = this.id+'Mnu' + currMenu + 'Div'; if(currMenu==0){ // first menu must be relatively positioned var attr; if(dynapi.ua.ns4) str = ''+str+''; else str = '
'+str+'
'; return str; } else if(this._created){ // add all other menus inside the document object var lyr; if (dynapi.ua.ie||dynapi.ua.opera) { document.body.insertAdjacentHTML('beforeEnd', ''); lyr = document.all[id]; lyr.style.visibility = "hidden"; } else if (dynapi.ua.dom) { var ptxt,r = document.body.ownerDocument.createRange(); r.setStartBefore(document.body); ptxt = r.createContextualFragment(''); document.body.appendChild(ptxt); lyr = document.body.lastChild; } else if (dynapi.ua.ns4) { lyr = new Layer(0); lyr.document.write(str); lyr.document.close(); lyr.zIndex = 10000; lyr.top = -100; lyr.visibility="hide"; } return lyr; } }; p._e = function(evt,mnuNum,itmNum){ var mnu = this._menu[mnuNum]; var index = mnu[0].id+itmNum; this._ePlaySnd(evt); // plays ordinary sound events: click, over & out if(evt=='click'){ this._evtResponse = this._defEvtResponse; if(mnu[itmNum] && mnu[itmNum].callback) { if(typeof(mnu[itmNum].callback)=='function') mnu[itmNum].callback(index); else eval(mnu[itmNum].callback); } if (mnu[itmNum].callback!=false) this._showOnly(0); } else if(evt=='mouseover'){ window.clearTimeout(this._mnuTmr); if(!mnu[itmNum].elm) return; lid=mnu[itmNum].lid; if(this._created && mnu[0].css==null) this._assignElm(); this._showOnly(mnuNum); this._litNow = this._getHierarchy(mnuNum, itmNum); mnu[0].lastItem = itmNum; // set last item this._changeCol(this._litNow, true); targetNum = this._menuLink[lid]; if (targetNum > 0) { if(mnuNum==0) { thisX = (dynapi.ua.ns4)? mnu[0].elm.pageX:parseInt(mnu[0].elm.offsetLeft||0); thisY = (dynapi.ua.ns4)? mnu[0].elm.pageY:parseInt(mnu[0].elm.offsetTop||0); if(!dynapi.ua.ns4){ thisX+=this.parent.getPageX(); thisY+=this.parent.getPageY(); } }else { thisX = parseInt(mnu[0].css.left||0); thisY = parseInt(mnu[0].css.top||0); } if(dynapi.ua.ns4){ if(!mnu[0].isRoot) thisX+=parseInt(mnu[itmNum].css.clip.width||0) else thisY+=parseInt(mnu[itmNum].css.clip.height||0) } else{ if(!mnu[0].isRoot) thisX+=parseInt(mnu[itmNum].css.width||0) + mnu[0].subMnuOffset; else thisY+=parseInt(mnu[itmNum].css.height||0) + mnu[0].subMnuOffset; } thisX += parseInt(mnu[itmNum].css.left||0); thisY += parseInt(mnu[itmNum].css.top||0); // auto-fold sub-menus var tarMnu = this._menu[targetNum]; if((thisX+tarMnu[0].width)>dynapi.document.getWidth()) { if(mnu[0]._mnuid) thisX-=(mnu[0].width+tarMnu[0].width); else { thisX=dynapi.document.getWidth()-tarMnu[0].width; } // remove subMenuOffset when sub-menus are folded inward if(!mnu[0].isRoot) thisX-=mnu[0].subMnuOffset; } if((thisY+(tarMnu[0].height*(tarMnu.length-1)))>dynapi.document.getHeight()) { if(mnu[0].isRoot && !mnu[0]._mnuid) thisY-=(tarMnu[0].height*tarMnu.length); else { thisY = dynapi.document.getHeight() - (tarMnu[0].height*(tarMnu.length-1)); } } with (tarMnu[0].css) { left = thisX + (dynapi.ua.def ? 'px':''); top = thisY + (dynapi.ua.def ? 'px':''); visibility = (dynapi.ua.ns4)? 'show':'visible'; } // plays special pop-up sound event if(this._lTargetNum!=targetNum) this._ePlaySnd('menuopen'); this._lTargetNum=targetNum; }else this._lTargetNum = mnu[0]._mnuid; } else if(evt=='mouseout'){ if ((mnuNum == 0) && !mnu[itmNum].lid) this._showOnly(0); else this._mnuTmr = window.setTimeout(this+'._showOnly(0)', 500); } // invoke event this.invokeEvent(evt,null,index); return this._evtResponse; }; p._getHierarchy = function(mnuNum, itmNum) { var mnu; var itmArray = [this._menu.length]; while(1) { itmArray[mnuNum] = itmNum; if (mnuNum == 0) return itmArray; mnu = this._menu[mnuNum][0]; itmNum = mnu.parentItm; mnuNum = mnu.parentMnu; } }; p._changeCol = function(changeArray, isOver) { var mnu,lmnu; var lastItem,newCol; var i,menu = this._menu; for (i = 0; i < changeArray.length; i++) { if(changeArray[i]) { lastItem = menu[i][0].lastItem; lmnu = menu[i][lastItem]; mnu = menu[i][changeArray[i]]; // Change the image of the menu if(lmnu.image) { img = lmnu.image; src = (img )? img.src:''; oversrc = (img && img.params && img.params.oversrc)? img.params.oversrc:src; newImg = isOver ? oversrc:src; img = (dynapi.ua.ns4)? mnu.elm.document.images[this.id+mnu.id]:document.images[this.id+mnu.id]; img.src = newImg; } // Change the colours of the div/layer background. newCol = isOver ? menu[i][lastItem].selBgCol:menu[i][lastItem].backCol; with (mnu.css) { if (dynapi.ua.ns4) bgColor = newCol; else backgroundColor = newCol; } } } }; p._showOnly = function(mnuNum) { var opnMnu = this._getHierarchy(mnuNum, 1); for (count = 0; count < this._menu.length; count++) { if (!opnMnu[count]) with(this._menu[count][0].css){ visibility = (dynapi.ua.ns4)? 'hide':'hidden'; left = -100; top = -100; } } this._changeCol(this._litNow, false); }; p.createMenuBar = function(id,itmWidth,itmHeight,subMnuOffset,padding){ var mnu = {}; var len = this._menu.length; mnu.id = id; mnu._mnuid = len; //menu id; mnu.isRoot = (!this._vertOrient && this._menu.length==0)? true:false; mnu.width = itmWidth||this.mnuItmWidth; mnu.height = itmHeight||this.mnuItmHeight; mnu.subMnuOffset = (subMnuOffset==null)? 0:subMnuOffset; mnu.addItem = HTMLMenu._addItem; mnu.padding = (padding==null)? 3:padding; mnu._src=this; if(mnu.isRoot) { // swap width & height if horizontal var tmp = mnu.width; mnu.width=mnu.height; mnu.height = tmp; } this._menu[len]=[mnu]; this._menuLink[id] = len; return mnu; }; p.getInnerHTML = function(){ this.html = this._buildMenu(0); return this.html; }; // Write Style to browser HTMLComponent.writeStyle({ HCMNUItm: 'border: 1px solid #002851', HCMNUItmText: 'cursor: default; text-decoration: none; color: #FFFFFF; font: 12px Arial, Helvetica' });