JavaScript Example B-2
Dr. Clue's Pop-Up Cascading Menu System

Click Here for Previous JavaScript Tutorial Home Click Here for Next

Example code from Dr. Clue's JavaScript tutorial, for what he calls a "Windows-style" menu system, http://www.drclue.net/F1.cgi/HTML/JAVA/JAVA.html

This example is not very educational unless you're willing to pore over some details. It is, however, a good illustration of the power of JavaScript programming.

Sample Menu System

Just to reiterate: I did not not write this menu system, it is from Dr. Clue's JavaScript tutorials. I've included it here because it was one of the examples I studied in learning JavaScript. All credit belongs to Dr. Clue and I encourage the reader to follow the link to his web site.  -- Chip

Your ToolKit | Technology Centers

The HTML code for the two links above is as follows:

   <A HREF="MNUtoolkit.html" onClick="return menuPop(this);" 
            onMouseover="menuPop(this);" >Your ToolKit</A>
    | 
   <A HREF="MNUtech.html"  onClick="return menuPop(this);"
        onMouseover="menuPop(this);">Technology Centers</A>

Dr. Clue writes:

You'll notice that the HREF=MNUtoolkit.html has the filename portion MNUtoolkit expressed as variable in the menuitems defined below. It is this trick that allows an older or javascript disabled browser to fall through to another page provided for browsers with no javascript. It does not matter what the filenames are, as long as your variable names match the filenames.

Extensive customization of the menus is possible. See the Dr. Clue source page for details.

Loading JavaScript from a File

In this example all of the JavaScript is loaded from separate files. Here's how to do it:

<script type="text/javascript" language="javascript1.2" src="./menu.js">
</script>
<script type="text/javascript" language="javascript1.2" src="./menuitems.js">
</script>

I'm not sure why Dr.Clue chose to use the "./filename" form in the src= instead of just "filename". Perhaps it's to avoid having the browser search in different locations.

Sample Content of menuitems.js

The JavaScript code below, which in this example resides in a separate file, menuitems.js, is what defines the content and semantics of the menu system.

var MNUtoolkit  = new MenuList();
    MNUtoolkit.APPEND("Home Page"           ,"http://www.drclue.net");
    MNUtoolkit.APPEND("My Resume"           ,"@MNUresume");
    MNUtoolkit.APPEND("My Folders"          ,"@MNUfolders");
    MNUtoolkit.APPEND("My Profile"          ,"");
    MNUtoolkit.APPEND("Change Password"     ,"");


    var MNUresume   = new MenuList()
    MNUresume.APPEND("OnLine HTML version","http://www.drclue.net/F1.cgi/HTML/RESUME/RESUME.html");
    MNUresume.APPEND("Word Format Resume","http://www.drclue.net/HTML/RESUME/drclueresume.doc");
    MNUresume.APPEND("Text Format Resume","http://www.drclue.net/HTML/RESUME/drclueresume.txt");

    var MNUfolders  = new MenuList();
    MNUfolders.APPEND("Dr. Clue's web-site" ,"http://www.drclue.net");
    MNUfolders.APPEND("Ryans Folder"        ,"javascript:alert('hi');");
    MNUfolders.APPEND("NEC Research"        ,"@MNUnec");

    var MNUtech     = new MenuList();
    MNUtech.APPEND("Databases"              ,"");
    MNUtech.APPEND("Desktop Computing"      ,"");
    MNUtech.APPEND("E-Commerce"             ,"");
    MNUtech.APPEND("Enterprise Apps"        ,"");
    MNUtech.APPEND("Internet/Intranet"      ,"");
    MNUtech.APPEND("Mobile Computing"       ,"");
    MNUtech.APPEND("Networking"             ,"");
    MNUtech.APPEND("Storage"                ,"");


    var MNUnec      = new MenuList();
    MNUnec.APPEND("Review: Two unique color printers","");
    MNUnec.APPEND("What's wrong with MS-Exchange"   ,"");
    MNUnec.APPEND("TestDrive: Internet Explorer 5.0","");
    MNUnec.APPEND("Netscape Preps Metadirectory"    ,"");
    MNUnec.APPEND("No Laptop Lite Enough"           ,"");
    MNUnec.APPEND("The Last artical in this menu"   ,"");

The Menu Package

