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

Dynamic HTML in Netscape Communicator
Part 2. Positioning HTML Content

Chapter 9

Using JavaScript With Positioned Content

This chapter discusses how to use JavaScript to modify and animate positioned blocks of HTML content. First the chapter gives an overview of why you might want to use JavaScript to modify blocks of content, then it discusses the Layer object, which represents a block of content. It shows how to use JavaScript to create new blocks of content, and how to write content dynamically. It discusses how you can make distinct blocks of HTML respond to events. It discusses how each block of content can contain its own localized script, and finishes up by addressing some of the issues involved in animating HTML content.

This chapter does not teach the basics of using the JavaScript language, although it does provide several examples that should help you get started. For more information about JavaScript see:

The remaining chapters in this part of the book each present a separate complete example of using JavaScript to work with positioned content.


Using JavaScript to Bring Your Web Pages to Life

Regardless of how you define your positioned blocks of HTML content, you can write scripts in JavaScript that move them, change their color and size, change their content, make them visible or invisible, and generally modify them in a variety of ways. Furthermore, you can use JavaScript to change the contents of a positioned block or create new ones on-the-fly.

Using JavaScript to work with positioned blocks of HTML content allows you to define animations directly in a web page. For example, you could create an animation that dynamically peels away a series of layers of content to reveal the one underneath. You can make blocks of content move across, over, and under other blocks of content. You can make them appear and disappear. You can make them dynamically expand and contract in response to mouse events. You can generally bring your web page alive with animated content.

You can use JavaScript to modify positioned blocks of HTML content regarless of how the blocks are defined. You can manipulate positioned blocks of HTML content with JavaScript, even if they are defined as styles.


The Layer Object

Regardless of how you define a positioned block of HTML content, it can be treated as a modifiable object in JavaScript.

For each layer in an HTML page (whether it is defined with the <LAYER> tag or as a style whose position property is either absolute or relative) there is a corresponding JavaScript layer object. You can write JavaScript scripts that modify layers either by directly accessing and modifying property values on the layer objects, or by calling methods on the layer objects.

The Document Property of Layers and the Layers Property of Documents

Each document object has a layers property that contains an array of all the top-level layers in the document. Each layer in turn has a document property.

This document property has a layers array that contains all the top-level layers inside this layer. The document of a layer also has all the usual properties of a document object, such as the images property, which is an array of all the images in the layer, as well as properties that are arrays for all the applets, embeds, links, and named anchors in that layer.

How Do You Refer to a Positioned Block of Content from JavaScript?

There are several ways you can access a layer from JavaScript. If you know the layer's id (or name) you can access it in the following ways:

If you know the index for the layer you can access it as follows:

When accessed by integer index, array elements appear in z-order from back to front, where zero is the bottom-most layer and higher layers are indexed by consecutive integers. The index of a layer is not the same as its zIndex property, as the latter does not necessarily enumerate layers with consecutive integers. Also, adjacent layers can have the same zIndex property values, but two layers can never occupy the same index in the array.

You can find the number of layers in a document or another layer array by obtaining its length property. For example, the following expression returns the number of top level layers in the document:

document.layers.length

The following expression returns the number of layers nested at the top level inside the layer named "houses".

document.layers["houses"].document.layers.length

The Layer Object Properties

As with any JavaScript object, you can access the properties of a layer object using the following syntax:

layerObject.propertyName

where layerObject is an expression that evaluates to a layer object, and propertyName is the name of the property to be accessed. For example, the following expression returns the value of the visibility property of the layer named "flowerlayer":

document.flowerlayer.visibility;

The following expression sets the left property of the layer named "flowerlayer" to 300 pixels.

document.flowerlayer.left=300;

The following table lists all the properties that you can use to access or modify a layer in JavaScript. Notice that there is only one set of property names. No matter whether a layer was created with the <LAYER> tag or was defined as a style, you can use the property names listed in the following table to access it or modify it after it has been created.

These property names are case-sensitive.

Table 9.1 Layer Object Properties

Property Name

Modifiable by user?

Description

document

No

Each layer object contains its own document object. This object can be used to access the images, applets, embeds, links, anchors and layers that are contained within the layer. Methods of the document object can only also be invoked to change the contents of the layer.

name

No

The name assigned to the layer through the NAME or ID attribute.

left

Yes

The horizontal position of the layer's left edge, relative to the origin of its parent layer (for layers with absolute positions) or relative to the natural flow position (for layers with relative positions).

The value can be an integer such as 12, or a percentage, such as " 25%".

The default unit of measurement is pixels.

top

Yes

The vertical position of the layer's top edge relative to the origin of its parent layer.

The value can be an integer, an integer such as 12, or a percentage, such as " 25%".

