You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
362 lines
13 KiB
362 lines
13 KiB
2 years ago
|
/*
|
||
|
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 += '<div id="' + itemID + '" onclick="return '+this+'._e(\'click\','+currMenu+','+currItem+')" style="position: absolute; left: ' + itemX + 'px; top: ' + itemY + 'px; width: ' + w + 'px; height: ' + h + 'px; visibility: inherit; ';
|
||
|
if (backCol) str += 'background: ' + backCol + '; ';
|
||
|
str += '" ';
|
||
|
}else if (dynapi.ua.ns4) {
|
||
|
str += '<layer id="' + itemID + '" left="' + itemX + '" top="' + itemY + '" width="' + w + '" height="' + h + '" visibility="inherit" ';
|
||
|
if (backCol) str += 'bgcolor="' + backCol + '" ';
|
||
|
}
|
||
|
if (cssName) str += 'class="' + cssName + '" ';
|
||
|
|
||
|
// Add mouseover handlers and finish div/layer.
|
||
|
str += 'onmouseover="'+this+'._e(\'mouseover\',' + currMenu + ',' + currItem + ')" onmouseout="'+this+'._e(\'mouseout\',' + currMenu + ',' + currItem + ')">';
|
||
|
|
||
|
// Setup menu image
|
||
|
var imgParams
|
||
|
if(!image) mnuImage ='';
|
||
|
else {
|
||
|
imgParams = image.params;
|
||
|
mnuImgAlg = (imgParams && imgParams.align)? imgParams.align:'absmiddle';
|
||
|
mnuImage = '<img name="'+this.id+id+'" src="'+image.src+'" width="'+image.w+'" height="'+image.h+'" border="0" align="'+mnuImgAlg+'">'
|
||
|
}
|
||
|
|
||
|
// 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+'<br>'+text;
|
||
|
if(dir=='S') text = text+'<br>'+mnuImage;
|
||
|
else text = mnuImage+text;
|
||
|
|
||
|
// In IE/NS6+, add padding if there's a border to emulate NS4's layer padding.
|
||
|
str += '<table width="' + (w - 8) + '" border="0" cellspacing="0" cellpadding="' + ((!dynapi.ua.ns4 && cssName)? mnu[0].padding : 0) + '"><tr><td align="left" height="' + (h - 7) + '" class="' + cssTextName + '">'
|
||
|
+ (contMode? text:'<a class="' + cssTextName + '" href="javascript:;" onclick="'+((!dynapi.ua.ns4)? 'this.blur(); return false;':'return '+this+'._e(\'click\','+currMenu+','+currItem+');')+'">' + text + '</a>')
|
||
|
+'</td>';
|
||
|
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 += '<td class="' + cssTextName + '" align="right">'+this.mnuArrow+'</td>';
|
||
|
}
|
||
|
str += '</tr></table>' + (dynapi.ua.ns4 ? '</layer>' : '</div>');
|
||
|
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 = '<ilayer id="'+id+'" visibility="inherit" height="'+(h+3)+'">'+str+'</ilayer>';
|
||
|
else str = '<div id="'+id+'" style="position:relative; visibility: inherit; height:'+(h+mnu[0].padding)+'px;">'+str+'</div>';
|
||
|
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', '<div id="' + id + '" style="position: absolute; top: -100px; visibility: hidden; z-index:10000">' + str + '</div>');
|
||
|
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('<div id="' + id + '" style="position: absolute; top: -100px; visibility: hidden; z-index:10000">' + str + '</div>');
|
||
|
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'
|
||
|
});
|