Scroll Concepts

It is a common need to be able to scroll the contents of layers to eliminate the need for long drawn out pages. You could separate your content into smaller scrollable boxes to make your pages appear lighter even though they contain much more information.

Understanding how to scroll a layer is quite easy. There are a couple ways of accomplishing it. But I will show you what I believe to be the best technique which is to use nested layers, and slide the child layer within the parent layer.

Finding the Height/Width of a Layer

The first thing to overcome is that we need to find the height (or width) of a layer that hasn't been clipped, and has not had it's height (or width) defined in it's CSS style. For example:


<STYLE TYPE="text/css">

<!--

#mylayerDiv {position:absolute; left:100; top:100;}

-->

</STYLE>



<DIV ID="mylayerDiv">



<P>Content to scroll. Content to scroll.

<P>Content to scroll. Content to scroll.

<P>Content to scroll. Content to scroll.

<P>Content to scroll. Content to scroll.

<P>Content to scroll. Content to scroll.



</DIV>

Now even though I haven't set the height or width of that layer, it obviously must have specific dimensions that can be captured - and it does.

For Netscape:

To find the width or height of a layer that hasn't had it's dimensions set, I recommend using the following:


document.layername.document.height

document.layername.document.width

I should point out that the clip.height and clip.width values will also return with the same numbers, however I don't believe it makes much sense conceptually to use the clip values since the layer has not had any clip values assigned.

For IE:

In IE you won't be able to use the clip values because they haven't been assigned (which is what Netscape should do), and you can't use document.height or width because layers in IE do not have their own document object. However there are 2 specific properties in IE which we can use to obtain the values we want:


document.all.layername.scrollHeight

document.all.layername.scrollWidth

These values are also the same as if you use the IE specific offsetHeight and offsetWidth properties.

Using the DynLayer to retrieve the Height and Width

If you're keen you will have noticed that to obtain the height and width in each browser you have to use different objects. In Netscape you target the layers' document object, whereas in IE you target the actual layer. We can use the DynLayer properties doc and event to target these objects. Recall what the doc and event properties are targeting:

In Netscape:
doc = document.layername.document
event = document.layername

In IE:
doc = document
event = document.all.layername

So if you want to use the DynLayer to retrieve the height or width you will have to use this:


if (ns4) var height = mylayer.doc.height

if (ie4) var height = mylayer.event.scrollHeight



if (ns4) var width = mylayer.doc.width

if (ie4) var width = mylayer.event.scrollWidth

I prefer to squish those into one liners:


var height = (ns4)? mylayer.doc.height : mylayer.event.scrollHeight

var width = (ns4)? mylayer.doc.width : mylayer.event.scrollWidth

I know it seems weird using an event property in there, but in actuality the event property is just a pointer to the actual layer element. I named it event because usually the only need for targeting that aspect of the layer is for defining events to it. However what we're doing is an exception.

View scrollconcepts1.html for an example that finds the height and width of a layer.

Applying This Knowledge to Scroll a Layer

If you're wondering why the heck we need to know this then maybe the following diagram will help. It is graphical representation of a layer that has text ("This is my content...") that is nested inside another layer that has been clipped (the grey square):

[diagram]

We need to know the height of that content layer because we have to know exactly how high to move it up. The distance we have to move the content layer is generally referred to as the offset height. The offset height is obviously the difference between the content layer's height and the window layer's height.

So to put this down on paper, here's the HTML/CSS for a simple scroll window:


<STYLE TYPE="text/css">

<!--

#scrollWindowDiv {position:absolute; left:180; top:100; width:200; height:150; clip:rect(0,200,150,0); background-color:#C0C0C0; layer-background-color:#C0C0C0;}

#scrollContentDiv {position:absolute; left:10; top:0; width:180;}

-->

</STYLE>



<DIV ID="scrollWindowDiv">



<DIV ID="scrollContentDiv">



<P>Top



<P>Content to scroll. Content to scroll. Content to scroll. Content to scroll. Content to scroll. Content to scroll. 

<P>Content to scroll. Content to scroll. Content to scroll. Content to scroll. Content to scroll. Content to scroll. 

<P>Content to scroll. Content to scroll. Content to scroll. Content to scroll. Content to scroll. Content to scroll. 



<P>Bottom



</DIV>



</DIV>

Then for the JavaScript, I assign DynLayers (could have used DynLayerInit() to do this automatically):


function init() {

	scrollWindow = new DynLayer('scrollWindowDiv')

	scrollContent = new DynLayer('scrollContentDiv','scrollWindowDiv')

}

