Layered Interfaces

If your interface won't fit properly in a reasonably sized dialog box, you can break it into two or more dialog boxes, or you can create one multipart dialog box that is essentially several dialog boxes' worth of interface sharing one space. Multipart dialog boxes are used throughout the Dreamweaver interface. They're created by putting different form elements on different layers, and using JavaScript to alternately show and hide each layer. In some dialog boxes, the layered effect is done almost invisiblythe Preferences and Site Definition interfaces, for instance,display different contents depending on which category is chosenan effect easily created by showing and hiding layers (see Figure 10.11). In other dialog boxes, such as the Drag Layer behavior and Clean Up Word HTML command, the layers are a graphic presence, appearing like a stack of tabbed note cards (see Figure 10.12). In this section of the chapter, we'll be focusing mainly on the tabbed layer interface because it's more graphically challenging; but similar scripting techniques are involved in both kinds of interfaces.

Figure 10.11. Subtle layer-swapping can create interfaces like that seen in the Preferences dialog box.


Figure 10.12. The graphically presented "tabbed" layer interface as seen in other parts of the interface. (Mac OS X and Windows XP versions shown.)



Because neither the Preferences nor the Site Definition dialog box is written as an extension, it's impossible to tell for sure how their content-swapping interfaces have been created. However, it seems logical to assume that some sort of layer scripting is involved.


There really are no special API tools for working with layered interfaces; there are only common sense and some slightly sneaky scripting.

There are two general ways to approach the tabbed layer interface: the easy way and the hard way. Although the basic layer setup is the same for both, the scripting setup is drastically different, as are the structural requirements for how the layers are put together. The simple way is quick and easy to set up, but it offers only a fraction of the power and flexibility of the hard way. We'll look at both, beginning with the simpler.

Layers the Simple Way

A simple tabbed layer interface is created from a layout built with layers and a JavaScript function controlling layer visibility.

Creating the Layers

The first step in creating a tabbed interface is assembling various interface elements into layers. As with any layered extension interface, it's not crucial how the layers are coded. Both <div> and <span> tags will work, and there are no special restrictions except the general warning that layers may not display exactly the same across platforms.

If you're creating a tabbed layer interface, the structure of your layers gets a bit more complicated. The "tabbed" look of a layered interface is created from the graphics employed in the various layers. Figure 10.13 shows a diagram of the layer structure utilized in the Macromedia extensions (such as the Drag Layer dialog box shown in Figure 10.12). From this diagram, you can see that a large layer containing a background graphic creates the main 3D note card effect. In front of this layer, each "page" of interface elements consists of five layers: the contents layer and four smaller layers creating the tab effect. These four layers consist of one layer to hold the " unselected " tab graphic, one to hold the "selected" tab graphic, one to hold the title that appears in the tab, and one to hold an invisible image field form element. The JavaScript for showing and hiding the layers is called onClick from that invisible button. Image files are available for all of these graphic needs, all stored in the Configuration/Shared/MM/Images folder. Table 10.5 lists the different images available, along with their uses. (Note that most are platform-specific, so you must target your tabbed layer interface to one platform or another.)

Figure 10.13. The tabbed layer interface effect, diagrammed to show layer stacking.


Table 10.5. Macromedia Images Available for Use with Tabbed Layer Interfaces (All Can Be Found in Configuration/Shared/MM/Images)



Target Platform


Non-selected tab



Selected tab



Non-selected tab












Non-selected tab

Mac OS X


Selected tab


















Non-selected tab

Win XP


Selected tab















Selected tab



Although you are free to use any graphics you choose if you want your tabbed layers to blend seamlessly with the rest of the Dreamweaver interface, you should use the Macromedia standard graphics. If you find that the dimensions of any of these graphics don't suit your interface needs, you can make duplicates and tweak them in an image-editing program, or you can just stretch and squash the originals by changing their width and height attributes in your extension file. (Warning: This may result in visual distortions.)

