Expandable Outlines: Netscape Navigator 4 | WebReference

Expandable Outlines: Netscape Navigator 4


Expandable Outlines
Navigator 4: outline concepts

As we have seen, toggling the display property is the natural way to achieve the technique-in-question. Even though Navigator does not allow us to change its value on-the-fly, we may still achieve the effect with the brute-force method.

First we break the technique into its logical parts:

Question: What does Explorer do when we toggle the display property?


  1. it marks the elements that will not be rendered for identification.
  2. it starts at the page top and renders the page anew.
  3. when an element is encountered that should not be rendered, page rendering pauses until the end of the element is parsed.
  4. the following element is rendered in its place, unless that too should not be displayed, in which case the procedure is repeated until a displayable element is encountered.
  5. elements are either displayed or not, until the end of page is reached

Next, we review what relevant capabilities Navigator does have:

  1. it can "hide" or "show" positioned elements.
  2. it can reposition positioned elements at any time.
  3. it can calculate the dimensions of positioned elements based on their content.

These three oft-used Navigator features are all we need.
Now we can list the steps necessary for expanding and collapsing ala Navigator:

  1. place outline headings and associated expandable/collapsable HTML in absolutely positioned elements (DIVs).
  2. place all subsequent non-outline HTML in absolutely positioned element(s).
  3. arrange all DIVs in vertical order to force vertical scrollbars to scroll to true fully-expanded page height.
  4. "hide" all expandable DIVs.
  5. reposition visible DIVs, one after the other.

When the page is displayed, only the non-expandable DIVs, that is, the outline headings and non-outline page will be visible. When an expansion is called for, we can:

  1. "show" the element.
  2. reposition all DIVs one after the other, this time including the newly-expanded DIV.

In the same way, we can "hide" and then reposition DIVs for an element collapse.

Try the following expandable two-item outline: (NS4 only)

Expand/Collapse Item World Wide Web Consortium (W3C)

HTML 4.0 Proposed Recommendation
HTML 3.2 Recommendation
Cascading Style Sheets, level 1 (CSS1)

Expand/Collapse Item Netscape

Dynamic HTML documentation   Updated!
Recently updated for Communicator final release with better CSS documentation and examples. An invaluable reference for developers, the complete documentation can be viewed online, or downloaded as:

We first enclosed the outline in four positioned elements:

    <DIV ID="elOneParent" STYLE="position:absolute; visibility:visible"> <H3> <A HREF="#" onClick="expandIt('elOne'); return false"> <IMG NAME="imEx" SRC="triDown.gif" WIDTH=16 HEIGHT=16 BORDER=0 ALT="Expand/Collapse Item"> </A> World Wide Web Consortium (W3C) </H3> </DIV> <DIV ID="elOneChild" STYLE="position:absolute; visibility:visible"> . . . </DIV>
    <DIV ID="elTwoParent" STYLE="position:absolute; visibility:visible"> <H3> <A HREF="#" onClick="expandIt('elTwo'); return false"> <IMG NAME="imEx" SRC="triDown.gif" WIDTH=16 HEIGHT=16 BORDER=0 ALT="Expand/Collapse Item"> </A> Netscape </H3> </DIV> <DIV ID="elTwoChild" STYLE="position:absolute; visibility:visible"> . . . </DIV>

The remainder of the page was enclosed in two more DIVs, but only for technical reasons. We could just as easily have included the remainder in one positioned element.

    <DIV ID="elBod" STYLE="position:absolute; visibility:visible"> . . remainder of page elements (except footer) . </DIV> <DIV ID="elFooter" STYLE="position:absolute; visibility:visible"> . . footer page elements . </DIV>

Expand the outline above again and keep it expanded. When you click on the form button below, the separate DIVs used in the layout of this page will be displayed in alternating colors for easy identification. Remember, the outline and every element on the page that comes after the outline are enclosed in positioned elements (DIVs).Scroll the page to identify them and see their vertical position. Then click the button to restore the white background, before we continue.

We have given our outline DIVs a naming convention of Parent-Child. This will become very useful later.

The Script

All our DIVs are absolutely positioned, with no left or top property values. This results in their being positioned one on top of the other. We must position them before the page has finished loading so that the maximum page height will become scrollable. If we position only the visible outline headings and non-outline page parts before page load, then the page will scroll only to that height. When we expand the outline, we will lose the bottom of the page off the scrollable page. Remember, Navigator is not re-drawing the page, we are. So first we position all elements tail to end, to ensure the proper page height.

Note: Navigator creates the page height, and fits scrollbars to match, while the page loads. Once it has loaded, new positioning will not be reflected in the scrollbars. That is, an element can easily be positioned off the page, leading to user frustration. We must, therefore, position all our elements before the page has finished loading. Navigator will correctly calculate their content height, only if they are visible. We have two options:
  1. make all our to-be-positioned elements visible during load. They are correctly positioned just before the page ends. After load, the expandable elements are hidden, and a re-positioning takes place, creating the outline format. This is the most efficient method, but it has one drawback. Since all the positioned elements are initially rendered at the same page coordinates, a visible layering effect occurs. It can be distracting to users, especially if the outline is large.
  2. make our collapsable elements hidden during load. At page end, they are made visible, and positioned. The behaviour after page load remains the same.

    We will discuss the first method. Additional code for the second method is included in our code page.

In either case, we need to know the index of the first DIV in our outline. The why will become clear in a minute. We include this code snippet at the end of our page, after the final DIV:

    ... </DIV> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- if (NS4) { firstEl = "elOneParent"; firstInd = getIndex(firstEl); arrange(); } //--> </SCRIPT> </BODY> </HTML>

We manually identify the outline's first DIV, and pass it as an argument to the getIndex() function in our script proper:

    function getIndex(el) { ind = null; for (i=0; i<document.layers.length; i++) { whichEl = document.layers[i]; if (whichEl.id == el) { ind = i; break; } } return ind; }

getIndex() compares the first DIVs ID to the ID of all the elements in the document.layers array. When a match is found, the search ends, and the index of the match (ind) is returned to become the global variable firstInd.

Any positioned elements that exist prior to the appearance of the outline on our page should not be repositioned. Only the outline elements and subsequent elements should be manipulated. The easiest way to identify these elements, therefore, is through their index.

Now that we know where to start the positioning, the arrange() function is called.

    function arrange() { nextY = document.layers[firstInd].pageY + document.layers[firstInd].document.height; for (i=firstInd+1; i<document.layers.length; i++) { whichEl = document.layers[i]; if (whichEl.visibility != "hide") { whichEl.pageY = nextY; nextY += whichEl.document.height; } } }

Using firstInd, arrange() finds the first outline element as document.layers[firstInd]. The pageY property of the element gives us the existing vertical page position. This position is the correct one for the element, since by being the first with no left/top properties, it was positioned correctly. The rest of the elements are positioned on top of this element. The document.height property gives us the vertical pixel dimension of the element's content. Adding this to pageY, we get the vertical page position that the next element should be placed at: nextY.

Next, we move through all subsequent positioned elements on the page, using a for loop, and starting at document.layers[firstInd+1]. The visibility property is checked. If the element should be hidden, we ignore it. If it should be visible, we position it and increment nextY by the content height of the element. By repeating this procedure, all visible elements are positioned. Since on the first go-through (before page load) all elements are visible, this results in the creation of a page to the maximum possible height (fully expanded outline).

Once the page is loaded, we have some more arranging to do.

Produced by Peter Belesis and

All Rights Reserved. Legal Notices.
Created: Jan. 14, 1998
Revised: Jan. 18, 1998

URL: http://www.webreference.com/dhtml/column12/outNSone.html