And to find the difference in height between the content layer and the window layer, I used the following function:


function findOffsetHeight() {

	var windowHeight = scrollWindow.h

	var contentHeight = (ns4)? scrollContent.doc.height : scrollContent.event.scrollHeight

	var offsetHeight = contentHeight - windowHeight

	alert(offsetHeight)

}

The windowHeight value is nothing tricky. That layer is clipped so it is easy to find its height using the clip values. I included the w and h properties into the DynLayer to have a quick way of obtaining the clip width and height values. Otherwise you'd have to initialize the clip methods and retrieve the clipValues('r') value.

View scrollconcepts2.html to view this demo - it sets up the scroll structure and finds the offset height value.

Making a Scroll Mechanism

So now that we've found the offset height we need to implement a mechanism to shift the content layer up and down. To make this easy to explain I'll first show a novice way to do it.

The following code finds the offset height and has 2 functions, up() and down() which moves the content layer accordingly. Notice in those functions, it actually moves the content layer in the opposite direction - if you want to scroll down the page, you move the content layer up, and vica-versa:


function init() {

	scrollWindow = new DynLayer('scrollWindowDiv')

	scrollContent = new DynLayer('scrollContentDiv','scrollWindowDiv')



	// find offsetHeight

	windowHeight = scrollWindow.h

	contentHeight = (ns4)? scrollContent.doc.height : scrollContent.event.scrollHeight

	offsetHeight = contentHeight - windowHeight

}



function up() {

	if (scrollContent.y < 0) scrollContent.moveBy(0,15)

}



function down() {

	if (scrollContent.y > -offsetHeight) scrollContent.moveBy(0,-15)

}

Note how I've limited how far the content can scroll. When scrolling up, the content layer can only move down if it hasn't reached to top, in other words a location of 0 (where it began). When scrolling down, it can only move up until it has reached the bottom. And yes I said that correctly because remember the layer goes in the opposite direction it's scrolling. The bottom of the content layer is the negative of offsetHeight because it's always in negative territory, the following diagram will illustrate this:

[diagram]

View scrollconcepts3.html for an example with a minimal scroll mechanism.

The Advanced Way To Scroll

That last demo was a little cheesy. We can do better than that by fully utilizing the DynLayer to create a new object which slides the content up and down. Here's what I came up with:


function MiniScroll(window,content) {

	this.window = window

	this.content = content

	this.content.slideInit()

	this.contentHeight = (ns4)? this.content.doc.height : this.content.event.scrollHeight

	this.offsetHeight = this.contentHeight-this.window.h

	this.up = MiniScrollUp

	this.down = MiniScrollDown

	this.stop = MiniScrollStop

}

function MiniScrollUp() {

	this.content.slideTo(null,0,8,20)

}

function MiniScrollDown() {

	this.content.slideTo(null,-this.offsetHeight,8,20)

}

function MiniScrollStop() {

	this.content.slideActive = false

}

Seems almost too simple to work, but it does. This object accepts 2 DynLayers (window,content) and and finds the offsetHeight value just as the previous example did. To create a new instance would look like this:


function init() {

	scrollWindow = new DynLayer('scrollWindowDiv')

	scrollContent = new DynLayer('scrollContentDiv','scrollWindowDiv')

	myscroll = new MiniScroll(scrollWindow,scrollContent)

}

Then the 3 methods up(), down() and stop() are activated using the Mouse Click Animation technique. For example you can create 2 hyperlinks which are set up like this:


<A HREF="javascript:// Scroll Up" onMouseDown="myscroll.up()" onMouseUp="myscroll.stop()" onMouseOut="myscroll.stop()">Scroll Up</A>

<BR><A HREF="javascript:// Scroll Down" onMouseDown="myscroll.down()" onMouseUp="myscroll.stop()" onMouseOut="myscroll.stop()">Scroll Down</A>

The results will be when you hold the links, the content layer will slide, and when they are released the layer will stop in mid-slide.

View scrollconcepts4.html for an example using the MiniScroll Object.

This system could obviously be extended for horizontal scrolling. I'm sure if you really need to do this you'll be able to figure it out.

Taking It Even Further

The following lesson, the Scroll Object, is a rather large JavaScript object which generates an actual scrollbar by which you can scroll the content layer. Although there is a lot more code in that object, the basic functionality is exactly same as I've discussed here. If you look closely enough you will find that it generates a content layer and a window layer, finds the offset height, and implements a mechanism to scroll the layer.

Home Next Lesson: Scroll Object