The default unit of measurement is pixels.

pageX

Yes

The horizontal position of the layer relative to the page.

The default unit of measurement is pixels.

pageY

Yes

The vertical position of the layer relative to the page.

The default unit of measurement is pixels.

zIndex

Yes

The relative z-order of this layer with respect to siblings. Sibling layers with lower numbered z-index's are stacked underneath this layer.

The value must be 0 or a positive integer.

visibility

Yes

Determines whether or not the layer is visible. A value of "show" means show the layer; "hide" means hide the layer; "inherit" means inherit the visibility of the parent layer.

clip.top

clip.left

clip.right

clip.bottom clip.width clip.height

Yes

These properties define the clipping rectangle, which specifies the part of the layer that is visible. Any part of a layer that is outside the clipping rectangle is not displayed.

The clipping region can extend beyond the area of the layer that contains content. Clipping values can be negative, 0, or positive integers.

For example, to clip 10 pixels from the left edge, you would increase clip.left by 10. To reduce the clipping region by 20 pixels at the right edge, you would reduce clip.right by 20.

The values for clip.top, clip.left, clip.bottom, and clip.right, are in the layer's coordinate system.

Setting the clip.width value to w is the same as:

clip.right = clip.left + w;

Setting the clip.height to h is the same as:

clip.height = clip.top + h;

background

Yes

The image to use as the background for the layer.

The image is tiled across the background of the layer. For example:

layer.background.src = "fishbg.gif";
The value is null if the layer has no backdrop.

bgColor

Yes

The color to use as a solid background color for the layer. The value can be an encoded RGB value, a string that indicates a pre-defined color, or null for a transparent layer

For example:

//blue background
layer.bgColor = "#0000FF"; 
// red background
layer.bgColor = "red";
// transparent layer
layer.bgColor = null;
siblingAbove

No

The layer object above this one in the stacking order, among all layers that share the same parent layer or null if the layer has no sibling above.

siblingBelow

No

The layer object below this one in z-order, among all layers that share the same parent layer or null if layer is bottommost.

above

No

The layer object above this one in z-order, among all layers in the document or the enclosing window object if this layer is topmost.

below

No

The layer object below this one in z-order, among all layers in the document or null if this layer is bottommost.

parentLayer

No

The layer object that contains this layer, or the enclosing window object if this layer is not nested in another layer.

src

Yes

Source of the content for the layer, specified as a URL.

The Layer Object Methods

There are several methods that you can use on a layer object to modify a layer. As with any JavaScript object, you can invoke a method on a layer object using the following syntax:

layerObject.methodName(args)

where layerObject is an expression that evaluates to a layer object, methodName is the method to be invoked, and args are the arguments to the method.

For example, the following expression invokes the method moveBy() on the layer named flowerlayer, to move the layer 10 pixels to the right and 10 pixels down from its current position.

document.flowerlayer.moveBy(10, 10);

The following table lists all the methods that you can use to access or modify a layer in JavaScript. You will notice that there is only one set of method names. It does not matter whether a layer was created with the <LAYER> tag or was defined as a style, you can use the methods listed in the following table to access it or modify it after it has been created.

These method names are case-sensitive


Table 9.2 Layer Object Methods

Method Name

Description

moveBy(dx, dy)

Moves this layer by dx pixels to the left, and dy pixels down, from its current position.

moveTo(x, y)

For layers with absolute positions, this method changes the layer's position to the specified pixel coordinates within the containing layer or document. For layers with relative positions, this method moves the layer relative to the natural position in the containing layer or document.

This method is equivalent to setting both the top and left properties of the layer object.

moveToAbsolute(x, y)

Changes the layer position to the specified pixel coordinates within the page (instead of the containing layer.)

This method is equivalent to setting both the pageX and pageY properties of the layer object.

resizeBy(dwidth, dheight)

Resizes the layer by the specified height and width values (in pixels). Note that this does not relayout any HTML contained in the layer. Instead, the layer contents may be clipped by the new boundaries of the layer.

This method has the same effect as adding dwidth and dheight to the clip.width and clip.height.

resizeTo(width, height)

Resizes the layer to have the specified height and width values (in pixels). Note that this does not relayout any HTML contained in the layer. Instead, the layer contents may be clipped by the new boundaries of the layer.

This method has the same effect as setting the clip.width and clip.height.

moveAbove(layer)

Stacks this layer (in z-order) above the layer specified in the argument, without changing either layer's horizontal or vertical position. After re-stacking, both layers will share the same parent layer.

The value must be a valid layer object.

moveBelow(layer)

Stacks this layer (in z-order) below the specified layer, without changing the layer's horizontal or vertical position. After re-stacking, both layers will share the same parent layer.

