DHTML library
Object Oriented Programming (OOP) and DHTML
We’ll divide these lessons in 3 pages guiding you through the building of objects and association of funtions to them. At the beginning we’ll just use pointer variables to explain what objects do, and then we’ll explain how to properly build objects to assign functions and properties to them, in order to save up some space and make the code reusable. Finally, before we start to discuss the library code, we’ll show you a simple, usable, example to move objects around the window. So here we go.
Basically, just for starting, you can see an object like a pointer to a layer. For instance, if you have layerA, using an object constructor you would avoid having to refer to that layerA as: document.layerA for ns4, document.all.layerA for ie4+ or document.getElementById('layerA') for ns5 and ie5+ depending on the browser, everytime you want to use or do anything to that layer.
Once you get this, everything is easier. :-) As an example, a simple (very improveable) object constructor could be:
if(bw.ns4) {lyrAObj= document.layerA}
if (bw.ie4 || bw.ie5) {document.all.layerA}
if (bw.ns5 || bw.ie55 || bw.ie6) {document.getElementById('layerA')}
But this is too long, so we could use booleans to shorten this a little. A boolean is a way to compare different values in a true/false condition, giving different results depending on the comparison result. The basic use are as follow: varA=(a==3)?1:0 will return varA being true if a is equal to 3 and false if not. To link different comparisons, we can use:
varA=(a==1)?"case one":(a==2)?"case two":(a==3)?"case three":0
and so on. In the first case, if a==3 varA will be true, whereas in case two will be “case three”. This way we can now look at the constructor again:
lyrAObj= (bw.ns4)?document.layerA:(bw.ie4 || bw.ie5)?document.all.layerA:
(bw.ns5 || bw.ie55 || bw.ie6)?document.getElementById('layerA'):0;
or
lyrAObj= (bw.ns4)?document.parentLayer.document.layers.layerA:
(bw.ie4 || bw.ie5)?document.all.layerA:(bw.ns5 || bw.ie55 || bw.ie6)?
document.getElementById('layerA'):0;
for nested layers (very important issue in netscape 4), assuming of course you are using Thomas browsercheck function (more on this later).
As we can see, the comparison test would be “Is the object bw.ns4 true?”. If it’s true, then the new object lyrAObj will have the value document.layerA, and so on.
Well, the example above tried to do a simple introduction to defining and using objects. But as I said before, the object constructor is a simple one. As you guessed it, if you want to make a new object you will have to write these lines for any object you would need. The solution is using a true object constructor that automatically retrieves all these informations and lets you use any object with any associated function easily.
Move method
I’ll start with a very basic example on how we can use this in the real world. Here we’ll make an object move around the page. The following code uses the regular browsercheck script, so we’ll start with this one.
//Browsercheck (needed) ***************
function lib_bwcheck(){
this.ver=navigator.appVersion
this.agent=navigator.userAgent
this.dom=document.getElementById?1:0
this.opera5=this.agent.indexOf("Opera 5")>-1
this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
this.ie=this.ie4||this.ie5||this.ie6
this.mac=this.agent.indexOf("Mac")>-1
this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
this.ns4=(document.layers && !this.dom)?1:0;
this.bw=(this.ie6||this.ie5||this.ie4||this.ns4||this.ns6||this.opera5)
return this
}
bw=new lib_bwcheck() //Browsercheck object
As you can see the browsercheck is in fact an object constructor function lib_bwcheck, several properties such as ie5 or ns4 and the instance that really builds the object bw is bw=new lib_bwcheck(). This way, when the browser reads this code it builds an object and assigns true to its actual case. For instance, if you’re surfing with ns4, the script will come out with bw.ns4 as true. This is nice to make comparisons later and use the appropiate code for each browser.
Now we are going to write the layer into the body. We make a div called divTest in the HTML code like this:
This is a test div!
<div id="divTest" style="position:absolute; left:10; top:800; background-color:red; ; color:white"> This is a test div! </div>
Then below that we add this code (inside a script tag):
function lib_moveIt(x,y){
this.css.left=x;
this.css.top=y;
}
function lib_obj(obj){
if(bw.ns4)this.css=document.layers[obj]
else if(bw.ie4)this.css=document.all[obj].style
else if(document.getElementById) this.css=document.getElementById(obj).style
this.moveIt=lib_moveIt
return this
}
oDiv=new lib_obj('divTest')
And we call the moveIt method of the object to move the object around like this with the arguments x and y which are the left and top values we want to move the object to:
That worked very well now didn’t it? The big advantage here is that this is very reusable code and you make as many objects like this you want in a page.
This code should more or less explain itself. It’s the same as the previous examples except that we make the this.css property, which is different depending on which browser the user is using. You’ll have to see this as the path the browser takes to reach the layers, which of course, due to the differences among browsers and their implementation of DOM, is different for each. The this.css points to the already existing object in the browser, so we can use the already existing properties and methods of that object like we want. Like in the lib_moveIt function where we use the regular .left and .top properties of the object.
Let me try and explain what happens here, first if the browser is Netscape 4 this is how it will behave/look:
function lib_moveIt(x,y){
this.css.left=x
this.css.top=y
/*
When this function is called with NS4
(NOTE: This is a function, but it's a method of the lib_obj objects!)
this.css = document.layers["divTest"]
Therefore when I assign a value to this.css.left I am basically
just assigning a value to document.layers["divTest"].left
*/
}
function lib_obj(obj){
if(bw.ns4)this.css=document.layers[obj] //NS4
else if(bw.ie4)this.css=document.all[obj].style //IE4 - IE5
else if(bw.dom) this.css=document.getElementById(obj).style
this.moveIt=lib_moveIt
return this
}
oDiv=new lib_obj('divTest')
/*
NS4 Will return an object with these properties and methods:
oDiv = [object object]
oDiv.css = document.layers["divTest"]
oDiv.moveIt=lib_moveIt (calls the lib_moveIt function)
*/
If you have Explorer 4 it will look like this:
function lib_moveIt(x,y){
this.css.left=x
this.css.top=y
/*
When this function is called with IE4
this.css = document.all["divTest"].style
Therefore when I assign a value to this.css.left I am basically just
assigning a value to document.all["divTest"].style.left
*/
}
function lib_obj(obj){
if(bw.ns4)this.css=document.layers[obj] //NS4
else if(bw.ie4)this.css=document.all[obj].style //IE4 - IE5
else if(bw.dom) this.css=document.getElementById(obj).style //NS6
this.moveIt=lib_moveIt
return this
}
oDiv=new lib_obj('divTest')
/*
IE4 Will return an object with these properties and methods:
oDiv = [object]
oDiv.css = document.all["divTest"].style
oDiv.moveIt=lib_moveIt (calls the lib_moveIt function)
*/
If you have Explorer 5+ or Netscape 6 it will look like this:
function lib_moveIt(x,y){
this.css.left=x
this.css.top=y
/*
When this function is called with IE5+ or NS6
this.css = document.getElementById(obj).style
Therefore when I assign a value to
this.css.left
I am basically just assigning a value to
document.getElementById(obj).style.left
*/
}
function lib_obj(obj){
if(bw.ns4)this.css=document.layers[obj] //NS4
else if(bw.ie4)this.css=document.all[obj].style //IE4 - IE5
else if(bw.dom) this.css=document.getElementById(obj).style //NS6
this.moveIt=lib_moveIt
return this
}
oDiv=new lib_obj('divTest')
/*
IE5+ or NS6 Will return an object with these properties and methods:
oDiv = [object]
oDiv.css = document.getElementById(obj).style
oDiv.moveIt=lib_moveIt (calls the lib_moveIt function)
*/
We know that this might be hard to understand, but really don’t know what more to say. Try and play with this code, add and remove properties and methods to figure out how this works.
We’ll do 2 more things before we look at the “real” code of the library. First off, taking the code from the top of this page and compress it a little to make it a little nicer:
function lib_moveIt(x,y){
this.css.left=x; this.css.top=y
}
function lib_obj(obj){
this.css=bw.ns4?document.layers[obj]:bw.ie4?document.all[obj].style:
bw.dom?document.getElementById(obj).style:0; //This is one line!
this.moveIt=lib_moveIt
return this
}
oDiv=new lib_obj('divTest')
We had previously seen the use of booleans, so this should sound logical. It’s basically the same as using if / else statements but shorter and more elegant.
Then we will use the prototype property of any javascript object that makes it possible to add methods and properties to an object constructor (and therefore to ALL objects created with that constructor), without being defined inside the constructor itself. This is helpful because we can create objects and then assign new properties to them. In this case the constructor is the lib_obj function. This makes it simpler to add functions:
function lib_obj(obj){
this.css=bw.ns4?document.layers[obj]:bw.ie4?document.all[obj].style:
bw.dom?document.getElementById(obj).style:0; //This is one line!
return this
}
lib_obj.prototype.moveIt = function(x,y){
this.css.left=x; this.css.top=y
}
oDiv=new lib_obj('divTest')
As you can see the object constructor doesn’t need the this.moveIt= lib_moveIt anymore. The syntax is the following:
constructorname.prototype.methodname = function(arguments) { }
The code
Go to project library to see the code
When you have looked through this one you can go to my new library section where you can go trough each function and get them explained.