Generated Layers

Generating layers is an easy concept to understand and it has a lot of applications, especially when developing an entire website with Dynamic HTML, or getting into more complex positioning. Using document.write() commands you can generate your CSS and DIV tags on the fly according to whatever specifications you want.

A lot of possibilities are opened when you take this approach:

I'll show how you can accomplish each of these tasks by following a few simple guidelines.

The Basics

At the simplest level, to generate a layer is very straight-forward. Just use the document.write() command to script the CSS and DIV's. The only trick is that you have to document.write the <STYLE> tag along with the CSS. If you don't, things tend not to render properly in Netscape. I've found the following set-up to be the most problem-free:


var str = '<STYLE TYPE="text/css">\n'+

'#mylayerDiv {position:absolute; left:50; top:70; width:80; height:20; clip:rect(0,80,20,0); background-color:yellow; layer-background-color:yellow;}\n'+

'</STYLE>'

document.write(str)

Usually there's no problems in IE, but I've found a few problems with Netscape that you'll want to avoid to save yourself a lot of headache.

Stick to those guidelines and you'll usually be okay.

Often its not necessary to SCRIPT the writing of the DIV's. You'll only need to do this if you're planning on making a widget of some sort, or write many DIV's that are alike in some manner. It works as expected:


<SCRIPT LANGUAGE="JavaScript">

str = '<DIV ID="mylayerDiv">my layer</DIV>'

document.write(str)

</SCRIPT>

Always try to keep the DIV's in the BODY of the document.

So a basic template to follow looks like this:


<HTML> 

<HEAD> 

<TITLE>The Dynamic Duo - Generated Layers Demo [Simple]</TITLE> 

<SCRIPT LANGUAGE="JavaScript"> 

<!-- 

 

var str = '<STYLE TYPE="text/css">\n'+ 

'#mylayerDiv {position:absolute; left:50; top:70; width:100; height:20; clip:rect(0,100,20,0); background-color:yellow; layer-background-color:yellow;}\n'+

'</STYLE>'

document.write(str) 

 

//--> 

</SCRIPT> 

</HEAD> 

 

<BODY BGCOLOR="#FFFFFF"> 



<SCRIPT LANGUAGE="JavaScript"> 

<!-- 

 

var str = '<DIV ID="mylayerDiv">my layer</DIV>' 

document.write(str) 

 

//--> 

</SCRIPT> 



</BODY> 

</HTML> 

View generate1-simple.html to see this example. View Source Code

The CSS Function

Something I've been doing to make it nicer to generate layers is to use a central function which returns the CSS syntax for you. This way you avoid having to rewrite the left, top, width, height etc. for each layer. This makes your code cleaner and will save some file size if you're planning on doing a lot of this.


// Generate CSS Function 

function css(id,left,top,width,height,color,vis,z) { 

	if (id=="START") return '' 

	var str = (left!=null && top!=null)? '#'+id+' {position:absolute; left:'+left+'; top:'+top+'; ' : '#'+id+' {position:relative; ' 

	if (width!=null) str += 'width:'+width+'; ' 

	if (height!=null) str += 'height:'+height+'; clip:rect(0,'+width+','+height+',0); ' 

	if (color!=null) str += 'background-color:'+color+'; layer-background-color:'+color+'; ' 

	if (vis!=null) str += 'visibility: '+vis+'; ' 

	if (z!=null) str += 'z-index: '+z+'; ' 

	str += '}\n' 

	return str 

} 

The usage should be pretty self-explanitory, except for a few things.

The most notable is the height value. That function does not have separate parameters for the clip values. The reason for this is because 99% of the time you want to set the height of your layer, you also want to clip the layer to that same value. For example, if you want to make a colored square, you'd have the width and the height the same as the clip right and clip bottom values. On the other hand, if you are just placing some text or an image you don't need to clip it and you don't have to set the height either. So what I've done with the CSS function is when you set the height, it also sets the clip values to (0,width,height,0) - which is the most common situation.

You can also make the layer positioned relatively by sending null for both the left and top values. In fact any of the values you don't want, just send a null value for and it won't write them. And by sending an ID of "START" or "END" it writes the appropriate STYLE tag to start or end the CSS syntax.

So its a pretty good function to use if plan on doing this stuff a lot. Here's that last layer template based on the CSS function:


<HTML> 

<HEAD> 

<TITLE>The Dynamic Duo - Generated Layers Demo [CSS Function]</TITLE>

<SCRIPT LANGUAGE="JavaScript">  <!-- 



// Generate CSS Function 

function css(id,left,top,width,height,color,vis,z) { 

	if (id=="START") return '<STYLE TYPE="text/css">\n' 

	else if (id=="END") return '</STYLE>' 

	var str = (left!=null && top!=null)? '#'+id+' {position:absolute; left:'+left+'; top:'+top+'; ' : '#'+id+' {position:relative; ' 

	if (width!=null) str += 'width:'+width+'; ' 

	if (height!=null) str += 'height:'+height+'; clip:rect(0,'+width+','+height+',0); ' 

	if (color!=null) str += 'background-color:'+color+'; layer-background-color:'+color+'; ' 

	if (vis!=null) str += 'visibility: '+vis+'; ' 

	if (z!=null) str += 'z-index: '+z+'; ' 

	str += '}\n' 

	return str 

} 

 

var str = css('START')+ 

css('mylayerDiv',50,70,100,20,'yellow')+ 

css('END') 

document.write(str) 

 

//--> 

</SCRIPT> 

</HEAD> 

 