The value must be a valid layer object.

load(sourcestring, width)

Changes the source of a layer to the contents of the file indicated by sourcestring, and simultaneously changes the width at which the layer's HTML contents will be wrapped.

This method takes two arguments. The first argument is a string indicating the external file name, and the second is the width of the layer in pixels.


Creating Positioned Blocks of Content Dynamically

You can use JavaScript to create new layer objects by calling the new operator on a Layer object, for example:

bluelayer = document.bluelayer;
newbluelayer = new Layer(300, bluelayer);

The first argument is the width of the new layer, and the second argument, which is optional, is its parent layer. The parent can also be a window, in which case the new layer is created as a top-level layer within the corresponding window. If you do not supply a parent layer, the new layer will be a top-level layer in the current document.

After creating a new layer, you can set its source either by setting a value for its src property, or by calling the load method. Alternatively, you can open the layer's document and write to it (as discussed in the next section.)

There are a few important things to know about creating layers and modifying their contents dynamically. You can create a new layer object by using the new operator only after the page has completely finished loading. You cannot open a layer's document and write to it until the page has finished loading. You can have only one layer open for writing at a time.


Writing Content in Positioned Blocks

While initially defining a layer, you can write to the layer's document using the document's write method.

<LAYER ID="layer1" BGcolor="green"> 
  <HR>
  <H1>First Heading</H1> 
  <SCRIPT>
     document.write("<P>Here is some content<P>")
  </SCRIPT>
  <HR>
</LAYER>

After a layer has been initially created and the page has fully finished loading, you can modify the contents of the layer by using the write() method of the layer's document. If you use the write() method to write content to a layer after the layer has been created, the original content of the layer is wiped out, and replaced by the new content.

After writing to a layer's document, you need to close the document.

For example:

<LAYER ID="layer1" BGCOLOR="blue"> 
 <HR>
 <H1>First Heading</H1> 
 <P>Here is the original content<P>
 <HR>
</LAYER>
</BODY>
</HTML>
<SCRIPT>
function changeLayerContent() {
  document.layer1.document.write("<HR><P>New content.</P><HR>");
  document.layer1.document.close();
}
</SCRIPT>

<FORM NAME="form">
<INPUT TYPE=button VALUE="CHANGE CONTENT" 
ONCLICK='changeLayerContent();return false;'>
</FORM>

For a further example of writing to a layer, see Chapter 12, "Expanding Colored Squares Example."


Handling Events

Each layer can be thought of as a separate document. It has the same event-handling capabilities as a top-level window. You can capture events for a layer.

For an overview of event handling, see the section "Scripting Event Handlers" in the JavaScript guide for in JavaScript. The following link takes you to the JavaScript guide:

http://home.netscape.com/eng/mozilla/3.0/handbook/javascript/index.html

When defining a layer with the <LAYER> tag, you can also supply the following attributes that specify event handlers:

onMouseOver
onMouseOut
onLoad
onFocus
onBlur

The onMouseOver event handler is invoked when the mouse cursor moves into a layer.

The onMouseOut event handler is invoked when the mouse cursor moves out of the area of a layer.

The onLoad event handler gets invoked when a layer is loaded, that is, the document that ultimately contains the layer is displayed. This is true regardless of whether a layer is visible or not.

The onFocus handler is invoked when the layer gets keyboard focus, and the onBlur handler is invoked when the layer loses keyboard focus.

Just as in the case of a document, if you want to define the mouse click response for a layer, you must capture onMouseDown and onMouseUp events at the level of the layer and process them as you want.

If an event occurs in a place where multiple layers overlap, the top-most layer gets the event, even if it is transparent. However, if a layer is hidden, it does not get events.

For an example of capturing events for a layer, see Chapter 13, "Changing Wrapping Width Example."


Using Localized Scripts

You can use the <SCRIPT> and </SCRIPT> tags within blocks of positioned content. The functions defined in the script will be scoped to the block that contains them, and they cannot be used outside that block.

This functionality is handy, for example, for defining event handlers for a layer.

<LAYER> Tag Syntax

<LAYER ID="layer1" BGCOLOR="red"
    onMouseOver='changeColor("blue");'
    onMouseOut='changeColor("red");'>
  <P>Layer content...</P>
  <SCRIPT>
    function changeColor(newcol) {
      bgColor=newcol; // Modifies the layer object's bgColor property
      return false;
      }
    </SCRIPT>
</LAYER>

CSS Syntax

<DIV STYLE="position:absolute; layer-background-color:red; 
    width:200px; height:100px">
  <P>Layer content...</P>
  <SCRIPT>
  function onMouseOver() {changeColor("blue");}
  function onMouseOut() {changeColor("red");}
  function changeColor(newcol) {
    bgColor=newcol;
    return false;
  }
  </SCRIPT>
</DIV>

When the mouse moves into the layer, the layer turns blue. When the mouse moves out of the layer, it turns red. To see the example in action, select:

chgcolor.htm


Animating Positioned Content

You can use JavaScript to modify layers to produce the effects of animation. Frequently, animation revolves around repeating actions over and over again, particularly for looping animations. You can use the JavaScript function setInterval() function to repeatedly call a function at a given interval.

For example, the following statement calls the keepExpanding() function every 25 milliseconds, with arguments of 20, 30, 40 and 50.

setInterval(keepExpanding, 25, 20, 30, 40, 50); 

JavaScript also provides the setTimeout() function, which calls another function after a given amount of time.

The setTimeOut() function has two different forms:

setTimeout("code to be executed", delay)
setTimeout(function, delay, args...)

For example, to invoke doItAgain("Sam", "piano") after 3 milliseconds, you can use either of the following statements:

setTimeout("doItAgain('Sam', 'piano')", 3)
setTimeout(doItAgain, 3, "Sam", "piano");

The setTimeout() function is useful for conditionally re-invoking a function, whereas the setInterval() function is useful for kicking off the repeated, unconditional invocation of a function.

The following function uses setTimeout() to keep making the clipping area of a layer 5 pixels wider and 5 pixels higher until the layer is 450 pixels wide.

function expand(layer) 
{
    if (layer.clip.right < 450) {
    layer.resizeBy(5, 5);
    setTimeout(expand, 5, layer);
  }
 return false;
}

Animating Images

You can achieve many interesting animations by changing the source of an image in conjunction with moving the image. To move an image, you can change the position of the layer that contains the image. To change the source of the image, you can assign a new value to the src property of the image object.

If the source of the image is changed too quickly or too often, the actual image may not download across the net quickly enough to keep up with the animation. Therefore if you have a script that changes the source of an image in a moving layer, it is best to make sure that the image has fully loaded before you try to do anything with it.

Using OnLoad Handlers

When a document has completely finished loading, it invokes its onLoad handler if it has one. You could define an onLoad handler for the BODY element of a document that initiates any animations in the document. The onLoad handler for a BODY element may be invoked before all frames in all animated GIF images have finished loading, but it will not be invoked until at least one frame of every animated GIF image has finished loading.

Layers can also have onLoad handlers. However, if a layer contains images, the images may load asynchronously from the rest of the layer's content, and the layer may think it has finished loading and thus fire its onLoad handler (if it has one) before all its images have finished loading.

Images can have onLoad handlers also. However, if the image is an animated GIF, its onLoad handler is invoked every time a frame in the image finishes loading. Therefore if your image is an animated GIF, it is better to define an onLoad handler that initiates any animations that use that image in the BODY element rather than directly on the image.However, it the image is a static GIF or JPEG, by all means define the onLoad handler directly on the image.

Chapter 11, "Swimming Fish Example," discusses an example, Positioning and Moving the Fish and Poles, that has a layer containing a fish that swims back and forth. The fish starts swimming when someone clicks on a button. To ensure that nobody can click the button before the fish image has finished loading, the layer containing the button is initially hidden. When the document has finished loading, its onLoad handler makes the form layer visible.

Pre-fetching Images

One way to reduce the time required to start an animation is to ensure that the images used in the animation are downloaded to the browser's cache before the animation starts. This approach is known as prefetching the images.

You can prefetch an image by embedding it in a layer. When a layer loads, it loads all its content, including all images, regardless of whether the layer is visible or not. If a page has a hidden layer that contains all the images needed in the animation then when the page opens, the source for the images is downloaded into the browser's cache, even though they are not visible.

Chapter 11, "Swimming Fish Example," discusses an example, Changing the Stacking Order of Fish and Poles, that illustrates the use of a hidden layer to contain images that are not needed when the page opens but are used in the course of animating the contents of the page.

Suppressing the Icon for Images that Have Not Yet Loaded

By default, when a page opens, it shows a placeholder icon for every image in the page that has not finished loading. Animation sequences may sometimes require multiple images. While the images are loading, the user could see lots of placeholder icons that you would prefer they did not see.

A new attribute has been introduced for the IMG tag to allow you to suppress the display of placeholder icons.

The SUPPRESS attribute for the IMG tag can be set to either true or false. The default value is false. If SUPPRESS is set to true, neither the place-holder icon or frame that appear during image loading will be displayed and tool-tips will be disabled for that image.

If SUPPRESS is set to false, the place-holder icon and frame will always be displayed during loading even if the images are transparent images that would not otherwise be displayed. Tool tips will be active.



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

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


Copyright 1997 Netscape Communications Corporation