How you create the layers is not crucial as long as you follow certain conventions in naming them (covered in the next section) and stick to the general structure diagrammed in Figure 10.13. You can create your layered page layout by hand-coding or by working in Dreamweaver Design view.

Scripting the Layered Interface

The key to a good, layered interface (tabbed or plain) is the scripting that hides and shows the various layers. Ultimately, it's up to you to create a script that works best for you; but you can start from the sample code here.

Generally, only one layer (or one set of content) is visible at a time. The key to accomplishing this is to create a global variable that holds the name of the visible layer; and to create a function for showing one layer and hiding all others. Because any layer in the interface should be able to call this function, each layer must pass its name to the function as a parameter so that Dreamweaver knows which layer to make visible when the function runs. The basic code structure is like this:

 var gCurrentLayer="page1";//this is the name of the currently visible page  function bringMeForward(myName) {//each layer passes its own name as a parameter  //if the layer that called the function (myName) is already visible, stop  //otherwise, make that layer (myName) visible  //make the layer that's currently visible (gCurrentLayer) invisible  //set gCurrentLayer to myName  } 

For a non-tabbed layered interface (like the Preferences or Site Definition dialog box), the fleshed-out version of the code looks like this:

 var gCurrentLayer="page1";  function bringMeForward(myName) {  //if the layer that called the function (myName) is already visible, stop  if (gCurrentLayer==myName) {     return;     }  //otherwise, make that layer (myName) visible  eval("document."+myName+".visibility=visible");  //make the layer that's currently visible (gCurrentLayer) invisible  eval("document."+gCurrentLayer+".visibility='hidden'");  //set gCurrentLayer to myName  gCurrentLayer=myName;  } 

The eval() function helps you construct the DOM accessing statement ( document.myForm.myLayer.visibility=visible ) to accommodate whatever layers have been defined as myName and gCurrentLayer . As long as the names of your layers are legal (no special characters , and so forth), it doesn't matter what you have named them for this to work.

For a tabbed layer interface, the code has to be more complex because several layers are being shown and hidden at a time (the content layer, the layer containing the selected tab graphic, and so forth). To accommodate this complexity and make your scripting task much easier, name the layers according to a set naming scheme that incorporates a base name and consistent prefixes or suffixes. If the layers that comprise the first tabbed layer are named page1Main , page1Tab , page1TabSel , page1Title , and page1Button , for instance, the fleshed-out function will look like this:

 var gCurrent="page1";  function bringMeForward(myShortName){  //if the layer that called the function (myShortName) is already visible, stop  if (gTab == myShortName) {     return;     }  //otherwise, make that layer (myShortName) visible  eval("document."+myShortName+"Main.visibility='visible'");  eval("document."+myShortName+"TabSel.visibility='visible'");  //make the layer that's currently visible (gCurrentLayer) invisible  eval("document."+gCurrent+"Main.visibility='hidden'");  eval("document."+gCurrent+"TabSel.visibility='hidden'");  //set gCurrent to myShortName  gCurrent=myShortName;  } 


Don't forget: Whenever you design an interface in layers, you'll need to use findObject() or some other equivalent functionto access the form elements. Link to UI.js or another shared file containing findObject() , or copy the function into your extension file.


Thanks to Andrew Wooldridge's QuickTime object extension, from which I adapted this function code.

Each function call to this function must then pass only its base name (for example, page1 ) to the function. The function will construct all other names by adding various suffixes ( Main , Tab , TabSel , and so forth) to this base; and the eval() statement will hide or show all layers associated with the same base name.


The layer terminology can get confusing here. Because, in a tabbed interface, multiple <div> or <span> elements go to make up each tab, Macromedia's convention is to refer to each <div> or <span> element as a layer, and each tabbed unit as a page. Thus, page1 refers to five layers.

Layers the Fancy Way

Now for the more complex and powerful way to set up the tabbed interface. This is the method used in the standard Dreamweaver extensions. It involves utilizing custom TabControl class objects, as well as custom page objects defined according to a specific set of rules. Setting up to use this system is much more of an undertaking than just writing the simple script shown above. But you get a payoff in the form of much more flexible functionality if you're willing to put some work in up front.

Creating the Layers

Because the layers in this kind of interface must work with predefined TabControl objects, the requirements for constructing them are more exact. This is especially true of the layers that create the tabbed effect. You have much more freedom in constructing the content layers (the layers containing the actual form elements). The safest way to begin constructing the interface is to copy the existing code for the tab layers from one of the standard extensions. These include Commands/Clean Up Word HTML.htm, Behaviors/Actions/Drag Layer.htm, and Commands/Insert Nav Bar.htm. You can also retype the code from here, if you like. The following style information should be added to your extension file's <head> section:

 <style type="text/css">  .pageBg { position:absolute; left:18px; top:21px; width:10px; height:10px; z-index:1; graphics/ccc.gif visibility:hidden; }  .tabLayer { position:absolute; top:0px; width:70px; height:20px; z-index:8; visibility: graphics/ccc.gif hidden ;}  .tabInnerLayer { position:absolute; width:75px; height:23px; z-index:8; left: 0px; top: graphics/ccc.gif 0px; visibility:inherit ;}  .tabLabelLayer { position:absolute; width:69px; height:1px; z-index:8; left: 0px; top: graphics/ccc.gif 5px; visibility:inherit; text-align:center }  </style> 

And the following code to create the tab layers should be added to the <body> section:

 <div class="pageBg" style="visibility:visible; left:4px; ">    <img name="tabBgWin" width="335" height="290" src="../Shared/MM/Images/tabBgWin335x290. graphics/ccc.gif gif">  </div>  <div id="Tab0" class="tabLayer" style="left: 8px; ">    <div class="tabInnerLayer"> <img src="../Shared/MM/Images/tabBg.gif"> </div>    <div id="Tab0Sel" class="tabInnerLayer" style="visibility:hidden">      <img src="../Shared/MM/Images/tabBgSel.gif"> </div>    <div name="Tab0Label" class="tabLabelLayer"></div>    <div class="tabInnerLayer">      <input type="image" src="../Shared/MM/Images/transparent.gif" width="69" height="21"> graphics/ccc.gif </div>   </div>  <div id="Tab1" class="tabLayer" style="left: 78px; ">    <div class="tabInnerLayer"> <img src="../Shared/MM/Images/tabBg.gif"> </div>    <div id="Tab1Sel" class="tabInnerLayer" style="visibility:hidden">      <img src="../Shared/MM/Images/tabBgSel.gif"> </div>    <div name="Tab1Label" class="tabLabelLayer"></div>    <div class="tabInnerLayer">      <input type="image" src="../Shared/MM/Images/transparent.gif" width="69" height="21"> graphics/ccc.gif </div>  </div> 

You can substitute different graphics as needed, as well as adjust the size of the background layer. You may also need to adjust the path to the image files, depending on where your extension is stored. But it's easiest and safest not to change any other names.


You can find a copy of the basic framework code for this tabbed layer interface on the book's companion web site:

As noted, you can create the page content layers without such coding restrictions, in Dreamweaver Design view or elsewhere. There are no special naming restrictions on content layers, either.

Scripting the Layers

Here's how this system works, in brief: You create a custom page class for each different kind of page in your interface, based on a model PageControl class provided in the shared files. You then link to the TabControlClass.js shared file, which defines a custom class for TabControl objects. In your extension file, you create an instance of a TabControl object, passing it your custom pages. You can then call on the various TabControl methods , each of which in turn will call on your custom page class's methods. You can also put custom functionality into the page class methods. Get it? If not, you will when you've seen it in action.

First, you'll create the custom page classes.

  1. . From the Macromedia Class folder, in the Shared folder, find and open the PageControlClass.js file. This file contains a template for defining page objects to be used with TabControls.

  2. Copy the code from this file, and paste it into your extension file.

  3. Throughout the new code in your extension file, wherever the name PageControl appears, replace it with a class name suitable to your project Pg1 , for instance, or BasicOptionsPage if you like to type long names.

  4. Repeat steps 2 and 3 for each type of "page" or set of content your interface will require. For a simple two-tab interface, for instance, you'll need to copy, paste, and rename two times. If you called the first class Pg1 , you might call the second Pg2 .

    Now you're ready to create an instance of the TabControl object and instantiate the custom page classes. This all needs to happen onLoad .

  5. . Create an initializeUI() function, called from the <body> tag. Enter the following code (names that can vary from file to file are shown in italic):

     function initializeUI() {  //Initialize the TabControl  //Pass the prefix used for the tab layers  T = new TabControl('Tab');  //Add tab pages  //by creating instances of your custom page objects  //Pass the layer name, and the page object)  T  .addPage('  basicPage  ', new  Pg1  (  "Basic"  ));  T  .addPage('  advPage  ', new  Pg2  (  "Advanced"  ));  //Initialize and display the tabs.  //(Optional: pass the name of a page to start on)  T.start('basicPage');  } 

    What does this code do? It creates a new TabControl object, called T herethis could be any name. Then, using the TabControl's addPage() method, it creates instances of your custom page objects. Finally, using the start() method, it sets up the tabs.

    Table 10.6 lists the methods of the TabControl object. Examining the addpage() method will reveal that in the previous code you're defining a content layer called basicPage as an instance of the Pg1 object and a content layer called advPage as an instance of the Pg2 object, and that the user will see the titles Basic and Advanced in the tabs for these layers.

    Table 10.6. Methods of the TabControl Object



    tab.getPageNum (thePageName)

    Returns the index in the pageList of the given page (starting from 0; returns 1 if the page can't be found).


    Returns the index in the pageList of the current page (starting from 1).


    Returns the total number of pages in the current group .

    tab.getPageObject (pageName)

    Returns the page object for the current page.

    tab.start( startpage )

    Initializes the tabs ( startPage is an optional parameter, indicating the page that should be loaded to start).


    Unloads the current page, and sends the lastUnload event to each of the pages in the current group.

    tab.addGroup (groupName, groupArray)

    Adds a group of pages to the list of possible groups ( theGroupArray is an array of page names). Returns true if successful; false if not.

    tab.showGroup (groupName)

    Selects a group to display (call refresh or showPage to view the new group).

    tab.addPage(pagename, pageObject)

    Adds a page and its corresponding object to the list of possible pages ( thePageName is the div id of the page).

    tab.showPage (pageName)

    Shows the page with the given name in the current group. (Calls the unload() method of the current page. Calls the canLoad() and load() methods of the new page.)

    tab.showPageNum (thePageNum)

    Shows the page with the given index in the current group.


    Shows the next page in the current group.


    Shows the previous page in the current group.


    Refreshes the tab display.

    tab.insertPage (thePageName, insertBeforeName, allowDuplicates)

    Dynamically inserts a page in the current group; insertBeforeName specifies the page to insert after, null = insert at end. (Calls refresh or showPage to view the new page.)

    tab.removePage (thePageName)

    Dynamically removes a page from the current group. (Calls refresh or showPage to remove the page from the display.)

    tab.update (theItemName)

    Calls the update() method in the page object for the current page.

    Now that there's a TabControl object and pages for it to act on, any of the methods shown in Table 10.6 can be used to create interface functionality.

  6. To create the basic show/hide behavior, for instance, just attach the showPage() method to the transparent image in the appropriate tab layer, passing the name of the layer to make visible, like this:

     <input type="image" src="../Shared/MM/Images/transparent.gif" width="69" height="21"  graphics/ccc.gif onClick="T.showPage('   basicPage   ')"  > </div> 

    If you examine the custom page classes you created, you'll see a variety of defined methods in each, most of which currently have no content. These methods are called by the TabControl object. Whatever code you place here will execute on cue. For instance, form data entered on one page can cause changes to occur in another page by setting those changes into motion as part of the new page's load() method. Like this (very simple) example, passing input from a text field on one page, to a text field on another:

     function Pg2_load() {  findObject("outputField").value=findObject("inputField").value;  } 

    To get an idea when each of these page class methods executes, uncomment the alerts in each; then try tabbing through the interface.

Simple versus Fancy Layers

As you can tell just from looking at the TabControl methods, interfaces created with the more complex method have much greater flexibility than those created the simple way. In addition to tabbing between content pages, pages can be dynamically generated, pages can be grouped to create customized content for every situation, and pages can act on one another.

Layered Interface Practice

This practice session will help familiarize you with tabbed layer interfaces. At the end of the session, you'll also have a handy framework file to use as stationery for other layered interfaces you want to build.

Task 1: Create a command file with one tabbed layer

Probably the hardest part of building a layered interface is keeping track of all those groups of layers, or pages. For this task, you'll create a command with a dialog box that consists of one page only. That involves one content layer and four layers to hold the graphics for the tabbing effect.

  1. In your text editor, create a new file. Save it in the Commands folder as Layer Practice.htm, and enter the following framework code:

     <html>  <head>  <title>Layer Practice</title>  <script language="JavaScript">  function myCommand() {  //command statements go here  }  function commandButtons() {  return new Array("OK","myCommand()","Close","window.close()");  }  </script>  </head>  <body>  <form name="myForm">  </form>  </body>  </html> 

    This creates a simple command with a very basic dialog box. Before proceeding to add layers, take a moment and try this command out, to make sure it works.

  2. Each tab of a tabbed layer interface looks like it's sitting on a notecard or other embossed rectangle. To create this effect, you need to place one of the tab images on a layer. Working either in Dreamweaver Design view or in your text editor, create a layer containing this graphic. The code for your <body> should now look like this (substitute whichever background graphic you choose, sizing your layer to match):

     <form name="myForm">  </form>  <div id="bgLayer" style="position:absolute; left:10px; top:50px; width:335; height:290; graphics/ccc.gif z-index:1">     <img src="../Shared/MM/Images/tabBgOSX335x290.gif" width="335" height="290">  </div> 

    If you try your command out at this point, the dialog box will look something like the one shown in Figure 10.14. (Note that the <form> tag must remain ! As you learned back in Chapter 5, command files display dialog boxes only if the body contains a formwhether or not the form is used for anything.)

    Figure 10.14. Layer Practice dialog box, with background layer (and graphic) in place.


  3. Now add another layer, containing a selected tab graphic (see Table 10.5 to choose the appropriate graphic for the job). Position the layer so that it looks like it's attached to the background layer along the top edge (like a tabbed notecard). Name the layer page1TabSel . Figure 10.15 shows what the layout might look like in Dreamweaver Design view.

    Figure 10.15. Layer Practice dialog box, with selected tab layer in place, as seen in Dreamweaver Design view.


  4. The layer for the non-selected tab should be exactly the same size and placement as the layer holding the selected tab. Create a new layer, identical to the page1TabSel layer. Replace the graphic with the appropriate non-selected tab graphic, and name the layer page1Tab . Adjust the z-index so that page1Tab is behind page1TabSel . (If you're working Dreamweaver Design view as you do this, you should now be able to use the visibility icons in the Layers panel to switch page1TabSel on and off, quickly checking the selected and non-selected states of this "page" of the dialog box.)

  5. For the title layer, create another layer. Name it page1Title . Position and size it to hold the title that you want to sit in your layer tab, and set its z-index to be in front of the other layers.Type PageOne in this layer. Figure 10.16 shows what this looks like in Dreamweaver Design view.

    Figure 10.16. The page1Title layer being added to the Layer Practice dialog box, as seen in Dreamweaver Design view.


  6. For the button layer, create another layer the same size and position as your selected and unselected tab layers. Name it page1Button . To create the button itself, if you're working in Dreamweaver Design view choose Insert > Form > Image Field and insert the space.gif image.If you're coding by hand, add the following code inside the button layer:

     <input type="image" src="../Shared/MM/Images/space.gif" width="7" height="7"> 

    Resize this image to match the size of the tab graphics.

  7. Finally, put some contents in your first page. Create another new layer, sized to fit within the area of the background image. Name this layer page1Main . Type a few words in it, or place a few form elements to simulate a working dialog box.

  8. There's your first page! Make sure all of your layers are visible, and then try it out. Figure 10.17 shows approximately what the resulting dialog box will look like. Figure 10.18 shows the various layers that went into making this tab, as they appear in the Dreamweaver Layers panel.

    Figure 10.17. The Layer Practice dialog box, with page1 in place.


    Figure 10.18. The Layers panel showing all of the layers that make up page1 of this interface.


Task 2: Create the second "page" of the interface

The steps for creating the second page, or tabbed layer, are the same as those for the first page, with the exception that the base name should be page2 , various tab layers should be moved over to the right to create that stack-of-notecards look, and the title and content should be different. Go ahead and create that second page now. If you're working in Dreamweaver, make life easy on yourself and temporarily hide the layers that belong to page1 so that they don't get in your way. Your resulting layout should look like the one shown in Figure 10.19.

Figure 10.19. The two-page interface of the Practice Layers command, in DreamweaverCode and Design view.


Task 3: Add the scripting to switch between layers Okay, you have two pages to your dialog box, and they look good when the right layers are visible and hidden. It's time to build that visibility control into the extension.

  1. Take a look at your layers one more time, to make sure they follow the naming convention. (If you're in Dreamweaver Design view, you can use the Layers panel for that.)

  2. When the dialog box first opens, page1 should be visible. Using the visibility attribute (if you're hand-coding) or the Layers panel (if you're working in Design view), hide page2Main and page2TabSel . Everything else should be visible. (Food for thought: Can you tell, after having worked with your multipage dialog box for a while, why only a few layers need to be shown and hidden to create the tabbed effect?)

  3. Add the following code to the <script> tag in the head section of your command file (new code is in bold):

     <script language="JavaScript">  function myCommand() {  //command statements go here  }  function commandButtons() {  return new Array("OK","myCommand()","Close","window.close()");  }  var gCurrent="page1";   function bringMeForward(myShortName){   //if the layer that called the function (myShortName) is already visible, stop   if (gCurrent == myShortName) {   return;   }   //otherwise, make that layer (myShortName) visible   eval("document."+myShortName+"Main.visibility='visible'");   eval("document."+myShortName+"TabSel.visibility='visible'");   //make the layer that's currently visible (gCurrentLayer) invisible   eval("document."+gCurrent+"Main.visibility='hidden'");   eval("document."+gCurrent+"TabSel.visibility='hidden'");   //set gCurrent to myShortName   gCurrent=myShortName;   }  </script> 
  4. Now you just need to call the new function. Users expect the tabs to change when they click on a tab; so you'll add an event handler and function call to each of the two transparent buttons you created for each tab. The code should look like this:

     <div id="page1Button"  ... etc ... >  <input type="image" src="../Shared/MM/Images/space.gif" width="70" height="23" border="0"  graphics/ccc.gif onClick="bringMeForward('page1')"  >  </div>  <div id="page2Button"  ... etc ... >  <input type="image" src="../Shared/MM/Images/space.gif" width="70" height="23" graphics/ccc.gif border="0"  graphics/ccc.gif onClick="bringMeForward('page2')"  >  </div> 
  5. Try it out. In the Layer Practice dialog box, clicking either tab should appear to bring its page to the front, as shown in Figure 10.20.

    Figure 10.20. Hiding and showing layers to create the tabbed interface, in the Layer Practice command.


    If it doesn't work, carefully check how you named your layers; how carefully you typed the various single and double quotes in the eval() statements; and whether the correct graphics are indeed placed within the correct layers. Keep tinkering until your layers work. What a handy file to build on for future projects!

Dreamweaver MX Extensions
Dreamweaver MX Extensions
ISBN: 0735711828
EAN: 2147483647
Year: 2001
Pages: 141
Authors: Laura Gutman

Similar book on Amazon © 2008-2017.
If you may any questions please contact us: