Week 5

Links for Week 5

Case Study-Forms and JavaScript

Click here to see a case study of form data maintenance and initialization using JavaScript.

Objects in JavaScript

Until now you have used JavaScript in much the same way as you would use a non object-oriented language. JavaScript, while not strongly typed, does allow you to create objects using a constructor. As in other object-oriented languages, you can associate functions with these objects. Click here to view a page creates an object of type auto and calls on the auto print function to get a string that describes this auto.

The constructor for the type auto and the print function are show here.

<SCRIPT LANGUAGE = "JavaScript">
<!--
function auto(make, year, color)
{
	this.make = make;
	this.year = year;
	this.color = color;
	this.toString = print;
}
function print()
{
   return "Your car is "+this.make+" from "+this.year+" in "+this.color;		
}
function doIt(make,year,color)
{
	var car = new auto(make,year,color);
	document.carForm.out.value=car.toString();
}	
//-->
</SCRIPT>

The function auto is the constructor of an object of user type auto. This function takes three parameters that represent the data items for autos. The last assignment statement in the constructor creates the association of the print function with toString. The print function is clearly tied to the type auto, or any object that has the fields make, year and color.

To create a variable of type auto, you need only add this line

	var car = new auto(make,year,color);

to a function that requires this variable.

There are no type definitions, so you cannot directly create child classes. You can however call on the constructor and other functions from a class to create de facto children. Suppose you decide you need to include information about the engine of your auto. You can change auto, but if you package auto to use in many pages, this would require redoing all of your pages. Instead you can locally create a new type "moreCar" that calls on the constructor for auto and uses the print function for auto. The code for this is below. Open the page "jsobjectfun.htm" in Red Edit and notice that the appropriate functions have been added. Uncomment the input text for engine and change the onClick event handler to:

onClick="doIt(make.value, year.value, color.value,engine.value);

Notice that the doIt function already has the engine parameter. If parameters are not used there is no error, but values are assigned to parameters in order, so if you only want the first and fourth parameters used, you have to provide dummys for the second and third.

function moreCar(make,year,color,engine)
{
	auto(make,year,color);
	this.engine = engine;
	this.toString=printMore;
}

function printMore()
{
	var out = print();
	out += " engine "+this.engine;
	return out;
}

Dynamic HTML (DHTML)

Introduction

DHTML encompasses many different methods for creating non static pages. As you have seen, you can use animated gif files, or generate you pages using JavaScript to write the page. There are other programs such as Flash that you can use to create animation on web pages, but you can also use the CSS-P visiblity property to create many interesting effects including animations that load quickly. When you change the properties of a style dynamically using a JavaScript, you must retrieve the object from the browser. You only need to use the following if you are changing the style of an item. Most of this discussion is based on information found in the following two web pages.

  1. The Universal HTML Presentation Template: An Example of Crossware Using JavaScript, Style Sheets, and Cross-Browser Dynamic HTML (Version 3.0) Eric Krock
  2. THE JAVASCRIPT APOSTLE CSS-POSITIONING -- THE DYNAMIC HTML NEUTRAL ZONE By Danny Goodman
  3. Animated presentations on dynamic html

Beware of the following cautions before you go any farther.

Warnings

  1. Always use all lower case letters and digits when naming objects to be accessed in a JavaScript
  2. Before you can alter a style, it has to have position as one of its properties.

Browser Oject Models

To alter the style of an element of a web page, you must create a variable that represents that object. The two major browsers store page objects in different structures and reference styles in different ways. Internet Explore uses the collection all to keep track of all of the items in a document. Objects in a web page can be retrieved by using that objects ID as a subscript in all. So if you have an object with ID, "div1" (notice all lower case and digets), you can variable for that object in Internet Explorer by using the following variable definition.

var myDiv = document.all["div1"];

Netscape uses the collection layers to catalog objects in a web page. To retrieve the same object in Netscape you need to write:

var myDiv = document.layers["div1"];

To add a little spice to the problem, earlier versions of Internet Explorer (and current versions for backward compatibility) used a function getElementById to retrieve an object.

Determine the Browser

Clearly before you venture into this tangle of browser objects, you have to have a way to retrieve the browser type. Fortunately all major browsers have an object called navigator that contains information about the browser in standard locations. The browser type is contained in the member variable userAgent and the version of the browser is contained in the member variable appVersion. It is useful to create a browser object with information about the versions that is needed to retrieve and use information about a page element. This constructor comes from the Krock article and related pages.

//constructor for browser
function browser()
{
      // convert all characters to lowercase to simplify testing
    var agt=navigator.userAgent.toLowerCase()

    // *** BROWSER VERSION ***
    this.major = parseInt(navigator.appVersion)
    this.minor = parseFloat(navigator.appVersion)

    this.nav  = ((agt.indexOf('mozilla')!=-1) && ((agt.indexOf('spoofer')==-1)
                && (agt.indexOf('compatible') == -1)))
    this.nav2 = (this.nav && (this.major == 2))
    this.nav3 = (this.nav && (this.major == 3))
    this.nav4 = (this.nav && (this.major == 4))
    this.nav4up = this.nav && (this.major >= 4)
    this.navonly      = (this.nav && (agt.indexOf(";nav") != -1))

    this.ie   = (agt.indexOf("msie") != -1)
    this.ie3  = (this.ie && (this.major == 2))
    this.ie4  = (this.ie && (this.major == 4))
    this.ie4up  = this.ie  && (this.major >= 4)

    this.opera = (agt.indexOf("opera") != -1)
}

Krock also names the browser object he creates is, so that you get conditionals like if (is.nav4up) that read well in the code. The browser becomes one of the global variables in the script handling objects and is defined by the following line.

var is = new browser();

Creating Objects

Once you know the browser, you can create an object to represent a page element. The following constructor, based on many different constructors with a few of my own addons, creates such an object from the ID of an element.

var visible;
if(is.nav4up)
	visible = "show";
else
	visible = "visible";

function getVisible()
{
	return this.css.visibility == visible;
}

function show()
{
	this.css.visibility = "visible";
}

function hide()
{
	this.css.visibility = "hidden";
}

function moveTo(x,y)
{
	this.x = x;
	this.y = y;
	this.css.left = x;
	this.css.top = y;
}

function moveRel(dx,dy)
{
	this.x +=dx;
	this.y += dy;
	this.css.top = this.y;
	this.css.left = this.x;	

}



function makeObject(obj,x,y)
{
	if (document.getElementById)
		this.el = document.getElementById(obj);
	else if(is.nav4up)
		this.el = document.layers[obj];
	else if (is.ie4up)
		this.el = document.all[obj];
	else 
		this.el = 0;
	// this has to be done separatly 
	// even if it looks like it should be placed above 
	// in the appropriate sections.
	if(is.nav4up)
		this.css = this.el;	
	else if(is.ie4up)
		this.css = this.el.style;
	//set object functions
	this.isVisible = getVisible;
	this.show = show;
	this.hide = hide;
	this.moveTo = moveTo;
	this.moveRel = moveRel;
	// set position if one is specified
	if (makeObject.arguments.length>1)
	{
		this.x = x;
		this.y = y;
	}

}

Notice that to change the style of an element in Netscape you can simply set the value for that element while in Internet Explorer you have to access the member variable style. This difference is address by the object member css. Visiblility is the most frequently altered style. If you have created an element variable el using makeObject, you could set the visibility to "visible" with the following assignment.

el.css.visibility="visible"

One problem with this is after el has its visibility set, if you want to test if el is visible, you cannot just write

 if (el.visibility == "visible")

since Netscape stores "visible" as "show" while Internet Explorer uses "visible". To avoid this problem, create a global variable, visible, set to "visible" or "show" depending on which browser is being used. To avoid some of these problems this version of browser object also has the functions "isVisible" to test visibility and "setVisible" to set the visibility. Check the use of these functions in a simple page, "elementtest.htm" you can look at by clicking here. The function hideDivText is called on a button click with the button as the sole parameter. The divBlock is created using makeObject in the function start called by the onload event. You will see more complicated uses for this strategy a little later.

function hideDivText(obj)
{
	if(divBlock.isVisible())
	{
		divBlock.hide();
		obj.value="Show Text"
	}
	else{
		divBlock.show();
		obj.value="Hide Text";
	}
}

Since the object constructor and visibility functions are frequently needed, this code is package in a script file objectmaker.js.

Inclass 8

Show two different pictures. Click here to get this project.

Other CSS-P Properties

Some properties of style can be set in one browser but not others, and some browsers have different names for properties (see table below). Add a function to the object that will change the background color. Make sure it works in both browsers. How well does it work. Notice color is not listed. Try changing color. Check the results in Internet Explorer and Netscape. What happened?

Layer vs. style CSS-P properties (Table 2 in the Goodman page listed above)
Navigator layer property Comments IE style  
property
left The Microsoft style object has a left property, but the value is a string including the unit of measure (for example, "20px"). To perform math on the left property of the style object, use the pixelLeft property.  pixelLeft
top The same situation as with left and pixelLeft. pixelTop
visibility The Netscape layer object returns possible values of show, hide, and inherit; the Microsoft style object returns visible, hidden, and inherit. But the layer object can be set to the style object property value names without complaint. visibility
zIndex 100 percent agreement on the integer values of this stacking order property. zIndex
background Value is a URL of a background image. background
bgColor Different property names, but the same color values, including Netscape plain-language names. backgroundColor