Introduction
I wanted to make a menu that faded in shortly after the page loads, plus I wanted to fade in any of the sub categories when I hovered over a parent category and (call me crazy) I wanted something that would work across browsers. About five hours later, I had created the Fading Javascript Menu and now I want to share it with all of you!
Using the Code
To get the fading JavaScript menu working for your site, save the source zip file to your web server. If you want to use the black and white CSS class, call menu.css or come up with your own theme. Next, add your js file reference and the css reference to the head section of your HTML file. Then add an onload
event to your body
tag and call the function LoadMenu()
. This is all you need to do to get your fading JavaScript menu working. LoadMenu
appends the document's body
object with a table containing your menu. You only need to position your menu where you would like it by editing the relative positioning styles in the ReturnMenuTable
function of the menu.js file.
Here are the functions with explanations for the fading menu.
First, let's declare our variables to hold our setTimeout
ids.
var SubOneCategoryOneInputTimeout = 0;
var SubTwoCategoryOneInputTimeout = 0;
var SubOneCategoryThreeInputTimeout = 0;
Now create a new HTML table, write the fading menu table to the new table and append the new table to the bottom of the document body.
function LoadMenu()
{
TableElement = document.createElement("table");
TableElement.align = 'center';
NewRow = TableElement.insertRow(null);
NewCell = NewRow.insertCell(null);
NewCell.innerHTML = ReturnMenuTable();
document.body.appendChild(TableElement);
setTimeout('DelayMenuLoad()', 600);
}
This function fades in the main menu on page load after a 6 ms pause.
function DelayMenuLoad()
{
displaySubCategory('Home', 0);
displaySubCategory('CategoryOne', 0);
displaySubCategory('CategoryTwo', 0);
displaySubCategory('CategoryThree', 0);
displaySubCategory('CategoryFour', 0);
}
Next, we created our browser specific menu table's HTML and we append the output to the bottom of the page's body. The first five div
s are parent categories. Some will have sub categories, others will not. If they do not contain any sub categories, then they will only hightlight on the mouse over event and will redirect to another page when clicked. The next three div
s are sub categories. The thing to watch out for is to not let the sub category get highlighted or fade out if it is not visible. We must test whether the category has faded in first.
function ReturnMenuTable()
{
if(navigator.appName == "Microsoft Internet Explorer")
{
return '<tr><td><table id="menutable" runat="server" align="center" width="200px"
style="position: relative; top: -815px; left: -20px;" border="0"
cellspacing="0" cellpadding="0">' +
'<tr>' +
'<td>' +
'<div id="Home" style="position: relative; left: -90px; top: 19px;
filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryHomeInput" class="button_menu_class"
style="cursor: pointer; width: 55px; height: 19px;"
onmouseout="MouseOutCategory(\'CategoryHomeInput\');"
onmouseover="MouseOverCategory(\'CategoryHomeInput\');"
onclick="javascript:parent.location.href=\'/home.html\'"
value=" Home "></input>' +
'</div>' +
'<div id="CategoryOne" style="position: relative; left: -25px;
top: -2px; filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryOneInput" class="button_menu_class"
style="cursor: default; width: 70px; height: 19px;"
onmouseout="MouseOutCategoryWithSubCategories(\'CategoryOneInput\');"
onmouseover="MouseOverCategoryWithSubCategories(\'CategoryOneInput\');"
value=" Software "></input>' +
'</div>' +
'<div id="CategoryTwo" style="position: relative; left: 53px;
top: -23px; filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryTwoInput" class="button_menu_class"
style="cursor: pointer; width: 95px; height: 19px;"
onmouseout="MouseOutCategory(\'CategoryTwoInput\');"
onmouseover="MouseOverCategory(\'CategoryTwoInput\');"
onclick="javascript:parent.location.href=\'/techsupport.html\'"
value=" Tech Support "></input>' +
'</div>' +
'<div id="CategoryThree" style="position: relative; left: 157px;
top: -44px; filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryThreeInput" class="button_menu_class"
style="cursor: default; width: 105px; height: 19px;"
onmouseout="MouseOutCategoryWithSubCategories(\'CategoryThreeInput\');"
onmouseover="MouseOverCategoryWithSubCategories(\'CategoryThreeInput\');"
value=" Code Snippets "></input>' +
'</div>' +
'<div id="CategoryFour" style="position: relative; left: 270px;
top: -65px; filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryFourInput" class="button_menu_class"
style="cursor: pointer; width: 75px; height: 19px;"
onmouseout="MouseOutCategory(\'CategoryFourInput\');"
onmouseover="MouseOverCategory(\'CategoryFourInput\');"
onclick="javascript:parent.location.href=\'/aboutus.html\'"
value=" About Us "></input>' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td>' +
'<div id="SubOneCategoryOne" style="position: relative;
top: -59px; left: -25px">' +
'<input id="SubOneCategoryOneInput"
onclick="javascript:if(
document.getElementById(\'SubOneCategoryOneInput\').style.opacity >
0.01 || document.getElementById(
\'SubOneCategoryOneInput\').style.filter != undefined){
parent.location.href=\'/solutions/ecommerce.html\';}"
class="button_menu_class" onmouseout="MouseOutSubCategory(
\'SubOneCategoryOneInput\')" onmouseover="MouseOverSubCategory(
\'SubOneCategoryOneInput\');"
style="cursor: pointer; filter:alpha(opacity=0);
opacity: 0.0; width: 148px; height: 19px;"
value=" Ecommerce Packages "></input>' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td>' +
'<div id="SubTwoCategoryOne" style="position: relative; top: -60px; left: -25px">' +
'<input id="SubTwoCategoryOneInput"
onclick="javascript:if(document.getElementById(
\'SubTwoCategoryOneInput\').style.opacity > 0.01 ||
document.getElementById(\'SubTwoCategoryOneInput\').style.filter !=
undefined){parent.location.href=\'/solutions/pointofsale.html\';}"
class="button_menu_class" onmouseout="MouseOutSubCategory(
\'SubTwoCategoryOneInput\');" onmouseover="MouseOverSubCategory(
\'SubTwoCategoryOneInput\');"
style="cursor: pointer; filter:alpha(opacity=0); opacity: 0.0;
width: 158px; height: 19px;" value=" Point of Sales Packages "></input>' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td>' +
'<div id="SubOneCategoryThree" style="position: relative; top: -104px; left: 157px">' +
'<input id="SubOneCategoryThreeInput"
onclick="javascript:if(document.getElementById(
\'SubOneCategoryThreeInput\').style.opacity > 0.01 ||
document.getElementById(\'SubOneCategoryThreeInput\').style.filter !=
undefined){parent.location.href=\'/codesnippets/js_fading_menu.html\';}"
class="button_menu_class"
onmouseout="MouseOutSubCategory(\'SubOneCategoryThreeInput\')"
onmouseover="MouseOverSubCategory(\'SubOneCategoryThreeInput\');"
style="cursor: pointer; filter:alpha(opacity=0);
opacity: 0.0; width: 70px; height: 19px;"
value=" javascript "></input>' +
'</div>' +
'</td>' +
'</tr>' +
'</table></td></tr>';
}
else
{
return '<tr><td><table id="menutable" align="center" width="200px"
style="position: relative; top: -815px; left: -20px;" cellspacing="0"
border="0" cellpadding="0">' +
'<tr>' +
'<td>' +
'<div id="Home" style="position: relative; left: -90px; top: 19px;
filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryHomeInput" class="button_menu_class"
style="cursor: pointer; width: 55px; height: 19px;"
onmouseout="MouseOutCategory(\'CategoryHomeInput\');"
onmouseover="MouseOverCategory(\'CategoryHomeInput\');"
onclick="javascript:parent.location.href=\'/home.html\'"
value=" Home" ></input>' +
'</div>' +
'<div id="CategoryOne" style="position: relative; left: -25px;
top: 0px; filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryOneInput" class="button_menu_class"
style="cursor: default; width: 70px; height: 19px;"
onmouseout="MouseOutCategoryWithSubCategories(
\'CategoryOneInput\');"
onmouseover="MouseOverCategoryWithSubCategories(
\'CategoryOneInput\');" value=" Software" ></input>' +
'</div>' +
'<div id="CategoryTwo"
style="position: relative; left: 53px; top: -19px;
filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryTwoInput" class="button_menu_class"
style="cursor: pointer; width: 95px; height: 19px;"
onmouseout="MouseOutCategory(\'CategoryTwoInput\');"
onmouseover="MouseOverCategory(\'CategoryTwoInput\');"
onclick="javascript:parent.location.href=\'/techsupport.html\'"
value=" Tech Support "></input>' +
'</div>' +
'<div id="CategoryThree" style="position: relative;
left: 157px; top: -38px; filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryThreeInput" class="button_menu_class"
style="cursor: default; width: 105px; height: 19px;"
onmouseout="MouseOutCategoryWithSubCategories(
\'CategoryThreeInput\');"
onmouseover="MouseOverCategoryWithSubCategories(
\'CategoryThreeInput\');" value=" Code Snippets "></input>' +
'</div>' +
'<div id="CategoryFour" style="position: relative;
left: 270px; top: -57px; filter:alpha(opacity=1); opacity: 0.0;">' +
'<input id="CategoryFourInput" class="button_menu_class"
style="cursor: default; width: 75px; height: 19px;"
onmouseout="MouseOutCategory(\'CategoryFourInput\');"
onmouseover="MouseOverCategory(\'CategoryFourInput\');"
onclick="javascript:parent.location.href=\'/aboutus.html\'"
value=" About Us "></input>' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td>' +
'<div id="SubOneCategoryOne" style="position: relative;
top: -56px; left: -25px">' +
'<input id="SubOneCategoryOneInput"
onclick="javascript:if(document.getElementById(
\'SubOneCategoryOneInput\').style.opacity > 0.01 ||
document.getElementById(\'SubOneCategoryOneInput\').style.filter !=
undefined){parent.location.href=\'/solutions/ecommerce.html\';}"
class="button_menu_class" onmouseout="MouseOutSubCategory(
\'SubOneCategoryOneInput\')"
onmouseover="MouseOverSubCategory(\'SubOneCategoryOneInput\');"
style="cursor: pointer; filter:alpha(opacity=0); opacity: 0.0;
width: 148px; height: 19px;" value=" Ecommerce Packages "></input>' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td>' +
'<div id="SubTwoCategoryOne" style="position: relative;
top: -55px; left: -25px">' +
'<input id="SubTwoCategoryOneInput"
onclick="javascript:if(document.getElementById(
\'SubTwoCategoryOneInput\').style.opacity > 0.01 ||
document.getElementById(\'SubTwoCategoryOneInput\').style.filter !=
undefined){parent.location.href=\'/solutions/pointofsale.html\';}"
class="button_menu_class" onmouseout="MouseOutSubCategory(
\'SubTwoCategoryOneInput\');"
onmouseover="MouseOverSubCategory(\'SubTwoCategoryOneInput\');"
style="cursor: pointer; filter:alpha(opacity=0); opacity: 0.0;
width: 158px; height: 19px;"
value=" Point of Sales Packages "></input>' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td>' +
'<div id="SubOneCategoryThree"
style="position: relative; top: -94px; left: 157px">' +
'<input id="SubOneCategoryThreeInput"
onclick="javascript:if(document.getElementById(
\'SubOneCategoryThreeInput\').style.opacity > 0.01 ||
document.getElementById(\'SubOneCategoryThreeInput\').style.filter !=
undefined){parent.location.href=\'/codesnippets/js_fading_menu.html\';}"
class="button_menu_class" onmouseout="MouseOutSubCategory(
\'SubOneCategoryThreeInput\')" onmouseover="MouseOverSubCategory(
\'SubOneCategoryThreeInput\');"
style="cursor: pointer; filter:alpha(opacity=0); opacity: 0.0;
width: 70px; height: 19px;" value=" Javascript "></input>' +
'</div>' +
'</td>' +
'</tr>' +
'</table></td></tr>';
}
}
Here's how we fade in the sub categories. Internet Explorer uses the style
attribute called filter
and it can range from "alpha(opacity=0)
" [100% opaque] to "alpha(opacity=100)
" [0% opaque]. For gecko based, Chrome, Opera and Safari browser, use the style
attribute opacity which ranges from "object.style.opacity = 0
" [100% opaque] to "object.style.opacity = 1
" [0% opaque]. This function is recursive, meaning if the opacity is greater than zero, the function will call itself slowly reducing the opacity giving us the fading in and fading out.
function displaySubCategory(SubCategory, CurrentOpacity)
{
if(!document.getElementById(SubCategory))
return;
if(navigator.appName == "Microsoft Internet Explorer")
{
if(CurrentOpacity == 0)
CurrentOpacity = 1;
CurrentOpacity = CurrentOpacity + 50;
document.getElementById(SubCategory).style.filter =
'alpha(opacity=' + CurrentOpacity + ')';
if(CurrentOpacity < 100)
setTimeout('displaySubCategory("' +
SubCategory + '",' + CurrentOpacity + ')', 140);
}else
{
CurrentOpacity = CurrentOpacity + 0.5;
document.getElementById(SubCategory).style.opacity = CurrentOpacity;
if(CurrentOpacity < 1)
setTimeout('displaySubCategory("' + SubCategory + '",' +
CurrentOpacity + ')', 140);
}
}
Here's how we hide the sub categories. This function although similar to the function above it works in an opposite manner to fade out menu items.
function HideSubCategory(SubCategory, CurrentOpacity)
{
if(document.getElementById(SubCategory) && navigator.appName ==
"Microsoft Internet Explorer")
{
if(CurrentOpacity > 0)
{
CurrentOpacity = CurrentOpacity - 50;
setTimeout('HideSubCategory("' + SubCategory + '",' +
CurrentOpacity + ')', 140);
document.getElementById(SubCategory).style.filter =
'alpha(opacity=' + CurrentOpacity + ')';
}
else
{
document.getElementById(SubCategory).style.filter =
'alpha(opacity=0)';
SubOneCategoryOneInputTimeout = 0;
SubTwoCategoryOneInputTimeout = 0;
SubOneCategoryThreeInputTimeout = 0;
}
}else if(document.getElementById(SubCategory))
{
if(CurrentOpacity > 0)
{
CurrentOpacity = (CurrentOpacity / 99.0) - 0.5;
setTimeout('HideSubCategory(\'' + SubCategory + '\',' +
CurrentOpacity + ')', 140);
document.getElementById(SubCategory).style.opacity =
CurrentOpacity;
}
else
{
document.getElementById(SubCategory).style.opacity = 0;
SubOneCategoryOneInputTimeout = 0;
SubTwoCategoryOneInputTimeout = 0;
SubOneCategoryThreeInputTimeout = 0;
}
}
}
These simple functions are for hightlighting and unhighlighting the top categories without any sub categories when moused over or out.
function MouseOverCategory(Category)
{
document.getElementById(Category).style.backgroundColor='#66ccff';
}
function MouseOutCategory(Category)
{
document.getElementById(Category).style.backgroundColor='#ffffff';
}
Next we handle the mouseover
event for a category with sub categories. SubOneCategoryOneInput
and SubTwoCategoryOneInput
are related because they both belong to the same parent category. Therefore, they will fade in and out together.
function MouseOverCategoryWithSubCategories(SubCategory)
{
document.getElementById(SubCategory).style.backgroundColor = '#66ccff';
if((SubCategory == 'CategoryOneInput' || SubCategory == 'CategoryTwoInput') &&
document.getElementById('SubOneCategoryOneInput').style.opacity < 0.01)
{
displaySubCategory('SubOneCategoryOneInput', 0);
displaySubCategory('SubTwoCategoryOneInput', 0);
}
else if((SubCategory == 'CategoryOneInput' ||
SubCategory == 'CategoryTwoInput') && document.getElementById(
'SubOneCategoryOneInput').style.filter != undefined)
{
displaySubCategory('SubOneCategoryOneInput', 0);
displaySubCategory('SubTwoCategoryOneInput', 0);
}
else if(SubCategory == 'CategoryThreeInput' && document.getElementById(
'SubOneCategoryThreeInput').style.opacity < 0.01)
displaySubCategory('SubOneCategoryThreeInput', 0);
else if(SubCategory == 'CategoryThreeInput' && document.getElementById(
'SubOneCategoryThreeInput').style.filter != undefined)
displaySubCategory('SubOneCategoryThreeInput', 0);
}
Here, we handle the mouseoout
event for a category with sub categories.
function MouseOutCategoryWithSubCategories(SubCategory)
{
document.getElementById(SubCategory).style.backgroundColor = '#ffffff';
if((SubCategory == 'CategoryOneInput' || SubCategory == 'CategoryTwoInput') &&
document.getElementById('SubOneCategoryOneInput').style.opacity > 0.01)
{
SubOneCategoryOneInputTimeout = setTimeout('HideSubCategory(
\'SubOneCategoryOneInput\', 99)', 120);
SubTwoCategoryOneInputTimeout = setTimeout('HideSubCategory(
\'SubTwoCategoryOneInput\', 99)', 120);
}else if((SubCategory == 'CategoryOneInput' || SubCategory ==
'CategoryTwoInput') && document.getElementById(
'SubOneCategoryOneInput').style.filter != undefined)
{
SubOneCategoryOneInputTimeout = setTimeout('HideSubCategory(
\'SubOneCategoryOneInput\', 99)', 120);
SubTwoCategoryOneInputTimeout = setTimeout('HideSubCategory(
\'SubTwoCategoryOneInput\', 99)', 120);
}
else if(SubCategory == 'CategoryThreeInput' && document.getElementById(
'SubOneCategoryThreeInput').style.opacity > 0.01)
SubOneCategoryThreeInputTimeout = setTimeout('HideSubCategory(
\'SubOneCategoryThreeInput\', 99)', 120);
else if(SubCategory == 'CategoryThreeInput' && document.getElementById(
'SubOneCategoryThreeInput').style.filter != undefined)
SubOneCategoryThreeInputTimeout = setTimeout('HideSubCategory(
\'SubOneCategoryThreeInput\', 99)', 120);
}
This function highlights the sub category and clears any of the recursive setTimeout
function calls so that the item does not fade out. The trick here is to not highlight or change the cursor to default when the button is not displayed.
function MouseOverSubCategory(SubCategory)
{
document.getElementById(SubCategory).style.cursor = 'Default';
if(navigator.appName != "Microsoft Internet Explorer" &&
document.getElementById(SubCategory).style.opacity == 0)
return;
else if(navigator.appName == "Microsoft Internet Explorer" &&
(document.getElementById(SubCategory).style.filter == undefined ||
document.getElementById(SubCategory).style.filter == 'alpha(opacity=0)'))
return;
document.getElementById(SubCategory).style.cursor = 'pointer';
document.getElementById(SubCategory).style.backgroundColor = '#66ccff';
if(SubCategory == 'SubOneCategoryOneInput' ||
SubCategory == 'SubTwoCategoryOneInput')
{
if(SubOneCategoryOneInputTimeout > 0)
{
try
{
clearTimeout(SubOneCategoryOneInputTimeout);
}catch(asdf){}
}
if(SubTwoCategoryOneInputTimeout > 0)
{
try
{
clearTimeout(SubTwoCategoryOneInputTimeout);
}catch(asdf){}
}
}else if(SubOneCategoryThreeInputTimeout > 0)
{
try
{
clearTimeout(SubOneCategoryThreeInputTimeout);
}catch(asdf){}
}
}
Finally, we need to handle the mouseout
event for the sub categories. We store the setTimeout
ids so that if the user hovers back over the button before it faded out of site, we can cancel the fade.
function MouseOutSubCategory(SubCategory)
{
document.getElementById(SubCategory).style.cursor = 'Default';
if(navigator.appName != "Microsoft Internet Explorer" &&
document.getElementById(SubCategory).style.opacity == 0)
return;
else if(navigator.appName == "Microsoft Internet Explorer" &&
(document.getElementById(SubCategory).style.filter == undefined ||
document.getElementById(SubCategory).style.filter ==
'alpha(opacity=0)'))
return;
document.getElementById(SubCategory).style.backgroundColor='#ffffff';
if(SubCategory == 'SubOneCategoryOneInput' || SubCategory ==
'SubTwoCategoryOneInput')
{
if(navigator.appName == "Microsoft Internet Explorer")
{
SubOneCategoryOneInputTimeout = setTimeout(
'HideSubCategory(\'SubOneCategoryOneInput\', 99)', 120);
SubTwoCategoryOneInputTimeout = setTimeout(
'HideSubCategory(\'SubTwoCategoryOneInput\', 99)', 120);
}else
{
SubOneCategoryOneInputTimeout = setTimeout('HideSubCategory(
\'SubOneCategoryOneInput\', 99)', 120);
SubTwoCategoryOneInputTimeout = setTimeout('HideSubCategory(
\'SubTwoCategoryOneInput\', 99)', 120);
}
}else if(SubCategory == 'SubOneCategoryThreeInput')
SubOneCategoryThreeInputTimeout = setTimeout(
'HideSubCategory(\'SubOneCategoryThreeInput\', 99)', 120);
}
Author's Site
I've been programming for about six years now and thankfully its not one of those fields that stagnates year after year. Programming always feels new and it forces you to learn new things and if you don't stay on top of the newest standards you'll be looking for a different line of work.
Programming is fun… after you get past the excruciating part.