Application Techniques



Implementing Tabs with JavaScript and DHTML

How to implement your own tab control on a page by using JavaScript and dynamic HTML (DHTML).

About this technique

Details

Category

HTML Client Techniques> JavaScript

Description

You'll learn about:

You can run this technique code from:

Related reading

See the chapter on advanced page topics in the Programmer's Guide

Setting up   Top of page

Because this technique involves DHTML, it's only appropriate when you're sure users will have browsers capable of handling it. That means version 4 (or later) of Netscape or Internet Explorer. And even then, it's tricky to implement for both browsers, due to their differing approaches to DHTML.

Images for rendering the tabs

The example uses six image files to make something that looks like a tab control:

Several HTML tables and DHTML layers are then required to fit together these images, along with the content of each tab.

Planning for browser support issues

The combination of tables and layers can create alignment complications when you're trying to support multiple browsers. The problems have to do with resizing the window.

In Internet Explorer, a layer in a table stays where it is when the window is resized, and the overall tab control remains aligned. In Netscape, the layer does not stay in the table and the result is a non-aligned tab control. By using a frameset to place the tab control's page in its own frame with specific dimensions, you can prevent resizing and avoid this problem.

About the frameset and pages

To implement the frameset and accompanying pages, this example uses the following files:

Coding the tabs   Top of page

The HTML in the frameset file looks like this. Note the fixed frame size for the tab control's page.

  <html> 
  <frameset rows="70,*" border=0> 
    <frame src="ImplementTabs.title.html" noresize scrolling=no> 
    <frameset rows="200,*" border=0> 
      <frameset cols="500,*"> 
        <frame src="ImplementTabs.html" noresize scrolling=no> 
        <frame src="ImplementTabs.pad.html"> 
      </frameset> 
      <frame src="ImplementTabs.pad.html"> 
    </frameset> 
  </frameset>     
  </html> 

