Wait ...
Before we move any further, examine the sample, which this article discusses, by grabbing the code above. Note that the article text refers to the original IE-only code. The updated source code works for Netscape 6+ as well as IE.
About Menus
Using JavaScript or VBScript we can produce some very cool user interface (UI) items like menus. The
DIV
element is useful when creating menus in that it can simulate the effect of pull-down and/or pop-up menus. However there is a compatibility problem with Netscape Navigator, DIV elements do not produce the same effects as Internet Explorer. The solution is to use the Netscape equivalent elements of
LAYER
,
ILAYER
and the like when developing for the Netscape browser. This article only discusses the idea of how to create menus for Internet Explorer, for Netscape Navigator however the logic remains the same with only minor changes.
Create A Menu
Each menu consists of menu items. Each menu is a
DIV
element that can contain other
DIV
elements (the menu items). In the example each menu item that you see as well as the separator bar is a
DIV
element with a style applied. How the menu/menu item appears to the user depends on what style attributes are set for each
DIV
element. Possible style attributes that could be used for menus are background color, borders, text color, etc.
DIV
elements also support events like
mouseover
and
mouseout
, this enables the menu/menu items to react to the user. Contained
DIV
elements inherit the style of their parents, i.e. if the parent is invisible so are the children. Now does all that ring any bells? In the following sections we will see this put to work, starting with the
CreateMenu
function.
In The Code
hColor
= highlight color, the color of a menu item when it is in a highlighted state.
dColor
= default color, the normal color of a menu item.
bColor
= background color, color of the parent DIV
element that contains menu items, this is also the color of separators.
menuArr
= global two dimensional array that contains the data for the menus.
titles
= global two dimensional array that contains the text to display for each top level menu and the number of menu items under each menu.
function show(obj)
{
obj.style.visibility = 'visible';
}
function hide(obj)
{
obj.style.visibility = 'hidden';
}
function CreateMenu(rowid,x,y,width,height,hColor,dColor,bColor,items,align,
border)
{
if(!items)
{
return;
}
var divHTML ;
var menuBar;
menuBar ="<DIV id=\"main_div_" + rowid + "\" align=\""+align+"\" ";
menuBar += " style=\" position:absolute; CURSOR:hand; top:" + y +
"px; left:" + x + "px; width:" + width + "px; ";
menuBar += " height:" + height + "px; visibility:visible; " +
"background-color:" + dColor + ";\" ";
menuBar += " onmouseover=\"show(document.all[\'div_"+ rowid +
"\']);\" onmouseout=\"hide(document.all[\'div_"+ rowid +
"\']);\">";
menuBar += titles[rowid][0] + " </DIV>";
document.write (menuBar);
y += document.all["main_div_" + rowid ].offsetHeight;
divHTML = "<DIV id=\"div_"+rowid+"\"" ;
divHTML += "style=\"position:absolute; top:" + y + "px; left:" + x +
"px; width:" + width + "px; visibility:hidden; ";
divHTML += " padding-left:" + border + "; background-color:" + bColor +
";\" ";
divHTML += "onmouseover=\"show(this);\" onmouseout=\"hide(this);\" >\n";
divHTML += CreateSeparatorBar(bColor,width-(border*2),border);
for (i=0;i<items;i++)
{
divHTML += CreateMenuBar('div_'+rowid,rowid,i,width-(border*2),
height,hColor,dColor,align);
divHTML += CreateSeparatorBar(bColor,width-(border*2),border);
}
divHTML += "</DIV>";
document.write(divHTML);
}
By now you must have an idea of what to expect in
CreateMenuBar
and
CreateSeparatorBar
. There is one important thing to note here, the use of an
IMG
tag in the
CreateSeparatorBar
ensures that the size of the separator is equal to the border (There is no other way to do it that I know...).
OnMouseOverBar
,
OnMouseOutOfBar
and
onmenuclick
are simple handlers for mouse events.
function OnMouseOverBar(obj,rowid,colid,color)
{
obj.style.backgroundColor = color;
window.status = menuArr[rowid][colid][2];
}
function OnMouseOutOfBar(obj,rowid,colid,color)
{
obj.style.backgroundColor = color;
window.status = "";
}
function onmenuclick(obj,code)
{
hide(obj);
eval(code);
}
function CreateSeparatorBar(dColor,width,border)
{
var sepHTML;
sepHTML = "<DIV id=\"line_separator\" style=\"position:relative; " +
"height:1px;" +
" background-color:"+dColor+";\" >";
sepHTML += "<img src=\"\" width=" + width + " height="+
border/2+"></DIV> \n";
return sepHTML;
}
function CreateMenuBar(parent,rowid,colid,width,height,hColor,dColor,align)
{
var subMenuHTML;
subMenuHTML = "\n<DIV align="+align+" id=\"div_"+rowid +
"_"+colid+"\" style=\"position:relative; CURSOR:hand; ";
subMenuHTML += " width:"+width+"px; background-color:"+dColor+";\" ";
subMenuHTML += " onmouseover=\"OnMouseOverBar(this,"+rowid+","+
colid+",\'"+ hColor+"\');\" ";
subMenuHTML += " onclick=\"onmenuclick(document.all[\'"+parent+"\'],\'" +
menuArr[rowid][colid][1] + "\');\" ";
subMenuHTML += " onmouseout=\"OnMouseOutOfBar(this,"+rowid+","+colid+
",\'"+dColor+"\');\" >";
subMenuHTML += menuArr[rowid][colid][0];
subMenuHTML += " </DIV> \n";
return subMenuHTML;
}
Displaying the menu.
All that is left to display the menu is to provide data for the menu. This is done using a two dimensional array. For simplicity these variables have been kept global.
var menuArr;
var titles;
function Initialize(rows,cols)
{
menuArr = new Array();
titles = new Array();
for(i=0; i< rows; i++)
{
titles[i] = new Array(2)
titles[i][0] = "";
titles[i][1] = 0;
}
for (i= 0;i < rows; i++)
{
menuArr[i] = new Array(cols)
for (j= 0;j < cols; j++)
{
menuArr[i][j] = new Array(3)
for (k=0; k < 3 ; k++)
menuArr [i][j][k] = "";
status window.
}
}
}
Initialize(1,4);
titles[0][0] = "File";
titles[0][1] = 4;
menuArr[0][0][0]="New";
menuArr[0][0][1]="window.navigate(\\\'cool.html\\\');"
menuArr[0][0][2]="open a new file.";
menuArr[0][1][0]="Save";
menuArr[0][1][1]="alert(\\\'save this document\\\');";
menuArr[0][1][2]="save this document.";
menuArr[0][2][0]="Exit"
menuArr[0][2][1]="window.close();";
menuArr[0][2][2]="see you later.";
menuArr[0][3][0]="mail me...";
menuArr[0][3][1]="window.navigate(\\\'mailto:alleey@usa.net\\\');";
menuArr[0][3][2]="alleey@usa.net";
for(i=0;i < 4; i++)
{
CreateMenu(i,i*150,0,150,15,'#000099','#999999','#c0c0c0',
titles[i][1],'center',4);
}
If there are no errors, this should produce a menu on the page. The code can also be used to create pop-up menus. To add this functionality, a way to position the menu inside the browser window where the mouse click has occurred is need. The window
object has an event
object that holds information about the last event occurred. For a mouse event, window.event
holds the x and y coordinates where the event occurred along with the button state and other useful information.
function TrackPopUp(obj)
{
if(typeof(obj) == "undefined")
return;
var winWidth = document.body.clientWidth;
var winHeight = document.body.clientHeight;
x = winWidth - (obj.offsetWidth + window.event.x);
y = winHeight - (obj.offsetHeight + window.event.y);
obj.style.left = x<0 ? window.event.x + x : window.event.x ;
obj.style.top = y<0 ? window.event.y + y : window.event.y;
show(obj);
return false;
}
<SCRIPT LANGUAGE="javascript" FOR=document EVENT=oncontextmenu>
<!--
return TrackPopUp(document.all['div_0']);
</SCRIPT>
If we do not return false from
TrackPopUp
the default IE menu will appear at the same time as our popup menu.
Final words.
This is fairly cool way to provide navigation in HTML pages. Here I am displaying just one menu. Depending on your situation, you can write code to change the menu that is displayed. By doing some extra work, self-modifying menus can be incorporated. There are so many cool things you can do with this, it is all up to you.
History
The original article by Shoaib Ali's was for MS IE only. This update by JavasOK tweaks the original slightly to extend its use to Netscape/Mozilla. In addition a new function has been added to support attaching the original popup menu to a table cell.