The JavaScript code which actually implements the menu system is loaded from menu.js. I haven't studied it yet, but here it is...

/*
Dr. Clue's drop-down menu system for 4th generation browsers
        copyright @ 1998,1999 drclue , www.drclue.net
license is granted for use of this software by individuals
in support of personal web-sites. All other rights reserved.
*/

//*** Global Variables
var LIBLOADEDJSmenu=false;
var     systemLibCnt    =0;
var     systemIsNS      =(document.layers!=null);       // Is it a Netscape browser
var     systemMouseDn   =false; // mousemove dragging
if(document.layers)document.all=document.layers;

var     systemMaxZ      =0; 
var     systemNullChk   =((systemIsNS)?((navigator.appVersion.substring(0,4)=="4.05")?"null":"undefined"):"null")
var menuTimeOut         =null;  // mouseout Cancel menu timer
var     menuCurrentItem =null;  // currently highlighted object.
var     menuCurrentPath ="";    // The open menu list.
var     menuScreenWidth =0;

//*** General Menu  configuration variables
var     menuSubAuto     =false;
var     menuSubSymbol   ="»";     // html to indicate sub menu
var     menuRoll        =true;  // Show menu items as built
var     menuCharHeight  =15;    // Avg Char Height.
var     menuCharWidth   =5;     // Avg Char Width.
var     menuYpopoff     =18;
var     menuXpopoff     =0;
var     menuBcolor      ="#9C9C9C";     // background
var     menuTcolor      ="#FFFFFF";     // Text
var     menuHBcolor     ="#003366";
var     menuHTcolor     ="#FFFF33";
var     menuFont        ="geneva, arial, helvetica";// menu label font
var     menuFontSize    =2;     // menu font size
var     menuBold        =false; // Use bold
var     menuAtimeout    =4500;
var     Firstpass       =true;
var     lastEVENT       =null;

var szDuds="Mozilla/4.0 (compatible; MSIE 4.5; Mac_PowerPC)";

function PreLoads(treeList)
        {
        window.status="["+systemLibCnt+"] menu.js["+LIBLOADEDJSmenu + "] items ["+""+" Loading ...";
        if(!LIBLOADEDJSmenu)
          {  setTimeout("PreLoads('"+treeList+"')",500);return;   }
        window.onResize="document.location.href=document.location.href";        
        if(!document.links.length)
          {  setTimeout("PreLoads('"+treeList+"')",500);return;   }
        window.status="initializing";
        while(treeList.length>1)
             {          
             killboy =treeList.substring(1);
             killboy =killboy.substring(0,killboy.indexOf(":"));
             treeList=treeList.substring(killboy.length+1);
             window.status="Loading "+killboy;
             menuCREATE(killboy,0,0);
             }
        window.status="";
        }

/* Called by the jsLAYERclass to create
a layer if the layer does not already exist.*/

function jsLAYERcreateLayer(Homeboy,x,y,w,h,bColor)
        {
        if(systemIsNS)
          {
          var lyr= document.layers[Homeboy.lyrName] = new Layer(w)
          lyr.left=x;lyr.top=y; lyr.clip.height=h+1;lyr.clip.width=w+1;
          lyr.bgColor=((jsLAYERcreateLayer.arguments.length>5)?bColor:menuBcolor);
          lyr.visibility='hidden';lyr.zIndex=1;
          lyr.isHighlight=false;
          lyr.border=1;
          document.layers[Homeboy.lyrName].style=document.layers[Homeboy.lyrName];
          }else{
          var str = '\n<DIV id='+Homeboy.lyrName+' style="visibility: hidden; position:absolute; left:'+x+'; top:'+y+'; width:'+w
          str += '; height:'+(h+1)+'px; clip:rect(0px '+(w+1)+'px '+(h+1)+'px 0px)'
          str += '; background-color:'+((jsLAYERcreateLayer.arguments.length>5)?bColor:menuBcolor)+';z-Index:5;"> </DIV>';
          document.body.insertAdjacentHTML("BeforeEnd",str);
          }
        Homeboy.jsLAYERobject=document.all[Homeboy.lyrName];
        if(systemIsNS)
          {
          Homeboy.jsLAYERdocument  =document.layers[Homeboy.lyrName].document;
          Homeboy.style            =document.layers[Homeboy.lyrName];
          }else{
          Homeboy.jsLAYERdocument  =document.all[Homeboy.lyrName];
          Homeboy.style            =document.all[Homeboy.lyrName].style;
          Homeboy.style.zIndex     =systemMaxZ++;
          }
        Homeboy.jsLAYERobject.HomeBoy=Homeboy;
        Homeboy.jsLAYERobject.W =w;
        Homeboy.jsLAYERobject.X =x;
        Homeboy.jsLAYERobject.Y =y;
        Homeboy.jsLAYERobject.H =h;
        Homeboy.jsLAYERobject.MOUSEHANDLER="MOUSEVECTOR";
        return Homeboy;
        }
