There is virtually no limit to what you can do with the Document Object Model. DOM uses include everything from simple mouseover image rotations to complex mouseover menus. Instead of trying to present every facet of using the DOM in a dry, formal discussion, I will present several examples and explain the problems and issues that occurred while writing them.
The most commonly used example of the DOM at work is the popular mouseover image rotation. Here is a partial example of how this is done:
<img src="image1.jpg" onMouseOver="JavaScript: this.src='image2.jpg';" onMouseOut="JavaScript: this.src='image1.jpg';">
When the image element is first loaded, image1.jpg is displayed. As the user moves his mouse cursor over the image element, the image changes to image2.jpg. When the user moves his mouse cursor off of the image, the original image1.jpg is displayed again. This simple example can be expanded to include the onMouseDown event, like this:
<img src="image1.jpg" onMouseOver="JavaScript: this.src='image2.jpg';" onMouseOut="JavaScript: this.src='image1.jpg';" onMouseDown="JavaScript: this.src='image3.jpg';">
This will not only give the user visual feedback when he moves the mouse cursor over or out of the image, but will also create an interesting effect when he clicks on the image—especially if the image is used as a hyperlink. This example is very simple to implement. You won't have any trouble with this technique as long as the browser can interpret all three mouse events.
The mouseover menu is a very popular feature that is used with great success on many Web applications. Mouseover menus are the menus, including File, Edit, View, Help, and others, found on the menu bar on any popular application.
Compared to the image rollover example above, this mouseover menu example is quite a bit more complex. Because of the limitations of the Netscape browser, this example can only be easily implemented for Internet Explorer. The techniques used in the example can be used in both browsers, however.
The first step to creating a mouseover menu is to create a function that will position HTML elements anywhere on the document:
function openMenuAbsolute( element, xPos, yPos ) { element.style.left = xPos; element.style.top = yPos; }
The openMenuAbsolute() function will position any element at the given coordinates on the document. Once this function is established, you can begin to create the menu bar. For simplicity's sake, this example will mimic Internet Explorer's menu bar but not its functionality. The HTML to make the actual bar that contains the menus would be something like this:
<center> <table border="1" width="75%"> <tr> <td width="17%"> <a href="JavaScript: void 0;" onMouseOver="JavaScript:"> File </a> </td> <td width="17%"> <a href="JavaScript: void 0;" onMouseOver="JavaScript:"> Edit </a> </td> <td width="17%"> <a href="JavaScript: void 0;" onMouseOver="JavaScript:"> View </a> </td> <td width="17%"> <a href="JavaScript: void 0;" onMouseOver="JavaScript:"> Favorites </a> </td> <td width="17%"> <a href="JavaScript: void 0;" onMouseOver="JavaScript:"> Tools </a> </td> <td width="17%"> <a href="JavaScript: void 0;" onMouseOver="JavaScript:"> Help </a> </td> </tr> </table> </center>
The event handlers for each menu will be filled in later.
Now that the menu bar has been created, the actual menus must be designed. The menus will be created in two parts. The first part is a style sheet class from which the menus will inherit, and the second part is the actual menu element.
Here's the first part, the style sheet class:
.menu { visibility: hidden; position: absolute; padding: 4px; background-color: "#D0D0D0"; border-style: solid; border-width: 2px; border-color: black; font-family: "Courier New"; font-size: 10; left: -1000; top: -1000; }
This style sheet class is called menu and sets several important aspects of its object. First of all, the menu objects will be initially hidden. They will also be absolutely positioned at coordinates −1000, −1000—this is necessary because even when absolutely positioned elements are hidden, they still may make it necessary for the browser to create scroll bars. The other attributes are just look-and-feel properties.
And now for the second part. The HTML DIV tag lends itself perfectly to this example. Here is the File menu fully written out:
<div class="menu" ID="File" style="width: 235;" level="0"> <a href="JavaScript: void 0;" onMouseOver="JavaScript: openMenuAbsolute( document.all.File_New, document.all.File.offsetLeft + document.all.File.clientWidth 1, document.all.File.offsetTop );"> New </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Open... </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Edit with Microsoft Front Page </a></br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Save </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Save as... </a><br> <hr> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Print... </a><br> <hr> <a href="JavaScript: void 0;" onMouseOver="JavaScript: openMenuAbsolute( document.all.File_New, document.all.File.offsetLeft + document.all.File.clientWidth 1, document.all.File.offsetTop + 125 );"> Send </a><br> <a href="JavaScript: void 0;" onMouseOver="javascrip: hideLevel( 1 );"> Import and Export... </a><br> <hr> <a href="JavaScript: void 0;" onMouseOver="javascrip: hideLevel( 1 );"> Properties </a><br> <a href="JavaScript: void 0;" onMouseOver="javascrip: hideLevel( 1 );"> Close </a><br> </div>
Two things make this DIV element interesting. The first is that it has a new property name, level, which has a value of 0. This property is used so that no two menus with the same level value can be open at one time. Secondly, each item in the menu has an onMouseOver event handler. Most of the event handlers make a call to the function hideLevel(), which will be explained later. The New and Send menu items, however, make a call to the openMenuAbsolute() function, which was explained previously.
Notice that on your Internet Explorer menu, New and Send each open a submenu. The HTML menus you create here will do the same thing. First, though, there needs to be a way to hide menus that should not be visible. The following function does just that:
function hideLevel( level ) { // Get all the <DIV> tags on the document var divTags = document.all.tags( "div" ); // Loop through the array of <DIV> tags for( i = 0 ; i < divTags.length ; i++ ) { // If the <DIV> is a menu and its level is greater // or equal to ‘level' then hide it if( divTags[i].className == "menu" && divTags[i].level >= level ) { // Hid the menu divTags[i].style.visibility = "hidden"; // Even when a menu is hidden, it might still // cause the scroll bars to be abnormally positioned // so I move the menu off the screen divTags[i].style.left = -1000; divTags[i].style.top = -1000; } } }
The hideLevel() function requests an array that contains a reference to every DIV element on the page, loops through each element in the array to see if it's a menu, and hides it if the level is bigger than the specified value.
One more item is required for this example to be fully functional: a function that will open a menu relative to another HTML element. Here is one possible implementation of such a function:
function openMenuRelative( divMenu, parent, position ) { xPos = 0; yPos = 0; // I subtract 4 because of the menu's border // ( 2 * border-width in pixels ) if( position == "TOP" ) yPos = 0 divMenu.clientHeight 4; else if( position == "BOTTOM" ) yPos = parent.clientHeight; // I subtract 4 because of the menu's border // ( 2 * border-width in pixels ) else if( position == "LEFT" ) xPos = 0 divMenu.clientWidth 4; else if( position == "RIGHT" ) xPos = parent.clientWidth; do { // For some reason <CENTER> tags mess up the // x,y coordinates so I ignore them if( parent.tagName != "CENTER" ) { xPos += parent.offsetLeft; yPos += parent.offsetTop; // The border-width of any element that has // a border is factored into the elements actual size // Running this part of the code will make // the menu cover up the border if( parent.border != null ) { xPos -= parent.border * 2; yPos -= parent.border * 2; } } // Move to the next highest element parent = parent.parentElement; } while( parent != null ); // Open the menu with the relative x,y coordinate openMenuAbsolute( divMenu, xPos, yPos ); }
This function takes a DIV element that is being used as a menu, the element that the menu will be opened relative to, and the relative position to open the menu. The last parameter can have one of four values—"BOTTOM", "TOP", "LEFT"or "RIGHT". This example will use only the "BOTTOM" position.
All that is left to complete this mouseover menu example is to create the page with all of the given functions and menus. This example contains only the first three Internet Explorer menus in order to conserve space:
<html> <head> <title> JavaScriptt Professional Projects Mouse Over Menus </title> <style type="text/css"> <!-- a { color: blue; text-decoration: none; font-size: 12; font-family: "Courier New"; } a:hover { color: blue; text-decoration: underline; font-size: 12; font-family: "Courier New"; } .menu { visibility: hidden; position: absolute; padding: 4px; background-color: "#D0D0D0"; border-style: solid; border-width: 2px; border-color: black; font-family: "Courier New"; font-size: 10; left: -1000; top: -1000; } --> </style> <script language="javascript"> function openMenuAbsolute( divMenu, xPos, yPos ) { hideLevel( divMenu.level ); divMenu.style.left = xPos; divMenu.style.top = yPos; divMenu.style.visibility = "visible"; } function openMenuRelative( divMenu, parent, position ) { xPos = 0; yPos = 0; // I subtract 4 because of the menu's border // ( 2 * border-width in pixels ) if( position == "TOP" ) yPos = 0 divMenu.clientHeight 4; else if( position == "BOTTOM" ) yPos = parent.clientHeight; // I subtract 4 because of the menu's border // ( 2 * border-width in pixels ) else if( position == "LEFT" ) xPos = 0 divMenu.clientWidth 4; else if( position == "RIGHT" ) xPos = parent.clientWidth; do { // For some reason <CENTER> tags mess up the // x,y coordinates so I ignore them if( parent.tagName != "CENTER" ) { xPos+= -=parent.offsetLeft; yPos+= -=parent.offsetTop; // The border-width of any element that has a // border is factored into the element's actual size // Running this part of the code will make // the menu cover up the border if( parent.border != null ) { xPos -= parent.border * 2; yPos -= parent.border * 2; } // Move to the next highest element parent = parent.parentElement; } while( parent != null ); // Open the menu with the relative x,y coordinate openMenuAbsolute( divMenu, xPos, yPos ); } function hideLevel( level ) { // Get all the <DIV> tags on the document divTags = document.all.tags( "div" ); // Loop through the array of <DIV> tags for( i = 0 ; i < divTags.length ; i++ ) { // If the <DIV> is a menu and its level is greater // or equal to ‘level' then hide it if( divTags[i].className == "menu" && divTags[i].level >= level ) { // Hid the menu divTags[i].style.visibility = "hidden"; // Even when a menu is hidden, it might still // cause the scroll bars to be abnomaly positioned // so I move the menu off the screen divTags[i].style.left = -1000; divTags[i].style.top = -1000; } } } </script> </head> <body onMouseUp="JavaScript: hideLevel( 0 );" onResize="JavaScriptt: hideLevel( 0 );"> <center> <font size=6>JavaScriptt Professional Projects</font><br> <font size=4>Chapter 7: Mouse Over Menus</font> <br><br> <br><br> <table border="1" width="75%"> <tr> <td width="17%"> <a onMouseOver="JavaScript: openMenuRelative( document.all.File, this.parentElement, 'BOTTOM' );"> File </a> </td> <td width="17%"> <a onMouseOver="JavaScript: openMenuRelative( document.all.Edit, this.parentElement, 'BOTTOM' );"> Edit </a> </td> <td width="17%"> <a onMouseOver="JavaScript: openMenuRelative( document.all.View, this.parentElement, 'BOTTOM' );"> View </a> </td> <td width="17%"><a>Favorites</a></td> <td width="17%"><a>Tools</a></td> <td width="17%"><a>Help</a></td> </tr> </table> </center> <div class="menu" ID="File" style="width: 235;" level="0"> <a href="JavaScript: void 0;" onMouseOver="JavaScript: openMenuAbsolute( document.all.File_New, document.all.File.offsetLeft + document.all.File.clientWidth 1, document.all.File.offsetTop );"> New </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Open... </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Edit with Microsoft Front Page </a></br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Save </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Save as... </a><br> <hr> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Print... </a><br> <hr> <a href="JavaScript: void 0;" onMouseOver="JavaScript: openMenuAbsolute( document.all.File_New, document.all.File.offsetLeft + document.all.File.clientWidth 1, document.all.File.offsetTop + 125 );"> Send. </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Import and Export... </a><br> <hr> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Properties </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Close </a><br> </div> <div class="menu" ID="Edit" style="width: 185;" level="0"> <a href="JavaScript: void 0;"> Cut </a><br> <a href="JavaScript: void 0;">Copy</a><br> <a href="JavaScript: void 0;">Paste</a><br> <hr> <a href="JavaScript: void 0;">Select All...</a><br> <hr> <a href="JavaScript: void 0;">Find (on This Page)</a><br> </div> <div class="menu" ID="View" style="width: 155;" level="0"> <a href="JavaScript: void 0;" onMouseOver="JavaScript: openMenuAbsolute( document.all.View_Toolbars, document.all.View.offsetLeft + document.all.View.clientWidth 1, document.all.View.offsetTop );"> Toolbars </a><br> <input type="checkbox" name="C1" value="ON"> <font color="#0000FF" size="2">Status Bar</font><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: openMenuAbsolute( document.all.View_ExplorerBar, document.all.View.offsetLeft + document.all.View.clientWidth 1, document.all.View.offsetTop + 43 );"> Explorer Bar </a><br> <hr> <a href="JavaScript: void 0;" onMouseOver="JavaScript: openMenuAbsolute( document.all.View_GoTo, document.all.View.offsetLeft + document.all.View.clientWidth 1, document.all.View.offsetTop + 70 );"> Go To </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Stop </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Refresh </a><br> <hr> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Text Size </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Encoding </a><br> <hr> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Source </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Scrip Debugger </a><br> <a href="JavaScript: void 0;" onMouseOver="JavaScript: hideLevel( 1 );"> Full Screen </a> </div> <div class="menu" ID="File_New" style="width: 115;" level="1"> <a href="JavaScript: void 0;">Window</a><br> <hr> <a href="JavaScript: void 0;">Message</a><br> <a href="JavaScript: void 0;">Post</a><br> <a href="JavaScript: void 0;">Contact</a><br> <a href="JavaScript: void 0;">Internet Call</a><br> </div> <div class="menu" ID="File_Send" style="width: 150;" level="1"> <a href="JavaScript: void 0;">Page by E-mail</a><br> <a href="JavaScript: void 0;">Link by E-mail</a><br> <a href="JavaScript: void 0;">Shortcut to Desktop</a><br> </div> <div class="menu" ID="View_Toolbars" style="width: 150;" level="1"> <a href="JavaScript: void 0;">Standard Buttons</a><br> <a href="JavaScript: void 0;">Address Bar</a><br> <a href="JavaScript: void 0;">Links</a><br> <a href="JavaScript: void 0;">Radio</a> <hr> <a href="JavaScript: void 0;">Customize</a> </div> <div class="menu" ID="View_ExplorerBar" style="width: 150;" level="1"> <a href="JavaScript: void 0;">Search</a><br> <a href="JavaScript: void 0;">Favorites</a><br> <a href="JavaScript: void 0;">History</a><br> <a href="JavaScript: void 0;">Folders</a> <hr> <a href="JavaScript: void 0;">Tip of the Day</a><br> <a href="JavaScript: void 0;">Discuss</a> </div> <div class="menu" ID="View_GoTo" style="width: 150;" level="1"> <a href="JavaScript: void 0;">Back</a><br> <a href="JavaScript: void 0;">Forward</a> <hr> <a href="JavaScript: void 0;">Home Page</a> <hr> </div> </body> </html>