DHTML Lab 7:
JavaScript With Netscape Layers
In the last lesson we learned how to make Netscape Layers, which are document objects. You may or may not have encountered the idea of document objects in the JavaScript lessons, in particular the lesson on the JavaScript Object Heirarchy. We can use the JavaScript Object Heirarchy to access and change the properties of layers. In the first example below we are accessing the left property of the layer called mylayer.
In HTML mode, Type the following code into the edit textarea below:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<script language=javascript>
<!--
alert(document.mylayer.left);
//-->
</script>
</body>
|
Now Preview it.
What happened? You should have gotten an alert box with the number "150" in it.
We could also use the layers array to access this:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<script language=javascript>
<!--
alert(document.layers["mylayer"].left);
//-->
</script>
</body>
|
Notice the layers array available from the document object. This layers array contains all of the layers in your document! This array is just like the forms array...you can access all of the layers in the array using either numerical indices (1,2,3,4,...) or constant indices corresponding to the NAME or ID value of the layer (you did notice the id="mylayer" parameter in the layer tag didn't you?)
Let's try modifying the "LEFT" property of our layer using JavaScript. Add this to your page:
In HTML mode, Type the following code into the edit textarea below:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<form><input type=button value='Move It' onclick=moveIt()></form>
<script language=javascript>
<!--
function moveIt(){
document.layers["mylayer"].left = 0;
}
//-->
</script>
</body>
|
Now Preview it.
Go try it out...click the 'Move It' button. Neat huh? Yes, you can modify most of the properties available to you via the JavaScript Object Heirarchy.
Here's a list of all of the properties that can be accessed via JavaScript. Again, I'm lazy so I'm going to copy Netscape's list below:
Table 2.1 Layer Object Properties
|
Property Name
|
Modifiable by user?
|
Description
|
|
document
|
Sometimes
|
Netscape didn't include this property/sub-object in their list. Each Layer has a document object that is just like any other document object...just like a frame or window.
|
|
name
|
N
|
The name assigned to the layer through the NAME attribute in the <LAYER> tag.
|
|
left
|
Y
|
The horizontal position of the layer's left edge, in pixels, relative to the origin of its parent layer.
Parent layer? Did I mention that you can put layers within layers? Well, you can. When you do, the "inner" layer's properties are in relation to the "parent" (containing) layer.
|
|
top
|
Y
|
The vertical position of the layer's top edge, in pixels, relative to the origin of its parent layer.
|
|
pageX
|
Y
|
The horizontal position of the layer, in pixels, relative to the page.
This is only different from "left" if the layer is embedded in another layer, or does not have the "left" parameter defined in the layer tag.
|
|
pageY
|
Y
|
The vertical position of the layer, in pixels, relative to the page.
|
|
zIndex
|
Y
|
The relative z-order of this layer with respect to siblings and parent. Sibling layers with lower numbered z-index's are stacked underneath this layer. A layer with a negative zIndex value is always stacked below its parent layer and a layer with a non-negative zIndex always appears above its parent layer.
the zIndex property corresponds to the Z-Index parameter. This syntax change is normal because you can't use "-" characters in object references.
|
|
visibility
|
Y
|
Determines whether or not the the layer is visible. A value of show means show the layer; hide means hide the layer; inherit means inherit the visiblity of the parent layer.
|
|
clip.top
clip.left
clip.right
clip.bottom clip.width clip.height
|
Y
|
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.
How is this different from width and height? Well, there isn't a width or height property in JavaScript for layers. We'll play with this in a second.
|
|
background
|
Y
|
The image to use as the background for the layer's canvas (which is the part of the layer within the clip rectangle).
Not the same as layer.document.background...the document gets painted over the top of the layer.
Each layer has a background property, whose value is an image object, whose src attribute is a URL that indicates the image to use to provide a tiled backdrop The value is null if the layer has no backdrop.
For example:
layer.background.src = "fishbg.gif";
|
|
bgColor
|
Y
|
The color to use as a solid background color for the layer's canvas (which is the part of the layer within the clip rectangle). The value can be an encoded RGB value, a string that indicates a pre-defined color, or null for a transparent layer
Not the same as layer.document.bgColor...the document gets painted over the top of the layer.
For example:
//blue background
layer.bgColor = "0000FF";
// red background
layer.bgColor = "red";
// transparent layer
layer.bgColor = null;
|
|
siblingAbove
|
N
|
The layer object above this one in z-order, among all layers that share the same parent layer or null if the layer has no sibling above.
|
|
siblingBelow
|
N
|
The layer object below this one in z-order, among all layers that share the same parent layer or null if layer is bottomost.
|
|
above
|
N
|
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
|
N
|
The layer object below this one in z-order, among all layers in the document or null if this layer is bottomost.
|
|
parentLayer
|
N
|
The layer object that contains this layer, or the enclosing window object if this layer is not nested in another layer.
|
|
src
|
Y
|
Source of the content for the layer, specified as a URL.
|
Pretty straight forward isn't it? You probably noticed that some of those properties were marked as "Not Being Modifiable By User". This means that although you can read the property via JavaScript, you can't change it. This is similar to the title property of a normal HTML document - you can't modify the title, but you can read it.
Let's play with a few things. First, let's write to the document of our layer. This is just like writing to a frame or window. Add the blue stuff:
In HTML mode, Type the following code into the edit textarea below:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<form><input type=button value='Write To It' onclick=writeIt()></form>
<script language=javascript>
<!--
function writeIt(){
document.layers["mylayer"].document.open();
document.layers["mylayer"].document.write(prompt("Enter some text for your layer",""));
document.layers["mylayer"].document.close();
}
//-->
</script>
</body>
|
Now Preview it.
Easy enough huh? But wait! Something weird happened...the size of our layer changed to fit the text you entered! We can't have that, so somehow we have to change the size back to the original size. Add this blue stuff:
In HTML mode, Type the following code into the edit textarea below:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<form><input type=button value='Write To It' onclick=writeIt()></form>
<script language=javascript>
<!--
function writeIt(){
old_width = document.layers["mylayer"].width;
old_height = document.layers["mylayer"].height;
document.layers["mylayer"].document.open();
document.layers["mylayer"].document.write(prompt("Enter some text for your layer",""));
document.layers["mylayer"].document.close();
document.layers["mylayer"].width = old_width;
document.layers["mylayer"].height = old_height;
}
//-->
</script>
</body>
|
Now Preview it.
Why didn't that work????? Ahhh! Remember the CLIP properties? We can't change the size of the layer this way (we'll use "resize()" for that later). But, there is a set of clip properties which define what portions of the layer are displayed. So, let's use those...change the blue stuff:
In HTML mode, Type the following code into the edit textarea below:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<form><input type=button value='Write To It' onclick=writeIt()></form>
<script language=javascript>
<!--
function writeIt(){
old_width = document.layers["mylayer"].clip.width;
old_height = document.layers["mylayer"].clip.height;
document.layers["mylayer"].document.open();
document.layers["mylayer"].document.write(prompt("Enter some text for your layer",""));
document.layers["mylayer"].document.close();
document.layers["mylayer"].clip.width = old_width;
document.layers["mylayer"].clip.height = old_height;
}
//-->
</script>
</body>
|
Now Preview it.
Ahhh...much better. Now the size of our layer is back to normal. So, what we've just done is written to the layer's document property, and then changed the size of the layer back to it's original size. But, there is a problem with doing this. This works great as long as you are changing the size of the layer back to it's original size, but if you change the clip size of the layer to something other than that original size, you run into a frustrating problem.
Add this blue stuff stuff, and then type in a good sentence or so when you are prompted:
In HTML mode, Type the following code into the edit textarea below:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<form><input type=button value='Write To It' onclick=writeIt()></form>
<script language=javascript>
<!--
function writeIt(){
old_width = document.layers["mylayer"].clip.width -20;
old_height = document.layers["mylayer"].clip.height + 50;
document.layers["mylayer"].document.open();
document.layers["mylayer"].document.write(prompt("Enter some text for your layer",""));
document.layers["mylayer"].document.close();
document.layers["mylayer"].clip.width = old_width;
document.layers["mylayer"].clip.height = old_height;
}
//-->
</script>
</body>
|
Now Preview it.
We made the layer 100 pixels wider and taller than it was before, but if you type enough text, you noticed that the text did not wrap to the full width of the layer. So, there was a large amount of space to the right of the text. If we were to decrease the clip size (otherwise known as the clip rectangle) we would encounter the problem of some of our text being cut off!
This is an unfortunate layers problem...and unfortunately the is no solution to this problem (well, not that I know of...if you find it PLEASE let me know.)
OK. Let's do one more thing before we move on...let's see how I moved that layer across the top of the page in the first tutorial. It's pretty obvious that we're going to be modifying the left property of the layer, so let's see if we can't reproduce what I did. We would use a loop to repetitively move that layer across the page, so let's try it. Let's move our layer across the page until it's left value is, say, 640 pixels:
In HTML mode, Type the following code into the edit textarea below:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<form><input type=button value='Move It' onclick=moveIt()></form>
<script language=javascript>
<!--
function moveIt(){
while (document.layers["mylayer"].left < 640) {
document.layers["mylayer"].left += 1;
}
}
//-->
</script>
</body>
|
Now Preview it.
Well, it sure did move that layer, but MAN it went too fast. You may not have even seen it go. If you did, you saw it slide VERY quickly to the right. We need to slow that down a little, so let's use a setTimeout (setTimeout allows us to delay when a function is executed by a certain number of milliseconds.) Change the blue stuff:
In HTML mode, Type the following code into the edit textarea below:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<form><input type=button value='Move It' onclick=moveIt()></form>
<script language=javascript>
<!--
function moveIt(){
if (document.layers["mylayer"].left < 640) {
document.layers["mylayer"].left += 1;
setTimeout("moveIt()",20);
}
}
//-->
</script>
</body>
|
Now Preview it.
Hey...that worked! Let's talk about how we made it work. What we did was test to see if the left property was less than "640". If it was, we moved the layer to the right 1 pixel. Then, we used the setTimeout method to call our moveIt() function again in 20 milliseconds (20/1000 seconds). If we wanted the layer to slide faster, we could speed up how fast our function was called by setTimeout {setTimeout("moveIt()",10) would be twice as fast}, or we could adjust how far the layer moved every time the function ran (document.layers["mylayer"].left += 2; would move it 2 pixels every time the function ran.). In other words you can run faster by increasing the rate you take steps, OR by increasing the size of the steps you take. Go ahead and play around with the speed of your layer for a few minutes.
But, this layer isn't doing what I did before...which was have the layer constantly scrolling across the top of the page. Let's see how I did that - add the blue stuff:
In HTML mode, Type the following code into the edit textarea below:
<body bgcolor=white>
Here is some text and <layer id="mylayer" bgcolor=red top=100 left=150 width=100 height=150>this is a layer</layer>
<form><input type=button value='Move It' onclick=moveIt()></form>
<script language=javascript>
<!--
function moveIt(){
if (document.layers["mylayer"].left < 640) {
document.layers["mylayer"].left += 1;
}
else {
document.layers["mylayer"].left = 0;
}
timerId = setTimeout("moveIt()",20);
}
//-->
</script>
</body>
|
Now Preview it.
What did we do? We changed the code so that when the left property was 640 or more, the layer was moved back to the left margin of the page. We also move the setTimeout method to outside of the if conditional statement so that no matter what, the function would continue to run over and over again as long as the user was looking at the page.
Guess what...you just made a DHTML Animation!!! Congratulations! Of course, you could combine different layers, move top to bottom, bottom to top (using the top property), right to left, changing sizes, etc., to make more complex animations, but that's where your creativity comes in...you now have to tools to do about anything you can think of!
Now, we are modifying the left property of our layer by hand. This works fine, but Netscape has provided us with some nice built-in methods that help us modify some properties more easily. Below is Netscape's list, with some of my comments as well.
Table 2.2 Layer Object Methods
Method Name
|
Description
|
|
moveBy(x, y)
|
Changes the layer position by applying the specified deltas, measured in pixels.
Just like we just did by doing document.layers["mylayer"].left += 1. We increased the value of the left property relative to it's previous value.
|
|
moveTo(x, y)
|
Changes the layer position to the specified pixel coordinates within the containing layer. For ILayers, moves the layer relative to the natural inflow position of the layer.
This is like setting the position properties specifically...ignoring the current position of the layer...as in "document.layers["mylayer"].left = 100;"
|
|
moveToAbsolute(x, y)
|
Changes the layer position to the specified pixel coordinates within the page (instead of the containing layer.)
This only affects layers without the left or top parameters defined, or layers embedded in other layers. Otherwise it does the same thing as "moveTo()".
|
|
resizeBy(width, height)
|
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.
Just like when we were changing the clip.width and clip.height properties of the layer...with the same wrapping problems...except this changes the clip rectangle relative to its current size.
|
|
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.
Just like when we were changing the clip.width and clip.height properties of the layer...with the same wrapping problems.
|
|
moveAbove(layer)
|
Stacks this layer 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.
We didn't actually try change the zIndex property of our layers, but I'm sure you can figure it out.
|
|
moveBelow(layer)
|
Stacks this layer below the specified layer, without changing the layer's horizontal or vertical position. After re-stacking, both layers will share the same parent layer.
|
|
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.
Just like changing the src property of a frame, or like setting the location.href property of a window or frame.
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 as a pixel value.
|
OK...I know we went fast. Basically, you can modify most of the properties listed above for layers using JavaScript. I suggest that you spend some time playing with layers and JavaScript before going on...these concepts are going to be basically the same for CSS, and you need a good handle on them.
Suggestion...I didn't show you how to make a layer magically appear when you click a button (like I did in Tutorial 1.) See if you can igure it out. I'll give you a hint...you have to start with a hidden layer, and then modify the visibility property using JavaScript.
|