function jsLAYERsetHandler(Homeboy,szHANDLER) // named function for events
        {
        Homeboy.jsLAYERobject.MOUSEHANDLER=szHANDLER;
        MOUSECAPTURE(Homeboy,Homeboy.lyrName);
        }
function jsLAYERhomeboy(layername){return document.all[layername].HomeBoy;}
function jsLAYERopen(Homeboy){if(systemIsNS){Homeboy.jsLAYERobject.document.open();  }else{  Homeboy.jsLAYERobject.innerHTML="";}}
function jsLAYERwrite(Homeboy,Text){if(systemIsNS){Homeboy.jsLAYERdocument.write(Text);}else{Homeboy.jsLAYERobject.innerHTML+=Text;}}
function jsLAYERclose(Homeboy)
        {
        if(systemIsNS)
          {
          Homeboy.jsLAYERdocument.close();
          MOUSECAPTURE(Homeboy,Homeboy.lyrName);
          }
        }
function jsLAYERsetContent(Homeboy,text)
        {
        jsLAYERopen(Homeboy);
        jsLAYERwrite(Homeboy,text);
        jsLAYERclose(Homeboy);return;
        }
function jsLAYERshow(Homeboy,vis){Homeboy.style.visibility=((vis)?"visible":"hidden");}
function jsLAYERgetX(Homeboy){return parseInt(Homeboy.style.left);}
function jsLAYERgetY(Homeboy){return parseInt(Homeboy.style.top);}
function jsLAYERxy(Homeboy,x,y,InLayer)
        {
        this.InX=x;this.InY=y;
        if(document.layers)
          {
          if(InLayer)
            {
            InX+=InLayer.style.left;
            InY+=InLayer.style.top;
            }
          Homeboy.jsLAYERobject.x=this.InX;
          Homeboy.jsLAYERobject.y=this.InY;
          }else{
          if(InLayer)
            {
            this.InX+=parseInt(document.all[Homeboy.lyrName].style.left);
            this.InY+=parseInt(document.all[Homeboy.lyrName].style.top);
            }
//alert(document.all[Homeboy.lyrName].style.left+"[]"+this.InX+"[]"+x)
          document.all[Homeboy.lyrName].style.left=this.InX
          document.all[Homeboy.lyrName].style.top=this.InY
          }
        }

/*Function      :MEVENT
**Parameters    :Homeboy        - Layer Class Pointer
**               Evt            - javascript Browser Event
**Description   :Noramalizes Netscape/MSIE evnts to 
**a class containing variables for both, with Netscape names
**superceding MSIE names. It is this psudeo event class that
**is passed to all MOUSE... event handler functions.
*/
function MEVENT(Homeboy,Evt) //normalizes the differences in NS and MSIE events
        {
        this.type=Evt.type;
        this.screenX=Evt.screenX;
        this.screenY=Evt.screenY;
        if(systemIsNS)
          {
        this.pageX=Evt.pageX;
        this.pageY=Evt.pageY;
        this.locationX=Homeboy.jsLAYERobject.x;
        this.locationY=Homeboy.jsLAYERobject.y;
        this.layerX=Evt.layerX;
        this.layerY=Evt.layerY;
        this.which=Evt.which;
        this.target=Evt.target;
        this.modifiers=Evt.modifiers;
          }else{
        this.pageX=Evt.x;
        this.pageY=Evt.y;
	if(document.body.scrollTop)this.pageY+=document.body.scrollTop;
        this.locationX=parseInt(Homeboy.jsLAYERobject.style.left);
        this.locationY=parseInt(Homeboy.jsLAYERobject.style.top);
        this.layerX=this.pageX-this.locationX;
        this.layerY=this.pageY-this.locationY;
        this.which=Evt.button+1;
        this.target=Evt.srcElement;
        this.modifiers=(((Evt.altKey)?1:0)+((Evt.ctrlKey)?2:0)+((Evt.AltKey)?4:0));
          }
        }
function MOUSEVECTOR(layername,Evt)// handles the actuall prep and call of mouse events
        {
        Homeboy=document.all[layername].HomeBoy;return false;
        }
// Sets up mouse event NOTE: Use of "new Function" is important
function MOUSECAPTURE(Homeboy,layername)
        {
var NFD="return "+Homeboy.jsLAYERobject.MOUSEHANDLER+"('"+layername+"',"+((systemIsNS)?"arguments[0]":"window.event")+")"
Homeboy.jsLAYERobject.onmouseover=new Function(NFD)
Homeboy.jsLAYERobject.onmouseout=new Function(NFD)
Homeboy.jsLAYERdocument.onmousemove=new Function(NFD)
Homeboy.jsLAYERdocument.onmousedown=new Function(NFD)
Homeboy.jsLAYERdocument.onmouseup=new Function(NFD)
if(systemIsNS)Homeboy.jsLAYERdocument.captureEvents(  Event.MOUSEUP |   Event.MOUSEDOWN   | Event.MOUSEMOVE);
        }
function NSResizePatch(){document.location.href=document.location.href;}
function jsNULLvector(layername,Evt){return true;}
var MPTYPE ="",MSTYPE ="";
function jsMPANELvector(panelName,Evt)  // Vectors mouse messages for the panel
        {
        Homeboy=jsLAYERhomeboy(panelName);
        if(menuTimeOut)clearTimeout(menuTimeOut);
        if(Evt.type=="mouseout" || Evt.type=="mouseover") 
          {
          MPTYPE=Evt.type;
          if(MPTYPE==MSTYPE&&MPTYPE=="mouseout")menuTimeOut=setTimeout("menuPOPDN()",100);
          }
        if(Evt.type!="mousemove" )return false;
        EVENT=new MEVENT(Homeboy,Evt);

        EntryNum=0;
        EntryNotch=EVENT.layerY;
        if(EntryNotch)
          {
          EntryNotch-=(EntryNotch%(menuCharHeight+1));
          EntryNum=(EntryNotch/(menuCharHeight+1))
          }
        if(Homeboy.mParent.Items.length<=EntryNum)return true;
        lastEVENT=EVENT;
        if(Homeboy.mParent.EntryNum==EntryNum)return false;

//if(!systemIsNS)
//{
//alert(EntryNum+"[]"+EntryNotch+"[]"+EVENT.layerY)
//Homeboy.mParent.Items[EntryNum].RENDER)
//}
        jsLAYERsetContent(Homeboy.mParent.mSELECT,Homeboy.mParent.Items[EntryNum].RENDER);

        jsLAYERxy(Homeboy.mParent.mSELECT,jsLAYERgetX(Homeboy),jsLAYERgetY(Homeboy)+(EntryNum*(menuCharHeight+1)));
        Homeboy.mParent.EntryNum=EntryNum;
        if(!menuSubAuto)return false;
        if(Homeboy.mParent.Items[EntryNum].ACTION.substring(0,1)=="@")
          {
          fakeEvt = new Object();
          fakeEvt.type="mouseup";
          jsMSELECTvector(Homeboy.mParent.mSELECT.lyrName,fakeEvt);
          }
        return false;
        }
/*
** Vectors mouse messages for the menu selector
*/
function jsMSELECTvector(panelName,Evt)
        {
        if(menuTimeOut)clearTimeout(menuTimeOut);
        if(Evt.type=="mouseout" || Evt.type=="mouseover") 
          {
          MSTYPE=Evt.type;
          if(MPTYPE==MSTYPE&&MPTYPE=="mouseout")menuTimeOut=setTimeout("menuPOPDN()",100);
          Homeboy=jsLAYERhomeboy(panelName);
          return false;
          }
        if(Evt.type!="mouseup")return false;
        Homeboy=jsLAYERhomeboy(panelName);
        var action = Homeboy.mParent.Items[Homeboy.mParent.EntryNum].ACTION;

        if(menuCurrentPath.indexOf(Homeboy.jsLAYERobject.GROUP)>0)
          {
          var FindGroup = ":"+Homeboy.jsLAYERobject.GROUP+":";
          var killList = menuCurrentPath.substring(menuCurrentPath.indexOf(FindGroup)+FindGroup.length-1);
          menuPOPDN(killList);
          }
        if(action.length<1){window.status="[Not Available]";return false;}
        var isMenu = action.substring(0,1)=="@";
        var isJavascript = action.substring(0,1)=="!";
        if(isJavascript)
          {
          eval(action.substring(1))
          return false;
          }
        if(isMenu)
          {
          menuPOPUP(jsLAYERgetX(Homeboy)+Homeboy.jsLAYERobject.W+2,jsLAYERgetY(Homeboy),action.substring(1));
          }else{
          document.location.href=action;
          }
        return false;
        }
/*
** This is the menu panel
*/
function jsMPANELclass(group,entry,label,action,x,y,w,h)
        {
        this.lyrName            =group+entry;
        if(!document.all[this.lyrName])jsLAYERcreateLayer(this,x,y,w,h,"#000000");
        jsLAYERsetHandler(this,"jsMPANELvector");
        this.jsLAYERobject.GROUP=group;this.jsLAYERobject.ENTRY=entry;
        this.jsLAYERobject.rtWidth=10;
        this.jsLAYERobject.rtSymbol="»";
        }
/*
** This is the highlite bar
*/
function jsMSELECTclass(group,entry,label,action,x,y,w,h)
        {
        this.lyrName            =group+entry;
        if(!document.all[this.lyrName])jsLAYERcreateLayer(this,x,y,w,h);
        jsLAYERsetHandler(this,"jsMSELECTvector");
        this.jsLAYERobject.GROUP=group;
        this.jsLAYERobject.ENTRY=entry;
        this.jsLAYERobject.rtWidth=10;
        this.jsLAYERobject.rtSymbol="»";
        }
/*
** Create the menu label obeject string for display
*/
function menuLABEL(Homeboy,text,isHighlight,isSub)
        {
        var fontstart="<FONT FACE='"+menuFont+"' SIZE="+menuFontSize+" COLOR='"+((isHighlight)?menuHTcolor:menuTcolor)+"'>"+((menuBold)?"<B>":"");
        var CONTENT=" ";
        if(text)CONTENT=text.length?" "+text:" ";
        var lyrtxt="<TABLE BORDER=0 CELLPADDING=0 STYLE='cursor:hand' CELLSPACING='0' BGCOLOR='";
        lyrtxt+=((isHighlight)?menuHBcolor:menuBcolor);
        lyrtxt+="' WIDTH='"+Homeboy.jsLAYERobject.W+"' HEIGHT='"+menuCharHeight+"'><TR VALIGN=MIDDLE>";
        twidth=parseInt(Homeboy.jsLAYERobject.W)-parseInt(Homeboy.jsLAYERobject.rtWidth);
        lyrtxt+="<TD WIDTH='"+twidth.toString();
        lyrtxt+="'>"+fontstart+CONTENT+((menuBold)?"</B>":"")+"</FONT></TD>";
        lyrtxt+="<TD WIDTH='10'>"+fontstart+((isSub)?menuSubSymbol:" ")+((menuBold)?"</B>":"")+"</FONT></TD></TR></TABLE>";
        return lyrtxt;
        }
function MenuItem(label,action)
        {
        this.LABEL      =label  ;
        this.ACTION     =action ;
        this.SUB        =this.ACTION.substring(0,1)=="@";
        this.RENDER     =""     ;
        }
function MenuListAPPEND(label,action)   //Appends an item to the menuobject
        {
        this.Items[this.Items.length]=new MenuItem(label,action);
        if(label.length>this.greatestCharWidth)this.greatestCharWidth=label.length;
        }
