Building a Dynamic Menu with CSS and JavaScript, part 1 - The "menu" JavaScript object
(Page 4 of 4 )
If you have ever worked with user-defined JavaScript objects, then you know that it is similar to working with functions, with some specific proprietary syntax. The core concept behind object-oriented programming is reusability, and I'm certainly going to take advantage of it. In order to define a new class, we must set up a constructor method to initialize the class properties, and then define the methods belonging to it. Finally, when we need to instantiate a new object from the class, we use the keyword "new" for doing so. I’m not going to explain in detail all of the theory behind user-defined objects in JavaScript, since it’s a very huge subject. For the scope of this article, it’s enough to know that I will define a "menu" class that will take care of building the dynamic menu.
Since through the class I’m defining the blueprints for any "menu" object, we can instantiate as many objects as we need for the application, just defining different properties values for each one of them. With a pinch of object theory, let’s see the JavaScript class that generates the dynamic menu. Here’s the complete source code listing:
function Menu(menuTexts,menuLinks){
if(arguments.length!=2||!menuTexts.length||!
menuLinks.length){return;}
for(var i=0;i<menuTexts.length;i++){
if(typeof(menuTexts[i])!='string'||typeof(menuLinks
[i])!='string'){return;}
}
this.menuTexts=menuTexts;
this.menuLinks=menuLinks;
this.loc=location.href;
this.d=document.createElement('div');
this.d.id='dynmenu';
this.leftCorner=createLeftCorner;
this.links=createLinks;
this.rightCorner=createRightCorner;
this.build=buildMenu;
return this.build();
}
function createLeftCorner(){
var lc=document.createElement('span');
lc.className='leftcorner';
lc.innerHTML=' ';
this.d.appendChild(lc);
}
function createRightCorner(){
var rc=document.createElement('span');
rc.className='rightcorner';
rc.innerHTML=' ';
this.d.appendChild(rc);
}
function createLinks(){
for(var i=0;i<this.menuTexts.length;i++){
var a=document.createElement('a');
a.appendChild(document.createTextNode
(this.menuTexts[i]));
a.href=this.menuLinks[i];
a.title=this.menuTexts[i];
this.loc.indexOf(a.href,0)!=-1?
a.className='activebutton':a.className=
'regbutton';
this.d.appendChild(a);
}
}
function buildMenu(){
this.leftCorner();
this.links();
this.rightCorner();
return this.d;
}
window.onload=function(){
if(document.body&&document.body.firstChild){
menuTexts=new Array('About
Us','Products','Services','Links','Contact Us');
menuLinks=new Array('about.htm','products.htm',
'services.htm','links.htm','contact.htm');
var menu=new Menu(menuTexts,menuLinks);
document.body.insertBefore
(menu,document.body.firstChild);
}
}
Here it’s recommended to employ a single (.js) file that will be used for all of the pages under the navigation menu. This way, you won’t need to update all the pages. By just updating only the JavaScript library file (.js), the job will be nicely done.
Now, let’s break down the code, to understand the properties and methods assigned to the class. I begin by defining the "menu()" constructor method, which accepts two parameters: "menuTexts" and "menuLinks". The first parameter refers to the texts displayed for the links. The second references the URLs corresponding to each link.
Until now it’s simple. The constructor takes these parameters and assigns them as class properties. Next, I assign a new property named "loc", which contains the URL corresponding to the current page. The following line does so:
this.loc=location.href;
The next step consists of creating the general <div> menu container element, and ties a style to it:
this.d=document.createElement('div');
this.d.id='dynmenu';
The rest of the code for the constructor defines the methods "createLeftCorner", "createLinks" and "createRightCorner", for generating the three main sections of the menu. Finally, the constructor invokes the "buildMenu" method to create the whole menu structure.
As the name implies, the "createLeftCorner" method builds the left corner of the menu, creating a <span> tag, attaching the "leftcorner" CSS class to it and assigning a ' ' as a value of its "innerHTML" property. Although this property is not really standard, it is fully supported by most browsers, so it becomes handy for implementing in cross-browser projects. In a similar fashion the "createRightCorner" method generates the right corner section. Once the two corners have been created, they’re appended as child nodes in the <div> menu container. Are you still with me? Fine, because we’re almost done.
To generate the menu links, the "createLinks" method loops through the arrays "menuTexts" and "menuLinks" to assign the texts and the URLs for each link. Here an explanation is needed. In order to determine whether the link corresponds to the active page, the method simply compares the page’s current location with the value of each element of the "menuLinks" array. If there is a match, the corresponding link is displayed differently. This location resolving process is done with the line:
this.loc.indexOf(a.href,0)!=-1?a.className='activebutton':a.className=
'regbutton';
Finally, once all of the links have been appended to the menu container element, the menu is ready to be inserted into the Web document. As usual, once the page is loaded, a "menu" object is instantiated and the proper parameters, menu links and texts are passed to the constructor. I’ve inserted the menu as the first child of the body element, but you might chose another insertion point within the document. The following lines do that:
window.onload=function(){
if(document.body&&document.body.firstChild){
menuTexts=new Array('About
Us','Products','Services','Links','Contact Us');
menuLinks=new Array
('about.htm','products.htm','services.htm',
'links.htm','contact.htm');
menu=new Menu(menuTexts,menuLinks);
document.body.insertBefore
(menu,document.body.firstChild);
}
}
I’ve defined some links to be displayed in the menu, in conjunction with their texts. This is completely customizable. Because the class is generating the necessary HTML markup via the DOM methods, the source HTML might be reduced to something like this:
<body>
<h1>Page Name</h1>
</body>
And, if you name the (.js) file something like "menu.js", the code to be placed in all of the pages would be the following:
<script language="javascript" src="menu.js"></script>
After some hard work, that’s your dynamic menu! Don’t you feel a bit happier? I bet you do.
Wrapping up
In the first part of this series, we’ve deeply covered the construction process of a dynamic menu, extensively using the DOM methods within user-defined JavaScript objects, to help us learn to build more complex structures. Of course, there is a flip side to this approach. If the client has disabled scripting on the browser, the menu won’t be displayed. Anyway, the challenge is worth tackling.
In the second part, I’m going to go further, building a new JavaScript class that generates all of the CSS code for the menu. Don’t miss it!
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |