[Contents] [Prev page] [Next page] [Index]

Dynamic HTML in Netscape Communicator
Part 2. Positioning HTML Content

Chapter 12

Expanding Colored Squares Example

This example illustrates how to expand and contract the clipping region of a layer, without changing the wrapping width of the layer. (The next example, Chapter 13, "Changing Wrapping Width Example,", illustrates how to capture mouse events so that the user can make a layer's wrapping width wider or narrower by dragging the mouse.)

This example illustrate these tasks:

The sections in this chapter are:


Running the Example

In this example, when the page initially loads, the user sees four colored squares as follows:

Figure 12.1 Initial appearance of the four colored squares

When the square is fully contracted, it displays a number. If the user moves the mouse over one of the squares, its content changes to a block of text and the square expands.The top-left square expands up and to the left, the top-right square expands to the top and to the right, and so on.

The following figure shows the four squares after the top-left and top-right squares are fully expanded.

Figure 12.2 Two squares are fully expanded

While a square is expanding, further mouse-over events are blocked on that square until it has finished expanding. When it is fully expanded, if the user moves the mouse over it, then it contracts again. While it is contracting, all mouse-over events for that square are blocked until it has finished contracting. When it finishes contracting, it changes its content back to a number.

To run the example see:

squares.htm

This example is provided only as a <LAYER> version.

To view the complete code for the example, use the Page Source command of the View menu in the Navigator browser that is displaying the example.


Creating the Colored Squares

Each colored square is in its own layer. The width of each layer is 200 and the height is 200. When the page loads you only see a 50x50 region of each layer because as soon as it is loaded, it calls a function that sets its clipping region so that only a small part of the square is visible.

Each square layer contains another layer that displays a number. The number needs to be in a layer so that can be placed it in the portion of the layer that is visible when the square is fully contracted.

The following figure shows where the number 1 would appear in the top-left square if it were not in a layer but were allowed to fall in its natural position in the parent layer. As you can see, when the red square is fully contracted, the number would not be visible.

Figure 12.3 Position where the number 1 would appear if it were not in a layer

Definitions for the Layers

The following code defines the top-left layer:

<LAYER ID="topleftblock" top=50 left=50
 width=200 height=200
 BGcolor="#FF5555"
 onLoad = initializeTopLeft(0);
 onMouseOver=changeNow(0); >
 <LAYER TOP=160 LEFT=168>
    <H1>1</H1>
  </LAYER>
</LAYER>

This layer would be 200 pixels wide by 200 high. However, when this layer finishes loading, it calls its onLoad function, initializeTopLeft().

Before considering the initializeTopLeft() function, quickly look at the global variables defined in the script. There are four variables that describe the minimum and maximum clipping values. The variable delta specifies the distance by which the clipping values change each time the expand() or contract() functions are called. (These functions will be discussed in detail soon.)

<SCRIPT>
var maxclip = 200;
var minclip = 0;
var maxclipcontracted = 150;
var minclipcontracted = 50;
var delta = 10;

The Initialization Functions

The initializeTopLeft() function does the following things:

Figure 12.4 Clip values

The full definition for the initializeTopLeft() function is shown here:

function initializeTopLeft(n)
{
 var thislayer = document.layers[n];
 thislayer.status = "waitingToExpand";
 thislayer.clip.top = maxclipcontracted;
 thislayer.clip.left = maxclipcontracted;
 thislayer.clip.bottom = maxclip;
 thislayer.clip.right = maxclip;
 thislayer.dleft = -delta;
 thislayer.dtop = -delta;
 thislayer.dbottom = 0;
 thislayer.dright = 0;
 thislayer.myposition = "topLeft";
 thislayer.mysource="point1.htm"
 thislayer.mytext="<LAYER TOP=160 LEFT=168><H1>1</H1></LAYER>"
 return false;
}

Each of the other three layers has a similar definition, and a corresponding initialization function.


The Last Layer

Since the bottom squares can be dynamically expanded beyond the height of the page, add a last layer that is positioned below the bottom of the expanded bottom squares. This last layer has nothing in it, but it forces the Web page to increase its height to be big enough to include the expanded layers. Thus you will be able to use the scrollbar to scroll down to the bottom of the expanded layers if they do not initially fit on your screen.

If you we do not include this last layer, then the scrollbar will only allow you to scroll to the bottom of the contracted squares.

Here is the definition for the last layer:

<LAYER TOP=500>
<P></P>
</LAYER>

Moving the Mouse Over a Square

When you move the mouse over any of the colored squares, its changeNow() function is invoked. (This is because in the layer definition, the onMouseOver handler is set to changeNow().)

The basic aim of the changeNow() function is to start expanding the layer if it is fully contracted, or start contracting the layer if it is fully expanded. If the layer is already in the process of expanding or contracting, it ignores the new mouse over event.

The status variable indicates whether the layer is waiting to expand, waiting to contract, expanding or contracting. The status value for each layer is initialized to "waitingToExpand".

The changeNow() function simply checks the status of the layer and then calls the expand() function, the contract() function, or does nothing, depending on the layer's status. If the layer needs to start expanding, it first sets the layer's source to change the content of the layer to show text instead of just a number.

function changeNow (n)
{
 var thislayer = document.layers[n];
 if (thislayer.status == "waitingToExpand")
 {
  thislayer.src=thislayer.mysource;
  expand(n);
  }
 else if (thislayer.status == "waitingToContract")
  {contract(n);}
 return false;
}

The expand() Function

The expand() function sets the layer's status to expanding. Then it changes each of the clip.left, clip.right, clip.top, and clip.bottom variables by the values appropriate to the particular layer to increase the layer's visible region in the appropriate direction. It then checks if the layer is fully expanded and, if not, calls the setTimeout() function to reinvoke the expand() function.

If the layer has finished expanding, the expand() function sets the layer's status to "waitingToContract".

Here is the code for the expand() function:

function expand (n)
{
 var thislayer = document.layers[n];
 thislayer.status = "expanding";
 // increase or decrease each clip value as appropriate
 thislayer.clip.left=thislayer.clip.left+thislayer.dleft;
 thislayer.clip.right=thislayer.clip.right+thislayer.dright;
 thislayer.clip.bottom=thislayer.clip.bottom+thislayer.dbottom;
 thislayer.clip.top=thislayer.clip.top+thislayer.dtop;
 // is the layer fully expanded?
 if (
  (((thislayer.myposition == "topLeft") |
   (thislayer.myposition == "bottomLeft")) &&
   (thislayer.clip.left > minclip)) ||
  (((thislayer.myposition == "topRight") |
   (thislayer.myposition == "bottomRight")) &&
   (thislayer.clip.right < maxclip)))
 // if not, call expand again
 {setTimeout("expand(" + n + ")", 50);}
 // if so, change the layer's status
 else {thislayer.status = "waitingToContract";}
 return false;
}

The contract() Function

The contract() function is very similar to the expand() function. The contract() function sets the layer's status to contracting. Then it changes each of the clip.left, clip.right, clip.top, and clip.bottom by the values appropriate to the particular layer to decrease the visible region in the appropriate direction. It then checks if the layer is fully contracted, and if not, calls the setTimeout() function to reinvoke the contract() function.

If the layer has finished contracting, the contract() function sets the layer's status to "waitingToExpand". The other thing it does is to change the contents of the layer so that you can see the number of the layer. It does this by opening the layer's document, writing the data stored in the layer's mytext variable, and then closing the layer's document.

The value of the mytext variable was set during the initialization process. For each layer, it contains the HTML text for an embedded layer that displays the layer's number at a place that will be visible when the layer is fully contracted.

Here is the code for the contract() function:

function contract (n)
{
 var thislayer = document.layers[n];
 thislayer.status = "contracting";
 // increase or decrease each clip value as appropriate
 thislayer.clip.left=thislayer.clip.left-thislayer.dleft;
 thislayer.clip.right=thislayer.clip.right-thislayer.dright;
 thislayer.clip.bottom=thislayer.clip.bottom-thislayer.dbottom;
 thislayer.clip.top=thislayer.clip.top-thislayer.dtop;
 // is the layer fully contracted? True if
 // the square is the top OR bottom left AND its clip left 
 //  is less than or equal to the minimum clip for contracted squares
 // OR if the square is the top OR bottom right AND its clip right
 // is greater than or equal the max clip for contracted squares
 if (
  (((thislayer.myposition == "topLeft") |
   (thislayer.myposition == "bottomLeft")) &&
   (thislayer.clip.left <= minclipcontracted)) ||
  (((thislayer.myposition == "topRight") |
   (thislayer.myposition == "bottomRight")) &&
   (thislayer.clip.right >= maxclipcontracted)))
 // if not, call contract again
 {setTimeout("contract(" + n + ")", 50);}
 // if it is fully contracted
 else {
  // change the status
  thislayer.status = "waitingToExpand";
  //open the document, write mytext to it, close again
  thislayer.document.write(thislayer.mytext);
  thislayer.document.close();
 }
 return false;
}
</SCRIPT>

Styles in the Document

Just to make the text in the squares look prettier, this file uses a style sheet to set left and right margins for paragraphs, and to center level-three headings:

<STYLE TYPE="text/css">
<!--
 P {margin-left:10%; margin-right:10%;}
 H3 {text-align:center; margin-top:4%;}
-->
</STYLE>


[Contents] [Prev page] [Next page] [Index]

Last Updated: 08/07/97 15:21:59


Copyright 1997 Netscape Communications Corporation