function menuPop(tobj) //Pops up menu relative to <A> tag location on screen.
        {
        objectName=tobj.href.substring(tobj.href.lastIndexOf("/")+1);
        if(objectName.indexOf(".html")>-1)objectName=objectName.substring(0,objectName.indexOf("."))
//      if(!menuCurrentPath)return;
        if(menuCurrentPath.indexOf(":"+objectName+":")==0)return false;
        if(menuCurrentPath.length>0)menuPOPDN();
if(szDuds.indexOf(navigator.userAgent)>-1)
{
if(tobj.href.indexOf(".html")==-1)tobj.href+=".html";
return true;
}

        if(navigator.appVersion.indexOf("MSIE")>-1&&navigator.appVersion.indexOf("Mac")>-1)
          {// compatible mac
          if(tobj.href.indexOf(".html")==-1)tobj.href+=".html";
          return true;
          }

        this.MX=((systemIsNS)?(tobj.x):window.event.clientX-window.event.offsetX+tobj.offsetLeft);
        this.MY=((systemIsNS)?(tobj.y):window.event.clientY-window.event.offsetY+tobj.offsetTop);
        if(!systemIsNS)MSIEmeasure(tobj,this);    
        this.MY+=menuYpopoff;
        this.MX+=menuXpopoff;
        menuPOPUP(this.MX,this.MY,objectName);
        menuTimeOut=setTimeout("menuPOPDN()",menuAtimeout);
        return false;
        }
function menuPOPUP(x,y,menulist)        //*** Opens named menu at given location
        {
        var DL=eval(menulist);
        if(!DL){alert("menuPOPUP NULL "+menulist);return;}
        menuSHOW(menulist,x,y);
        if(!menuScreenWidth)
          menuScreenWidth=(systemIsNS)?document.width:document.body.offsetWidth;
        mkw=(DL.greatestCharWidth*menuCharWidth)+10;
        var atX = ((x+mkw+20)>=menuScreenWidth)?x-mkw:x;
        if(jsLAYERgetX(DL.mPANEL)!=atX)menuXY(DL,atX,y);
        }
function menuCREATE(szMlist,iLeft,iTop)
        {
        Left= 20;Top = 40;
        if(menuCREATE.arguments.length>1)Left=iLeft;
        if(menuCREATE.arguments.length>2)Top=iTop;
        Mlist=eval(szMlist);
        if(Mlist.mPANEL ==null)
          {
          Mlist.mPANEL=new jsMPANELclass(szMlist,0,"Hello","alert('hi')",Left,Top,((Mlist.greatestCharWidth+10)*menuCharWidth)+1,((menuCharHeight+1)*Mlist.Items.length)+1);
          Mlist.mPANEL.mParent=Mlist;
          var menuContent='';
          menuContent='<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD>';
          for(x=0;x<Mlist.Items.length;x++)
           {
           menuContent+=menuLABEL(Mlist.mPANEL,Mlist.Items[x].LABEL,false,Mlist.Items[x].SUB);
           Mlist.Items[x].RENDER=menuLABEL(Mlist.mPANEL,Mlist.Items[x].LABEL,true,Mlist.Items[x].SUB);
           }
        menuContent+='</TD><TD BGCOLOR="#000000"> </TD>';
        menuContent+="</TR><TR><TD COLSPAN=2> </TD></TR></TABLE>";
//alert(menuContent);
          jsLAYERsetContent(Mlist.mPANEL,menuContent);
          }
        if(Mlist.mSELECT==null)
          {
          Mlist.mSELECT=new jsMSELECTclass(szMlist,1,"Hello","alert('hi')",Left,Top,(Mlist.greatestCharWidth+10)*menuCharWidth,menuCharHeight);
          Mlist.mSELECT.mParent=Mlist;
          jsLAYERsetContent(Mlist.mSELECT,Mlist.Items[0].RENDER);
          }
        }

