Nesse artigo vou mostrar como construir um menu no Javascript, com tabelas, divs e css. Para construir um menu precisamos utilizar recursividade, cada nó pode ter nós irmãos e nós filhos.
Abaixo a figura do modelo de classes.
Figura 1. Modelagem das Classes
Classe Menu.
id: Identificador do objeto
height: Altura do menu.
width: Largura do menu.
Classe ItemMenu.
id: Identificador do objeto
text: Texto do item.
value: Valor do item.
image: URL da imagem.
isSeparator: Indica se o item é objeto separador.
isOpen: Indica se o menu de filhos está aberto.
elementMenuDiv: Objeto que o item está dentro.
Listagem 1: Construtores.
function Menu(id, height, width) {
this.id = id;
this.height = height;
this.width = width;
this.items = [];
}
function ItemMenu(id, text, value, image, isSeparator) {
this.id = id;
this.text = text;
this.value = value;
this.image = image;
this.isSeparator = isSeparator;
this.items = [];
this.isOpen;
this.elementMenuDiv;
this.onClick;
}
Agora vamos criar os métodos que serão chamados quando os eventos OnMouseOver, OnMouseOut e OnClick forem disparados.
Menu.prototype.itemMenu_OnMouseOver: Quando o mouse passa sobre o objeto.
Menu.prototype.itemMenu_OnMouseOut: Quando o mouse deixa de estar em cima do objeto.
Menu.prototype.itemMenu_OnClick: Evento que abre e fecha o menu filho.
Listagem 2: Eventos.
Menu.prototype.itemMenu_OnMouseOver = function (element) {
element.style.backgroundColor = "#FFE6A0";
};
Menu.prototype.itemMenu_OnMouseOut = function (element) {
element.style.backgroundColor = "";
};
Menu.prototype.itemMenu_OnClick = function (element) {
var index = parseInt(element.attributes['indexItemMenu'].value);
var oItemMenu = this.items[index];
for (var row = 0; row < this.items.length; row++) {
if (oItemMenu.id != this.items[row].id) {
this.items[row].hideItens(this.items[row]);
}
}
if (oItemMenu.elementMenuDiv != null) {
if (oItemMenu.isOpen == null || oItemMenu.isOpen == false) {
oItemMenu.isOpen = true;
oItemMenu.elementMenuDiv.style.display = 'block';
oItemMenu.elementMenuDiv.style.top = element.offsetTop + parseInt(this.height) + 1;
oItemMenu.elementMenuDiv.style.left = element.offsetLeft;
}
else {
oItemMenu.hideItens(oItemMenu);
}
}
};
ItemMenu.prototype.itemMenu_OnMouseOver = function (element) {
element.style.backgroundColor = "#FFE6A0";
};
ItemMenu.prototype.itemMenu_OnMouseOut = function (element) {
element.style.backgroundColor = "";
};
ItemMenu.prototype.itemMenu_OnClick = function (element) {
var index = parseInt(element.attributes['indexItemMenu'].value);
var oItemMenu = this.items[index];
if (oItemMenu.elementMenuDiv != null) {
if (oItemMenu.isOpen == null || oItemMenu.isOpen == false) {
oItemMenu.isOpen = true;
oItemMenu.elementMenuDiv.style.display = 'block';
oItemMenu.elementMenuDiv.style.top = element.offsetTop + element.parentNode.parentNode.parentNode.parentNode.offsetTop;
oItemMenu.elementMenuDiv.style.left = element.offsetLeft + parseInt(widthListComponentMenu) + 1 + element.parentNode.parentNode.parentNode.parentNode.offsetLeft;
}
else {
oItemMenu.hideItens(oItemMenu);
}
}
else {
if (oItemMenu.onClick != null) {
oItemMenu.onClick(oItemMenu);
}
isClickComponentMenu = false;
hideAllComponentMenu();
}
};
Os métodos que criaremos agora é para adicionar os itens no menu.
ItemMenu.prototype.addItemMenu: Adiciona um objeto filho.
ItemMenu.prototype.addItemMenuSeparator: Adiciona um objeto filho, esse objeto separador.
Menu.prototype.addItemMenu: Adiciona um objeto filho.
Listagem 3: Adicionando itens.
Menu.prototype.addItemMenu = function (id, text, value, image) {
var index = this.items.length;
this.items[index] = new ItemMenu(id, text, value, image, false);
return this.items[index];
};
ItemMenu.prototype.addItemMenu = function (id, text, value, image) {
var index = this.items.length;
this.items[index] = new ItemMenu(id, text, value, image, false);
return this.items[index];
};
ItemMenu.prototype.addItemMenuSeparator = function (id) {
this.items[this.items.length] = new ItemMenu(id, '', '', '', true);
};
O próximo método tem a função de esconder os menus.
Listagem 4: Escondendo o menu.
ItemMenu.prototype.hideItens = function (oItemMenu) {
if (oItemMenu.isOpen == true) {
oItemMenu.isOpen = false;
oItemMenu.elementMenuDiv.style.display = 'none';
}
for (var index = 0; index < oItemMenu.items.length; index++) {
oItemMenu.hideItens(oItemMenu.items[index]);
}
};
Menu.prototype.hideItens = function () {
for (var index = 0; index < this.items.length; index++) {
this.items[index].hideItens(this.items[index]);
}
};
Métodos para construir o menu na página.
Menu.prototype.createMenu: Cria o menu principal.
ItemMenu.prototype.createItemMenu: Cria os menus filhos.
Listagem 5: Desenhando o menu.
Menu.prototype.createMenu = function (objRecipient) {
var mainTable = document.createElement('TABLE');
var mainTBody = document.createElement('TBODY');
mainTable.style.width = this.width;
mainTable.style.height = this.height;
mainTable.cellPadding = 0;
mainTable.cellSpacing = 0;
mainTable.border = 0;
mainTable.className = 'menuStyle';
var mainTr = document.createElement('TR');
var mainTd = document.createElement('TD');
//########################### MENU ###############################
var objTable = document.createElement('TABLE');
var objTBody = document.createElement('TBODY');
objTable.style.width = this.width;
objTable.style.height = (parseInt(this.height) - 5) + 'px';
objTable.cellPadding = 0;
objTable.cellSpacing = 0;
objTable.border = 0;
var objTr = document.createElement('TR');
var self = this;
for (var index = 0; index < this.items.length; index++) {
var objTd = document.createElement('TD');
var oItemMenu = this.items[index];
objTd.onmouseover = function () { self.itemMenu_OnMouseOver(this); }
objTd.onmouseout = function () { self.itemMenu_OnMouseOut(this); }
objTd.onclick = function () { self.itemMenu_OnClick(this); }
objTd.onmousedown = function () { componentMenu_onMouseDown(); }
var textItem = '';
if (oItemMenu.image != null && oItemMenu.image != '') {
textItem = '<img src="' + oItemMenu.image + '" /> <label class="fontItemMenuButton">' + oItemMenu.text + '</label>';
}
else {
textItem = '<label class="fontItemMenuButton">' + oItemMenu.text + '</label>';
}
objTd.vAlign = 'middle';
objTd.align = 'center';
objTd.style.cursor = 'default';
objTd.style.whiteSpace = 'nowrap';
objTd.innerHTML = '<span> ' + textItem + ' </span>';
objTd.setAttribute('indexItemMenu', index);
objTr.appendChild(objTd);
if (oItemMenu.items.length > 0) {
oItemMenu.elementMenuDiv = oItemMenu.createItemMenu(objRecipient, oItemMenu.items);
objRecipient.appendChild(oItemMenu.elementMenuDiv);
}
}
var lastTd = document.createElement('TD');
lastTd.style.width = '100%';
lastTd.style.whiteSpace = 'nowrap';
lastTd.innerHTML = ' ';
objTr.appendChild(lastTd);
objTBody.appendChild(objTr);
objTable.appendChild(objTBody);
//########################### MENU ###############################
mainTd.appendChild(objTable);
mainTr.appendChild(mainTd);
mainTBody.appendChild(mainTr);
mainTable.appendChild(mainTBody);
objRecipient.appendChild(mainTable);
};
ItemMenu.prototype.createItemMenu = function (objRecipient, itemMenuCollection) {
var objDIV = document.createElement('DIV');
objDIV.style.display = 'none';
objDIV.style.position = 'absolute';
var objTable = document.createElement('TABLE');
var objTBody = document.createElement('TBODY');
objTable.style.width = widthListComponentMenu;
objTable.cellPadding = 0;
objTable.cellSpacing = 0;
objTable.border = 0;
objTable.className = 'menuStyle';
var self = this;
for (var index = 0; index < itemMenuCollection.length; index++) {
var oItemMenu = itemMenuCollection[index];
if (oItemMenu.isSeparator == false) {
var objTr = document.createElement('TR');
var objTd = document.createElement('TD');
objTr.style.height = heightItemComponentMenu;
objTd.onmouseover = function () { self.itemMenu_OnMouseOver(this); }
objTd.onmouseout = function () { self.itemMenu_OnMouseOut(this); }
objTd.onclick = function () { self.itemMenu_OnClick(this); }
objTd.onmousedown = function () { componentMenu_onMouseDown(); }
objTd.style.cursor = 'default';
objTd.style.whiteSpace = 'nowrap';
objTd.vAlign = 'middle';
var textItem = '';
if (oItemMenu.image != null && oItemMenu.image != '') {
textItem = '<img src="' + oItemMenu.image + '" /> <label class="fontItemMenuButton">' + oItemMenu.text + '</label>';
}
else {
textItem = '<label class="fontItemMenuButton">' + oItemMenu.text + '</label>';
}
if (oItemMenu.items.length > 0) {
objTd.innerHTML = '<table cellpadding="0" cellspacing="0" border="0" width="100%"><tr><td><span> ' + textItem + '</span></td><td style="width:6px"><img src="Arrow.png" /></td></tr></table>';
}
else {
objTd.innerHTML = '<span> ' + textItem + ' </span>';
}
objTd.setAttribute('indexItemMenu', index);
objTr.appendChild(objTd);
objTBody.appendChild(objTr);
if (oItemMenu.items.length > 0) {
oItemMenu.elementMenuDiv = oItemMenu.createItemMenu(objRecipient, oItemMenu.items);
objRecipient.appendChild(oItemMenu.elementMenuDiv);
}
}
else {
var objTr = document.createElement('TR');
var objTd = document.createElement('TD');
objTd.align = 'center';
objTd.innerHTML = '<table cellpadding="0" cellspacing="0" border="0" width="95%"><tr><td class="itemMenuSeparatorStyle"><img style="height:1px;visibility:hidden;" /></td></tr></table>';
objTr.appendChild(objTd);
objTBody.appendChild(objTr);
}
}
objTable.appendChild(objTBody);
objDIV.appendChild(objTable);
return objDIV;
};
Listagem 6: HTML da página.
<html>
<head>
<title></title>
<link rel="stylesheet" href="MainStyleSheet.css" type="text/css" />
<script language="javascript" type="text/javascript" src="MenuJavaScript.js"></script>
<script language="javascript" type="text/javascript">
var oMenu;
var isClickComponentMenu;
var widthListComponentMenu = '130px';
var heightItemComponentMenu = '30px';
function componentMenu_onMouseDown() {
isClickComponentMenu = true;
}
function hideAllComponentMenu() {
if (isClickComponentMenu == false) {
oMenu.hideItens();
}
isClickComponentMenu = false;
}
function document_OnLoad() {
isClickObject = false;
oMenu = new Menu('oMenu', '30px', '100%');
//################ FILE #################
var fileMenu = oMenu.addItemMenu('fileMenu', 'File', '', '');
var newFileMenu = fileMenu.addItemMenu('newFileMenu', 'New', '', '');
var notePadNewFileMenu = newFileMenu.addItemMenu('notePadNewFileMenu', 'Notepad', '', 'Notepad.png');
notePadNewFileMenu.onClick = menu_OnClick;
var wordPadNewFileMenu = newFileMenu.addItemMenu('wordPadNewFileMenu', 'WordPad', '', 'WordPad.png');
wordPadNewFileMenu.onClick = menu_OnClick;
var openFileMenu = fileMenu.addItemMenu('openFileMenu', 'Open', '', 'Open.png');
openFileMenu.onClick = menu_OnClick;
var saveFileMenu = fileMenu.addItemMenu('saveFileMenu', 'Save', '', 'Save.png');
saveFileMenu.onClick = menu_OnClick;
var saveAsFileMenu = fileMenu.addItemMenu('saveAsFileMenu', 'Save As', '', 'Save.png');
saveAsFileMenu.onClick = menu_OnClick;
fileMenu.addItemMenuSeparator('separator1');
var printFileMenu = fileMenu.addItemMenu('printFileMenu', 'Print', '', 'Print.png');
printFileMenu.onClick = menu_OnClick;
fileMenu.addItemMenuSeparator('separator2');
var exitFileMenu = fileMenu.addItemMenu('exitFileMenu', 'Exit', '', 'Exit.png');
exitFileMenu.onClick = menu_OnClick;
//################ FILE #################
//################ EDIT #################
var editMenu = oMenu.addItemMenu('editMenu', 'Edit', '', '');
var undoMenu = editMenu.addItemMenu('undoMenu', 'Undo', '', 'Undo.png');
undoMenu.onClick = menu_OnClick;
var redoMenu = editMenu.addItemMenu('redoMenu', 'Redo', '', 'Redo.png');
redoMenu.onClick = menu_OnClick;
editMenu.addItemMenuSeparator('separator3');
var cutMenu = editMenu.addItemMenu('cutMenu', 'Cut', '', 'Cut.png');
cutMenu.onClick = menu_OnClick;
var copyMenu = editMenu.addItemMenu('copyMenu', 'Copy', '', 'Copy.png');
copyMenu.onClick = menu_OnClick;
var pasteMenu = editMenu.addItemMenu('pasteMenu', 'Paste', '', 'Paste.png');
pasteMenu.onClick = menu_OnClick;
var deleteMenu = editMenu.addItemMenu('deleteMenu', 'Delete', '', 'Delete.png');
deleteMenu.onClick = menu_OnClick;
editMenu.addItemMenuSeparator('separator4');
var findMenu = editMenu.addItemMenu('findMenu', 'Find', '', 'Find.png');
findMenu.onClick = menu_OnClick;
var replaceMenu = editMenu.addItemMenu('replaceMenu', 'Replace', '', 'Replace.png');
replaceMenu.onClick = menu_OnClick;
//################ EDIT #################
//################ FORMAT #################
var formatMenu = oMenu.addItemMenu('formatMenu', 'Format', '', '');
var fontMenu = formatMenu.addItemMenu('fontMenu', 'Font', '', 'Font.png');
fontMenu.onClick = menu_OnClick;
//################ FORMAT #################
//################ VIEW #################
var viewMenu = oMenu.addItemMenu('viewMenu', 'View', '', '');
var statusBarMenu = viewMenu.addItemMenu('statusBarMenu', 'Status bar', '', 'statusBar.png');
statusBarMenu.onClick = menu_OnClick;
//################ VIEW #################
//################ HELP #################
var helpMenu = oMenu.addItemMenu('helpMenu', 'Help', '', '');
var helpTopicsMenu = helpMenu.addItemMenu('helpTopicsMenu', 'Help Topics', '', '');
helpTopicsMenu.onClick = menu_OnClick;
helpMenu.addItemMenuSeparator('separator5');
var aboutMenu = helpMenu.addItemMenu('aboutMenu', 'About', '', '');
aboutMenu.onClick = menu_OnClick;
//################ HELP #################
oMenu.createMenu(document.getElementById('recipientTD'));
}
function menu_OnClick(oItemMenu) {
document.getElementById('clickMenuLabel').innerHTML = oItemMenu.text;
document.getElementById('clickMenuImg').src = (oItemMenu.image == null || oItemMenu.image == '' ? 'Nulo.png' : oItemMenu.image);
}
function document_OnMouseUp() {
hideAllComponentMenu();
}
document.onmouseup = document_OnMouseUp;
</script>
</head>
<body onload="document_OnLoad();" >
<table cellpadding="0" cellspacing="0" border="0" width="100%" >
<tr>
<td id="recipientTD">
</td>
</tr>
<tr style="height:400px;">
<td align="center" valign="middle">
<img id="clickMenuImg" alt="" src="Nulo.png" />
<label id="clickMenuLabel"></label>
</td>
</tr>
</table>
</body>
</html>
Figura 2. Exemplo do Menu.
Até o próximo artigo.