<BODY BGCOLOR="#FFFFFF"> 

 

<SCRIPT LANGUAGE="JavaScript"> 

<!-- 

 

var str = '<DIV ID="mylayerDiv">my layer</DIV>' 

document.write(str) 

 

//--> 

</SCRIPT> 

 

</BODY> 

</HTML> 

View generate2-cssfunction.html to see this example. View Source Code

Now that we have a good way to go about generating layers, we can start getting to the whole reason for doing this. By generating layers in this manner we have a great way to substitute static numbers in your CSS for variables.

Generating Multiple Layers:

By doing loops you can use this technique to generate any number of layers in any way you want. You could generate dozens of layers in random positions, or create grids of layers. The following examples show the latter. They're straight-forward, I'm pretty sure you'll be able to follow along with the source code:

generate3-multiple.html creates a grid of blue squres - View Source Code

generate4-smartblocks (The Smart Blocks Demo) is similar to the previous but with some added functionality - View Source Code

Centering Layers

By generating your layers according to the size of the browser window you can make your layers centered horizontally, vertically or both, or you can make certain layers stretch to fill the whole page. But first you have to retrieve the size of the window. Don't be fooled into using the screen object - that applies to the user's screen resolution - it does not determine the size of the browser window. To find the actual size of the window works differently between the browsers...

In Netscape you use:


window.innerWidth

window.innerHeight

In IE you use:


document.body.scrollWidth

document.body.scrollHeight

However, these values don't take into consideration the scrollbar. Usually you'll only be concerned about the vertical scrollbar, so you can manually account for it by subtracting 20 from the width in IE, and 16 in Netscape (Netscape excludes the chrome window border). Because IE uses the body tag to find the width, these lines must be in a script that comes after the BODY tag. So a generic template for finding with window width's and height's is as follows:


<HTML>

<HEAD>

<TITLE></TITLE>

</HEAD>

<BODY>

<SCRIPT LANGUAGE="JavaScript">

ns4 = (document.layers)? true:false

ie4 = (document.all)? true:false



if (ns4) {

	winW = window.innerWidth-16

	winH = window.innerHeight

}

if (ie4) {

	winW = document.body.offsetWidth-20

	winH = document.body.offsetHeight

}



// write out the layers accordingly using the CSS function....

</SCRIPT>



DIV's go here



</BODY>

Note: this is only situation where you should ever have to write CSS within the body - generally there's no problems as long as the SCRIPT follows immediately after the BODY.

To use these values to center a layer you can do a little math to find where the left/top co-ordinate should be. For example if your layer is 100px wide and 50px tall, you'll need to use the variable (winW-100)/2 for the left coordinate, and (winH-50)/2 for the top coordinate.

And that translated into code is:


var str = css('START')+

css('centerDiv',(winW-100)/2,(winH-50)/2,100,50,'blue')

css('END')

document.write(str)

You can do similar statements to align a layer to the right or bottom of the screen. The following example places layers in all four corners and the center of the screen.

View generate5-widthheight.html for an example which uses the browser width and height extensively View Source Code

Note: That example also utilizes the Netscape Resize Fix function:


// Netscape Resize Fix

if (document.layers) {

	widthCheck = window.innerWidth

	heightCheck = window.innerHeight

	window.onResize = resizeFix

}

function resizeFix() {

	if (widthCheck != window.innerWidth || heightCheck != window.innerHeight)

	document.location.href = document.location.href

}

This piece of code can be inserted into pages which suffer the common problem when you resize the Netscape browser, all your layers loose their positioning. That code will reload the page, again using the browser width and height to check if the size has changed.

Making Self-Generating Widgets

The ultimate use for generating layers is to make JavaScript objects which generate their own layers, and apply events to themselves thereby creating a reusable "widgets". This is the tactic I used to create my Scroll and Select Objects, and it works very well.

Basic self-generating object structure:


function MyObject(name,x,y,width,height etc...) {



	// make the appropriate CSS

	this.css = css('START')+

	+css(name+'MyObject', ....)+

	+css('END')

	

	// write the CSS

	document.write(this.css)



	// make the appropriate DIV's

	this.div = '<DIV ID="'+name+'MyObject">....</DIV>'



	// but write the DIV's in the body

}

When you make instances of the objects I recommend putting each command into it's own SCRIPT tag. The reason is that early versions of Netscape 4.0 (ala 4.0, 4.01 and 4.02) have a nasty bug where if you don't do this it will hang the browser immediately. By separating them it will work properly:


<SCRIPT LANGUAGE="JavaScript">

myobj1 = new MyObject('myobj1',40,50,100,100 ....)

</SCRIPT>



<SCRIPT LANGUAGE="JavaScript">

myobj2 = new MyObject('myobj2',120,80,100,100 ....)

</SCRIPT>

An alternative to this would be to instead have a central variable which contains all the CSS for all objects - therefore you're only writing one set of a STYLE tag. In other words, instead of writing the the CSS in the object, you write the CSS outside of the object (like how I handle the DIV tags below).

Then in the BODY write the .div property of each object:


<BODY>



<SCRIPT LANGUAGE="JavaScript">

document.write(myobj1.div)

document.write(myobj2.div)

</SCRIPT>



</BODY>

Once you have the object generating the layers properly you can then make any of the layer's into DynLayers and assign events to them or whatever you can think of to make the objects interactive. View the following example to see a neat application of self-generating objects.

View generate6-widgets.html for an example which makes an outlined box and automatically makes them draggable. View Source Code

Home Next Lesson: Page Templates
copyright 1998 Dan Steinman