function menuSHOW(szMlist,iLeft,iTop)   // SHOW the menu
        {
        Left= 20;Top = 40;
        if(menuSHOW.arguments.length>1)Left=iLeft;
        if(menuSHOW.arguments.length>2)Top=iTop;
        Mlist=eval(szMlist);
        if(Mlist.mPANEL==null)menuCREATE(szMlist,iLeft,iTop);
        if(jsLAYERgetX(Mlist.mPANEL)!=Left || jsLAYERgetY(Mlist.mPANEL)!=Top)
            {
            jsLAYERxy(Mlist.mPANEL,Left,Top)   
            jsLAYERxy(Mlist.mSELECT,Left,Top+(Mlist.EntryNum*(menuCharHeight+1)));
            }; 
        if(menuCurrentPath.indexOf(":"+szMlist+":")<0)menuCurrentPath+=((menuCurrentPath.length)?"":":")+szMlist+":";

        if(Mlist.mPANEL.style.clip&&!systemIsNS)
          {
          Clips= Mlist.mPANEL.style.clip.split("rect(")[1].split(")")[0].split("px")
          Clips[2]=Mlist.Items.length * (menuCharHeight+1);
          Mlist.mPANEL.style.clip = "rect("+Array(0,Clips[1],Clips[2],0).join("px ")+"px)";
          Mlist.mPANEL.style.zIndex=5;
          Mlist.mSELECT.style.zIndex=6;
          }
        Mlist.mPANEL.style.visiblity='visible';
//alert(Mlist.Items.length +" Item(s) "+ Mlist.mPANEL.style.clip);
        jsLAYERshow(Mlist.mPANEL,true);
        jsLAYERshow(Mlist.mSELECT,true);
        }
function menuHIDE(szMlist)      //  Hides the named menu
        {
        Mlist=eval(szMlist);
        jsLAYERshow(Mlist.mSELECT,false);
        jsLAYERshow(Mlist.mPANEL,false);
        }
function menuXY(Mlist,x,y)      // Moves the referenced menu
        {
        jsLAYERxy(Mlist.mPANEL,x,y)
        jsLAYERxy(Mlist.mSELECT,x,y+(Mlist.EntryNum*(menuCharHeight+1)));
        }
function menuPOPDN(treeList)    // closes a list of menus
        {
        if(menuTimeOut)clearTimeout(menuTimeOut);
        if(menuPOPDN.arguments.length<1)treeList=menuCurrentPath;
        while(treeList.length>1)
             {          
             killboy =treeList.substring(1);
             killboy =killboy.substring(0,killboy.indexOf(":"));
             treeList=treeList.substring(killboy.length+1);
             menuHIDE(killboy);
             }
        if(menuPOPDN.arguments.length<1)menuCurrentPath="";
        };
/*
** MAIN MENU OBJECT
*/
var mSELECT=null;
function MenuList(Mlist)
        {
        this.mPANEL=null;this.mSELECT=null;
        this.Items=new Array();this.EntryNum=0;
        this.APPEND=MenuListAPPEND;
        this.greatestCharWidth=0;
        }

/*      Function        :MSIEmeasure
**      Since I have found no straight forward method of obtaining IE x,y
**      coords for the clicked link, this function recurses up the object tree
**      to measure the screen location of the <A> involved
*/
function MSIEmeasure(btobj,HB)
        {
        var tobj=btobj;
        HB.MX=tobj.offsetLeft;
        HB.MY=tobj.offsetTop;
        while(tobj.parentElement)
          {
          if(!tobj.parentElement)break;
          tobj = tobj.parentElement;
//        if(tobj.tagName=="TABLE")
          if(String(":TABLE:TD:DIV:").indexOf(":"+tobj.tagName+":")>-1)
            {
            HB.MX+=tobj.offsetLeft;
            HB.MY+=tobj.offsetTop;
            }
          if(!tobj.parentElement)break;
          if(tobj.parentElement.tagName=="BODY")break;
          }
        return ;
        }
/****************************************
** A message window                     *
*****************************************/
var StatusMsgWin=null;
function jsMESSAGEclass(group,entry,x,y,w,h)
        {
        this.lyrName            =group+entry;
        if(!document.all[this.lyrName])jsLAYERcreateLayer(this,x,y,w,h,"#FFFFCC");
        jsLAYERsetHandler(this,"jsNULLvector");
        jsLAYERshow(this,true);
        this.jsLAYERobject.GROUP=group;this.jsLAYERobject.ENTRY=entry;
        }
/*
** Set the contents of the message window;
*/
function jsStatusMsg(txtMESSAGE)
        {
        if(!StatusMsgWin)
          {
          StatusMsgWin= new jsMESSAGEclass("E",1,1,1,355,100);
          jsLAYERshow(StatusMsgWin,true);
          }
        jsLAYERsetContent(StatusMsgWin,txtMESSAGE);
        }
var LIBLOADEDJSmenu=true;
//systemLibCnt++; 
 
Click Here for Previous JavaScript Tutorial Home Click Here for Next