Web DevCenter    
 Published on Web DevCenter (http://www.oreillynet.com/javascript/)
 See this if you're having trouble printing code examples


Cross-Browser Layers: Part 2

by Budi Kurniawan
06/22/2001

Editor's Note: When we published part one of this two-part series on cross-browser layers, a couple readers posted Talk Back messages questioning the timelines of content that discusses how to use layers for older browsers -- especially because Netscape 6 and Internet Explorer 5 now support layers in accordance with the new W3C standards. In essence, the author responded by saying that it's too early to stop supporting the older browsers.

As a result of this discussion, I asked the author to make some adjustments to the second part in the series before publishing. The following text includes those changes. In a sense, I think the dialogue from the previous article represents the larger discussion about coping with evolving standards.

Displaying and hiding a layer

Normally, all layers in your page are hidden by default. Only when the user does something, such as moving the mouse pointer over an image or a hyperlink, will the layer show up. If the user does something else, say move to another image, you might want to hide the first layer and display the second one. In a nutshell, layer programming is just the art of displaying and hiding layers at the right time.

As mentioned in part one of this article, you need to first detect the browser type and version. You can use the navigator.appName property to check the browser type (Netscape or Microsoft), but then in addition to the browser type, you still need to check the version. There is an easier way of doing this. In Netscape browsers that understand layers (such as Netscape Navigator 4.x), the document object contains the layers collection. On the other hand, in Internet Explorer 4 and above, the document object contains all. With this, you have the information you need.

The code in Listing 1 shows some JavaScript that can detect whether or not a browser can support layers.


Listing 1: Detecting browser layers support

<script language="JavaScript">
var NN4 = document.layers? true : false; //Netscape Navigator 4.x.
var IE4 = document.all? true : false; // IE version 4 and above.
</script>

In the code in Listing 1, the variable NN4 will only be "true" if the browser is Netscape Navigator version 4.x, and the variable IE4 will only be "true" if the browser is Internet Explorer version 4 and above. If both NN4 and IE4 are "false," you know that the user is using a browser that does not support layers. Checking the values of NN4 and IE4 allows you to force the browser to execute the appropriate code. For instance, to display a layer you will have something similar to the code in Listing 2.


Listing 2: Displaying a layer

<script language="JavaScript">
function display() {
  if (NN4) {
    // the code to display a layer in NN 4.x
  }
  else if (IE4) {
    // the code to display a layer in IE 4 and above
  }
}
</script>

The display function will later be triggered by a designated event when you have decided how you should display your layer and have the complete HTML file. The function is still safe even in a browser that does not understand layers because in that browser, the code in the two if blocks will never be executed.

Comment on this articleWe welcome your comments on this article.
Post your comments

Related Articles:

Cross-Browser Layers, Part One

Related Books:

Dynamic HTML: The Definitive Reference

HTML and XHTML: The Definitive Guide 4th Edition

JavaScript: The Definitive Guide, 3rd Edition

Cascading Style Sheets: The Definitive Guide

To control the visibility of a layer, you need to know how to refer to the layer from your script and how to change the value of the visibility property of that layer. In Netscape Navigator 4.x, a layer is accessed by its name, therefore the reference format would be as follows.

document.layerName

However, layers are also stored as arrays of the document object, so you can use array indexing and naming techniques to access that layer object:

document.layers[n]

or

document.layers[layerName]

To change the visibility property value in Netscape Navigator 4.x, you can use the following code.

document.layers[layerName].visibility = "show";

In Internet Explorer 4 and above, the Document Object Model provides a way to transcend any hierarchical structure of nested style objects with a document property called all. A reference to document.all exposes all named objects in the document. To that reference beginning, you add the name of the object defined in the document, plus a further reference to the style property, according to the following format.

document.all.objectName.style

And to access the visibility property, use this format.

document.all.objectName.style.visibility

With this in mind, displaying a layer can be done in only one line of code in both browsers. The code in Listing 3 is working code for displaying a layer.


Listing 3: Code for displaying a layer in both Netscape and Microsoft browsers

function display() {
  if (IE4) {
    document.all[layerName].style.visibility = "visible";
  }
  else if(NN4) {
    document.layers[layerName].visibility = "show";
  }
}

To hide a layer, you need to set the visibility property value to "hidden". Like the display function, the hide function to hide layers would have two sets of code, one for Navigator and one for Internet Explorer. Listing 4 displays the code for hiding a layer.


Listing 4: Hiding a layer

function hide() {
  if (IE4) {
 .   document.all[layerName].style.visibility = "hidden";
  }
  else if(NN4) {
    document.layers[layerName].visibility = "hidden";
  }
}

Now that you have the function for displaying and hiding layers, you need an event handler that will trigger the display and hide functions. The event handler is just an ordinary event handler. For example, the following hyperlinks respectively display and hide the layer on the page when the user moves the mouse pointer over them.


<a href="javascript:void()" onMouseOver='display()'>Display</a>
<br />
<a href="javascript:void()" onMouseOver='hide()' >Hide</a>

Hiding layers from old browsers

As mentioned above, browsers before version 4 of Netscape Navigator and Internet Explorer don't understand the <div> tag, so any <div> tag in the page will be ignored. However, it does not mean older browsers will ignore what lies between the <div> and </div> tags. Consider a layer that you create as a page division, like the following.

<div id="MyLayer" style="LEFT:0px; POSITION:absolute; TOP:0px; VISIBILITY:hidden; Z-INDEX:0">
<form method="POST" action="verify.asp">
<input type=text name="userName">
<br /><input type=text name="password">
<br /><input type=submit>
</div>

An older browser will ignore the <div> tags, but will still display the form. This is of course an unexpected result. A way to get around this is to generate the layer on the fly for <div>-aware browsers. The code is given in Listing 5.


Listing 5: Hiding layers from old browsers

<div id="layer1" style="left:0px; position:absolute; top:0px; visibility:hidden; z-index:0">

<script language="JavaScript">
  if (NN4 || IE4) {
    document.write("<table border=\"1\" bgcolor=\"white\" cellspacing=\"0\" cellpadding=\"0\">");
    document.write("<tr><td>");
    document.write("<table>");
    document.write("<tr><td><a href=\"Product.html\">Product</a></td></tr>");
    document.write("<tr><td><a href=\"Search.html\">Search</a></td></tr>");
    document.write("<tr><td><a href=\"Order.html\">Order</a></td></tr>");
    document.write("<tr><td><a href=\"Help.html\">Help</a></td></tr>");
    document.write("</table>");
    document.write("</td></tr>");
    document.write("</table>");
  }
</script>
</div>


Yes, it is a tedious task to write the HTML tags in the layer with numerous document.write methods. However, this seems to be the only sure solution.

Using layers in an HTML page

After you have learned how layers can be made cross-browser-compatible, it is time to present a complete HTML file that uses layers. Listing 6 shows such an example. The code shows a page containing a layer and code to control the layer visibility in browsers that are mature enough to understand <div> tags.


Listing 6: A complete example of using layers

<html>
<head>
<title>Using Layers</title>
<script language="JavaScript">
<!--
var NN4 = document.layers? true : false;
var IE4 = document.all? true : false;
var left = 140;
var top = 50;

function display() {
  if (IE4) {
    document.all['layer1'].style.pixelLeft = left;
    document.all['layer1'].style.pixelTop = top;
    document.all['layer1'].style.visibility = "visible";
  }
  else if(NN4) {
    document.layers['layer1'].left = left;
    document.layers['layer1'].top = top;
    document.layers['layer1'].visibility = "show";
  }
}

function hide() {
  if (IE4) {
    document.all['layer1'].style.visibility = "hidden";
  }
  else if(NN4) {
    document.layers['layer1'].visibility = "hidden";
  }
}
// -->
</script>
</head>
<body>
<a href="javascript:void()" onMouseOver='display()'>Display</a>
<br /><a href="javascript:void()" onMouseOver='hide()'>Hide</a>

<div id="layer1" style="left:0px; position:absolute; top:0px; visibility:hidden; z-index:0">

<script language="JavaScript">
<!--
  if (NN4 || IE4) {
    document.write("<table border=\"1\" bgcolor=\"white\" cellspacing=\"0\" " +    
      " cellpadding=\"0\">");
    document.write("<tr><td>");
    document.write("<table>");
    document.write("<tr><td><a href=\"Product.html\">Product</a></td></tr>");
    document.write("<tr><td><a href=\"Search.html\">Search</a></td></tr>");
    document.write("<tr><td><a href=\"Order.html\">Order</a></td></tr>");
    document.write("<tr><td><a href=\"Help.html\">Help</a></td></tr>");
    document.write("</table>");
    document.write("</td></tr>");
    document.write("</table>");
  }
// -->
</script>
</div>
</body>
</html>


Note that the display function in Listing 6 has been modified to include the layer position on the page.

function display() {
  if (IE4) {
    document.all['layer1'].style.pixelLeft = left;
    document.all['layer1'].style.pixelTop = top;
    document.all['layer1'].style.visibility = "visible";
  }
  else if(NN4) {
    document.layers['layer1'].left = left;
    document.layers['layer1'].top = top;
    document.layers['layer1'].visibility = "show";
  }
}

Again, the properties that control the position are different. In IE 4 and above, the properties are called pixelLeft and pixelTop; in Netscape Navigator 4.x, the properties are called left and top.

Figures 1 and 2 shows the code in Listing 6 in action. Figure 1 shows the initial page when it is first loaded. The layer is hidden.

The initial page.
Figure 1: The page when the layer is hidden.

When you move the mouse pointer over the Display link, the layer will be displayed, as shown in Figure 2.

The page when the mouse point is moved over the display link.
Figure 2: The page when the layer is visible.

To hide the layer again, move the mouse over the Hide link.

Using layers as sub-menus

You probably have more than one layer in your page. For instance, if you use layers to display sub-menus for each menu item, you would have a different layer for each menu item. Four menu items mean four different layers. Predictably, your JavaScript code would also be more complex. Normally, there is only one layer visible at a time, so you need to hide the other layers before displaying a layer.

The easiest way is to hide all layers in the hide function prior to displaying any layer. Each event handler for displaying a layer will then have to invoke two functions, the hide function to hide all layers and the display function to display the corresponding layer. Listing 7 gives you the code for an online computer magazine that provides four topics: HTML, JavaScript, Java, and ASP. Each topic has four articles. To read an article, you need to click the corresponding link, or you can choose the article directly from the layer that appears.

Unlike the code in Listing 6 where the layer position is fixed, the code in Listing 7 displays a layer at the position relative to the mouse when the mouse pointer is over a hyperlink. To know the position of the mouse, you need to capture the MOUSEMOVE event using the following statements.

if (NN4)
  document.captureEvents(Event.MOUSEMOVE);
document.onmousemove = setMouseCoordinate;

And then, set the left and top variables with the setMouseCoordinate function (see Listing 7).


Listing 7: Using layers as sub-menus

<html>
<head>
<title>Using Layers as Sub-menus</title>
<script language="JavaScript">
<!--
var NN4 = document.layers? true : false;
var IE4 = document.all? true : false;
var left;
var top;

function display(layerName) {
  if (IE4) {
    document.all[layerName].style.pixelLeft = left + 25;
    document.all[layerName].style.pixelTop = top;
    document.all[layerName].style.visibility = "visible";
  }
  else if(NN4) {
    document.layers[layerName].left = left + 25;
    document.layers[layerName].top = top;
    document.layers[layerName].visibility = "show";
  }
}

function hide() {
  if (IE4) {
    document.all['layer1'].style.visibility = "hidden";
    document.all['layer2'].style.visibility = "hidden";
    document.all['layer3'].style.visibility = "hidden";
    document.all['layer4'].style.visibility = "hidden";
  }
  else if(NN4) {
    document.layers['layer1'].visibility = "hidden";
    document.layers['layer2'].visibility = "hidden";
    document.layers['layer3'].visibility = "hidden";
    document.layers['layer4'].visibility = "hidden";
  }
}

function setMouseCoordinate(e) {
  if (NN4) {
    left = e.pageX;
    top = e.pageY;
  }
  else if (IE4) {
    left = document.body.scrollLeft + event.clientX
    top = document.body.scrollTop + event.clientY
  }
}

if (NN4)
  document.captureEvents(Event.MOUSEMOVE);
document.onmousemove = setMouseCoordinate;

// -->
</script>
</head>
<body>
<a href="HTML.html" onMouseOver='hide(); display("layer1")'>HTML</a><br />
<a href="JavaScript.html" onMouseOver='hide(); display("layer2")'>JavaScript</a><br />
<a href="Java.html" onMouseOver='hide(); display("layer3")'>Java</a><br />
<a href="ASP.html" onMouseOver='hide(); display("layer4")'>ASP</a><br />

<div id="layer1" style="LEFT:0px; POSITION:absolute; TOP:0px; VISIBILITY:hidden; Z-INDEX:0">
<script language="JavaScript">
<!--
  if (NN4 || IE4) {
    document.write("<table border=\"1\" bgcolor=\"white\" cellspacing=\"0\" CELLPADDING=\"0\">");
    document.write("<tr><td>");
    document.write("<table>");
    document.write("<tr><td><a href=\"HTML/intro.html\">Introduction To HTML</a></td></tr>");
    document.write("<tr><td><a href=\"HTML/advtags.html\">Advanced Tags</a></td></tr>");
    document.write("<tr><td><a href=\"HTML/CSS.html\">CSS Overview</a></td></tr>");
    document.write("<tr><td><a href=\"HTML/DHTML.html\">Dynamic HTML</a></td></tr>");
    document.write("</table>");
    document.write("</td></tr>");
    document.write("</table>");
  }
// -->
</script>
</div>

<div id="layer2" style="left:0px; position:absolute; top:0px; visibility:hidden; z-index:0">
<script language="JavaScript">
<!--
  if (NN4 || IE4) {
    document.write("<table border=\"1\" bgcolor=\"white\" cellspacing=\"0\" CELLPADDING=\"0\">");
    document.write("<tr><td>");
    document.write("<table>");
    document.write("<tr><td><a href=\"JS/intro.html\">Introduction To JavaScript</a></td></tr>");
    document.write("<tr><td><a href=\"JS/array.html\">Arrays</a></td></tr>");
    document.write("<tr><td><a href=\"JS/JSSpec.html\">Specifications</a></td></tr>");
    document.write("<tr><td><a href=\"JS/advJS.html\">Advanced JavaScript</a></td></tr>");
    document.write("</table>");
    document.write("</td></tr>");
    document.write("</table>");
  }
// -->
</script>
</div>

<div id="layer3" style="left:0px; position:absolute; top:0px; visibility:hidden; z-index:0">
<script language="JavaScript">
<!--
  if (NN4 || IE4) {
    document.write("<table border=\"1\" bgcolor=\"white\" cellspacing=\"0\" cellpadding=\"0\">");
    document.write("<tr><td>");
    document.write("<table>");
    document.write("<tr><td><a href=\"Java/intro.html\">Introduction To Java</a></td></tr>");
    document.write("<tr><td><a href=\"Java/applet.html\">Writing Applets</a></td></tr>");
    document.write("<tr><td><a href=\"Java/JSP.html\">Introduction to JSP</a></td></tr>");
    document.write("<tr><td><a href=\"Java/EJB.html\">Programming EJB</a></td></tr>");
    document.write("</table>");
    document.write("</td></tr>");
    document.write("</table>");
  }
// -->
</script>
</div>

<div id="layer4" style="left:0px; position:absolute; top:0px; visibility:hidden; z-index:0">
<script language="JavaScript">
<!--
  if (NN4 || IE4) {
    document.write("<table border=\"1\" bgcolor=\"white\" cellspacing=\"0\" cellpadding=\"0\">");
    document.write("<tr><td>");
    document.write("<table>");
    document.write("<tr><td><a href=\"ASP/intro.html\">Introduction To ASP</a></td></tr>");
    document.write("<tr><td><a href=\"ASP/session.html\">The Session Object</a></td></tr>");
    document.write("<tr><td><a href=\"ASP/FileUpload.html\">File Upload</a></td></tr>");
    document.write("<tr><td><a href=\"ASP/asa.html\">The Global.asa file</a></td></tr>");
    document.write("</table>");
    document.write("</td></tr>");
    document.write("</table>");
  }
// -->
</script>
</div>

</body>
</html>


Figure 3 shows the code in Listing 7 when loaded in a browser.

The code as seen in a browser.
Figure 3: Displaying a layer as a submenu.

Summary

In this article you have seen how to write cross-browser layers. You have also learned how the <div> tag plays an important role in the layering technology. The pieces of code in this article show how to use layers for creating sub-menus.

Budi Kurniawan is a senior J2EE architect and author.


Return to the JavaScript and CSS DevCenter.

Copyright © 2009 O'Reilly Media, Inc.