And here's the code for the tab control's page itself.

  <HTML> 
  <HEAD> 
  <TITLE>Technique Example:  
  Implementing Tabs with JavaScript and DHTML</TITLE> 
  <script language="JavaScript"> 
   
     // This is the standard browser recognition setup. 
   
     browserCheck = ((navigator.appName == "Microsoft Internet Explorer")  
                   || (navigator.appName == "Netscape")) &&  
                   (parseInt(navigator.appVersion) >= 4) 
   
     // Create a variable with the name of the browser as 
     // its value. 
   
     browserName = navigator.appName; 
   
     // Due to the nature of this technique, most of the code 
     // needs to be conditionalized based on the browser the 
     // client is using.  For that reason, you should create a 
     // boolean variable that states whether the browser is  
     // Netscape or not.  You will refer back to this variable 
     // frequently in this technique. 
   
     doNetscape = (browserName.indexOf("Netscape") >= 0); 
   
     // If you are using Netscape, initialize the layers. 
     // If this was not conditionalized, Internet Explorer 
     // would throw errors here. 
   
     if (doNetscape) { 
        tab1_layer = new Layer(); 
        tab2_layer = new Layer(); 
        tab3_layer = new Layer(); 
     } 
   
  </script> 
  <style> 
   
     // Set up some styles that will be used in the layers 
     // and tables. 
   
  .div1 { 
      background-color : #C6C6C6; 
      padding-top:0; 
      clip:rect(0, 250, 75, 0); 
  } 
  all.testLayer { 
      border-width:0px; 
      margin-left : 0px; 
      margin-bottom:0px; 
      overflow:clip; 
      font-family : arial; 
  } 
  TD { 
      font-family : arial; 
  } 
  .CODETD { 
      font-family : courier; 
      font-size : 9pt; 
  } 
  </style> 
  <script> 
  <!-- 
   
     // Create a variable that will hold a reference 
     // to the currently active tab.  The first tab that 
     // is active when the page is loaded is by default, 
     // tab1, so you should set curTab equal to 1. 
   
     var curTab = 1; 
   
     // The getTab() method is responsible not only 
     // for switching the active tab but also for switching 
     // the top image to show the active tab's appropriate 
     // header graphic.  getTab() takes three parameters: 
     //   whichTab = The number of the tab to switch to. 
     //   whichLayer = A reference to the layer object to  
     //                switch to.  This is for Internet 
     //                Explorer: 
     //                  tab1_layer 
     // 
     //    whichNetLayer = A reference to the layer object  
     //                    to switch to.  This is for Netscape: 
     //                      document.tab1_layer 
     // 
     // Here you can start to see the different syntax for the 
     // different browsers. 
   
  function getTab(whichTab,whichLayer,whichNetLayer) { 
   
     // The first thing that you must do is switch the  
     // tab header image to the new tab header image. 
     // Set a variable, curSrc, equal to the 
     // source value of the tab image, document.images[0] 
   
     curSrc = document.images[0].src; 
   
     // Before anything happens, check to see if the 
     // current tab is the same as the tab that was 
     // selected.  There is no need to do anything if  
     // the tab is already active. 
   
     if (curTab != whichTab) { 
   
        // Replace the number in the source string  
        // (curSrc) with the number of the tab you 
        // want to switch to (whichTab). 
   
        curSrc = curSrc.replace(curTab + ".jpg",whichTab + ".jpg"); 
   
        // Set the source of the tab image to its 
        // new source. 
   
        document.images[0].src = curSrc; 
   
        // Set the current tab equal to the selected 
        // tab. 
   
        curTab = whichTab; 
     } 
   
     // Now you need to actually switch the content, or  
     // the layer that contains the content.  Netscape 
     // and Internet Explorer have two different ways of 
     // accomplishing this so you can write two different  
     // functions, one for Netscape and one for IE. 
     // 
     // If the browser is Netscape, invoke getTabNet() 
     // and pass the correct layer reference to it.  Then  
     // stop the current function. 
   
     if (doNetscape) { 
      getTabNet(whichNetLayer); 
         return; 
     } 
   
     // Check to see if the current layer object is the  
     // same as the selected layer object.  Do not proceed  
     // if that is the case.  curLayer is initialized 
     // at the very end of this file. 
   
     if (curLayer == whichLayer) 
        return; 
    
     // Set the visibility of the current layer object 
     // to 'hidden' and the visibility of the selected 
     // layer object to 'visible'. 
   
     curLayer.style.visibility = 'hidden'; 
     whichLayer.style.visibility = 'visible'; 
   
     // Set the current layer object equal to the  
     // selected layer object. 
   
     curLayer = whichLayer; 
   
     // Remove the focus from the tab image. 
   
     document.images[0].blur(); 
  } 
   
     // The getTabNet() function has the  
     // same functionality as the getTab()  
     // function with slightly different 
     // syntax to accommodate Netscape. 
   
  function getTabNet(whichNetLayer) { 
   
     // Check to see if the current layer 
     // is the same as the selected layer. 
     // curNetLayer is initialized at the 
     // end of this file. 
   
     if (curNetLayer == whichNetLayer) { 
        return; 
     } 
   
     // Hide the current layer. 
   
     curNetLayer.visibility = 'hide'; 
   
     // Show the selected layer. 
   
     whichNetLayer.visibility = 'show'; 
   
     // Set the current layer equal to the 
     // selected layer. 
   
     curNetLayer = whichNetLayer;    
  } 
   
  //--> 
  </script> 
   
      <!--     
          Here is the Image Map that is used to trigger the tab clicks. 
          When you click on a hot spot, the getTab() function is invoked 
          with 3 arguments: the number of the tab to get, an object 
           reference to the correct layer in IE format, and an object 
          reference to the correct layer in Netscape format.  
      -->  
              
  <map name="TABAREAS"> 
  <area shape="rect" coords="8,0,74,21" href="javascript:getTab(1,tab1_layer,document.tab1_layer)"> 
  <area shape="rect" coords="76,2,140,21" href="javascript:getTab(2,tab2_layer,document.tab2_layer)"> 
  <area shape="rect" coords="141,3,208,21" href="javascript:getTab(3,tab3_layer,document.tab3_layer)"> 
  </map> 
  </HEAD> 
  <BODY bgcolor="#ffffff" TEXT="#086B8C" LINK="#086B8C" VLINK="#086B8C" ALINK="#086B8C"> 
  <h1><font color="#ffffff">Hidden PlaceHolder</font></h1> 
  <script> 
     
     // This specific example uses form elements. 
     // In order to get it to work correctly for IE, you can 
     // specify one form that surrounds the entire HTML portion 
     // of the document. But for Netscape, you need to specify 
     // a new form in each layer.   
     // 
     // If the browser is IE, write a form tag. 
   
     if (!doNetscape) 
        document.write("<form>"); 
  </script> 
  <table border=0 cellpadding=0 cellspacing=0> 
  <tr> 
  <td colspan=3 height=40 valign=bottom  bgcolor="white"><center> 
  <img border=0 src="tab1.jpg" name="TAB" usemap="#TABAREAS"> 
  </center></td> 
  </tr> 
  <tr> 
  <td rowspan=2 align=right valign=bottom bgcolor="#C6C6C6"> 
  <img src="tabLftSide.jpg" height=85> 
  </td> 
   
  <td height=65 valign=top bgcolor="#C6C6C6"> 
  <script> 
  <!-- 
   
     // This is the layer initialization for the first of the three 
     // layers used in this example.   
     // 
     // If the browser is Netscape, create a string with the <layer>  
     // tag and the appropriate attributes.  Notice that a form tag is 
     // also written here. 
   
     if (doNetscape) { 
        writeString = "<layer id=\"tab1_layer\" visibility=\"show\" height=70 overflow=clip"; 
        writeString += " top=90 left=12 width=301 bgcolor=#C6C6C6 "; 
        writeString += "position=absolute zIndex=-1 class=\"testLayer\"><form>"; 
     } 
   
     // Otherwise, create the string with the <div> tag and its 
     // appropriate attributes. 
   
     else {  
        writeString = "<div id=\"tab1_layer\" style=\"position:absolute;visibility:'visible'\""; 
        writeString += " top=80 left=25 width=100 class=\"div1\">" 
     } 
   
     // Write the string to the page. 
   
     document.write(writeString); 
  //--> 
  </script> 
   
      <!--     
          This is the actual content of the first 
          layer.  This code is the same for both  
          browsers.  Just plain HTML. 
      --> 
       
  <table border=0 bgcolor="#C6C6C6"> 
  <tr> 
  <td width=30></td> 
  <td></td> 
  <td><BR>This is the first tab page. 
  <BR>Click the other tabs to see the controls they contain.</td> 
  <td width=30 bgcolor="#C6C6C6"></td> 
  </tr></table> 
  <script> 
  <!-- 
   
     // If the browser is Netscape, close the current form and 
     // the current layer.  Then open a new layer the same way 
     // as before.  Initialize this layer to be hidden, as 
     // opposed to the first, which was visible. 
   
     if (doNetscape) { 
        writeString = "</form></layer><layer id=\"tab2_layer\" bgcolor=\"#C6C6C6\" visibility=\"hide\""; 
        writeString += "  height=70 overflow=clip top=90 left=12 width=301 "; 
        writeString += "class=\"testLayer\" zIndex=-1 position=absolute><form>"; 
     } 
   
     // Otherwise, close the current DIV, and open a new one the 
     // same way as before.  Initialize this DIV to be hidden, 
     // as opposed to the first, which was visible. 
   
     else { 
        writeString = "</div><div id=\"tab2_layer\" style=\"visibility:'hidden';position:absolute;'\"";  
        writeString += " top=80 left=25 width=100 class=\"div1\">"; 
     } 
   
     // Write the string to the document. 
   
     document.write(writeString); 
  //--> 
  </script> 
   
      <!--  
          Here is the content of the second tab. 
      -->  
   
  <BR> 
  <table border=0 bgcolor="#C6C6C6"> 
  <tr> 
  <td width=30 bgcolor="#C6C6C6"></td> 
  <td bgcolor="#C6C6C6">Name:</td> 
  <td bgcolor="#C6C6C6"><input type="text" name="uName" size=15></td><td width=30></td> 
  </tr></table> 
  <script> 
  <!-- 
   
     // Repeat the same procedures for the third tab. 
   
     if (doNetscape) { 
        writeString = "</form></layer><layer id=\"tab3_layer\" bgcolor=\"#C6C6C6\" visibility=\"hide\""; 
        writeString += " height=70 overflow=clip top=90 left=12 width=301 "; 
        writeString += "position=absolute zIndex=-1 class=\"testLayer\"><form>"; 
     } 
     else { 
        writeString = "</div><div id=\"tab3_layer\" style=\"visibility:'hidden';position:absolute;'\"";  
        writeString += " top=80 left=25 width=100 class=\"div1\">"; 
     } 
   
     // Write the string to the page. 
   
     document.write(writeString); 
  //--> 
  </script> 
   
      <!-- 
          Here is the content for the third tab. 
      --> 
   
  <BR> 
  <table border=0 bgcolor="#C6C6C6"> 
  <tr><td width=30 bgcolor="#C6C6C6"></td> 
  <td bgcolor="#C6C6C6">Choice A:</td> 
  <td bgcolor="#C6C6C6"><input type="radio" name="choices" value="a"></td><td width=30></td></tr> 
  <tr><td></td> 
  <td bgcolor="#C6C6C6">Choice B:</td> 
  <td bgcolor="#C6C6C6"><input type="radio" name="choices" value="b"></td><td></td></tr> 
  <script> 
  <!-- 
   
     // Finally, close everything that is still open. 
   
     if (doNetscape) 
        document.write("</form></table></layer>"); 
     else  
        document.write("</table></div>"); 
  //--> 
  </script> 
  </td> 
  <td rowspan=2 align=left valign=bottom bgcolor="#C6C6C6"> 
  <img src="tabRtSide.jpg" height=85> 
  </td> 
  </tr> 
  <tr> 
  <td valign=bottom bgcolor="#C6C6C6"> 
  <img src="tabBottom.jpg"> 
  </td> 
  </tr> 
  </table> 
  <script> 
  <!-- 
   
    // If the browser is IE, close that form that you 
    // opened at the beginning of this page. 
   
    if (!doNetscape) 
        document.write("</form>"); 
  //--> 
  </script> 
  <script> 
  <!-- 
   
     // Initialize the curLayer and curNetLayer 
     // variables to the first layer object using  
     // the correct syntax. 
   
     var curLayer = tab1_layer; 
     var curNetLayer = document.tab1_layer; 
  //--> 
  </script> 
   
  </BODY> 
  </HTML> 






Copyright © 2000, SilverStream Software, Inc. All rights reserved.