Web Developer's Virtual Library: Encyclopedia of Web Design Tutorials, Articles and Discussions


WDVL Newsletter

Active Server Pages
JSP/Java Servlets
Microsoft SQL Server
Daily Backup
Dedicated Servers
Streaming Audio/Video
24-hour Support    

jobs.webdeveloper.com

Hiermenus


e-commerce
Partner With Us















Developer Channel
FlashKit.com
JavaScript.com
JavaScriptSource
Developer Jobs
ScriptSearch
StreamingMediaWorld
Web Developer's Journal
Web Developer's Virtual Library
WebDeveloper.com
Webreference
Web Hosts
XMLfiles.com

internet.com
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers


Creating Cross-Browser Objects

February 1st 1998

I wrote an article in the August issue of the then NetscapeWorld online magazine (now called Netscape Enterprise Developer) that talked about cross-browser compatibility with Dynamic HTML and other Web technologies (access the article in the resource section). At that time I talked about my first implementation of cross-browser objects, scripting objects that hide the browser implementation details from the web developer.

The premise was simple: if both browsers support moving an element by changing the value for the left attribute for the element, but they use different techniques, then create a new object that contains the browser-specific code and provide a method that results in the same behavior. One object is then created for Microsoft Internet Explorer, and one object for Netscape Navigator.

I expanded on the concept in a book I wrote for IDG Books on Dynamic HTML (the "Power Guide to Dynamic HTML", published by IDG Books, January, 1998). In the book I created scripting objects that hid the details of Netscape's and Microsoft's positioning implementation, and then used these objects to create some fairly complex DHTML applications.

I expanded on these cross-browser objects for use at my Web site, adding new properties and methods, and used these objects as the base for building higher level complex animations and actions. The objects are created in JavaScript, and using a technique that is ECMAScript compliant (resource section) and that both Microsoft and Netscape support.

My first step in designing the objects was to determine which methods and properties the objects would have. One rule I follow when creating objects is always, always start simple. A successful object is one in which all changes are positive changes. This means that methods and properties are never removed from the object but added, only. Based on this, changes can be made to the object without having any impact to the applications already using the objects.

The cross-browser objects I am creating for WDVL are to be used to create two different types of "index card" like applications. These applications will show and hide content as well as move the content around the page. Following from the "keep it simple" premise, and the known requirements, the WDVL cross-browser objects include pointers to functions to hide and show the element and move the element based on setting its left or top values. I also wanted to access the element's current left and top value, to make an incremental movement rather than an absolute movement, and created methods for getting these two values.

To create the objects, I first needed to create a function which acts as the constructor for each object. This function would take a reference to an HTML element and assign this reference to a specific object property. The function would also set pointers to functions that act as object methods. The actual methods are created a little later in the article. The code for the Navigator object follows:

// create NS cross-browser object
function wdvlNewObject(obj) {
	this.obj = obj;		
			// cannot assign object directly to "this"
	this.objHide = objHide;
	this.objShow = objShow;
	this.objGetLeft = objGetLeft;
	this.objGetTop = objGetTop;
	this.objSetTop = objSetTop;
	this.objSetLeft = objSetLeft;
}

The function is called wdvlNewObject, and it contains an object property holding the reference to the object as well as pointers to the six methods discussed earlier. Why methods instead of properties? Assigning a new value to a property does not activate a change. The change is activated when the property of the underlying object is changed, not our derived cross-browser object. Additionally, I also follow the OO-based recommendation of setting and accessing an object's properties through methods rather than through direct access to the properties, a process referred to as data encapsulation. With this approach, changes to the underlying objects can be made without impact on the applications using the objects.

The IE 4.x object is very similar to the Navigator object, except that a reference to the style property/object is kept, not a reference to the object itself:

// create IE DHTML equalizer object
function wdvlNewObject(obj) {
	this.obj = obj.style;
	this.name = obj.id;
	this.objHide = objHide;
	this.objShow = objShow;
	this.objGetLeft = objGetLeft;
	this.objGetTop = objGetTop;
	this.objSetTop = objSetTop;
	this.objSetLeft = objSetLeft;
}

I could have set the object reference directly to the object, and there are advantages to this approach. By setting the reference directly to the object, I can then access and change properties other than just those available through the style object/attribute. However, following from the original premise of keeping the object simple, at this time the object reference is set to the object's style property/object. When these objects are used to create the second of the index card applications, you will see how the underlying object is changed for the IE 4.x object without having to change any application using the objects, the real strength of using object technology.

Now that the object constructor has been created, the methods for each browser need to be coded. These are very simple methods, with one line of code, at most. The methods for the Navigator object are:

// hide element
function objHide() {
	this.obj.visibility = "hidden";
}

// show element
function objShow() {
	this.obj.visibility = "inherit";
}

// element's left position
function objGetLeft() {
	return this.obj.left;
}

// element's top position
function objGetTop () {
	return this.obj.top;
}

// set element's top position
function objSetTop(top) {
	this.obj.top = top;
}

// set element's left position
function objSetLeft(left) {
	this.obj.left = left;
}

And the methods for the IE 4.x object are:

// hide element
function objHide() {
	this.obj.visibility = "hidden";
}

// show element
function objShow() {
	this.obj.visibility = "inherit";
}

// element's left position
function objGetLeft() {
	return this.obj.pixelLeft;
}

// element's top position
function objGetTop () {
	return this.obj.pixelTop;
}

// set element's top position
function objSetTop (top) {
	this.obj.pixelTop = top;
}

// set element's left position
function objSetLeft(left) {
	this.obj.pixelLeft = left;
}

The final step to take to create the objects is to create a routine that traverses the Web page and pulls the objects into an array. This routine is then called during the page onLoad event, to instantiate the cross-browser objects. The instantiation routine for Navigator is:

// function to instantiate equalizer objects
function wdvlCreateObjects() {
   wdvlObjs = new Array(document.layers.length);
   for (i = 0; i < document.layers.length; i++)      
      // check to see if Netscape assigned block
      if (document.layers[i].id.substring(0,3) != "_js") 
   	   wdvlObjs[document.layers[i].id] =
   		 new wdvlNewObject(document.layers[i]);
}

The function uses the Navigator Layers built-in array to access all layer elements. A layer element is one defined using the LAYER tag, or positioned using a CSS-P style sheet. If a LAYER element is used, the element is named using the NAME property. For DIV blocks, the element is named with the ID proprety. As I iterate through the array, I only pull in elements that have been given a name, as the WDVL cross-browser objects are only accessed by their names. However, Netscape assigns a default name for all objects that do not have names, a name that begins with the prefix "_js". So, in the instantiation code, I check the first three characters of the identifier to see if it matches this prefix, and if not, I include the layer in my array of objects.

By only including named layers in the cross-browser object array, the developer can then control which elements become cross-browser elements or not, based on the simple technique of giving the element a name.

The IE 4.x setup function is shown next. Unlike Navigator, Microsoft pulls in all of the HTML elements within the page into its collection named all. The routine fine tunes which elements are selected by only going for the DIV block elements, and only those that have names:

// function to create named and unnamed objects
function wdvlCreateObjects() {
   theelements = document.all.tags("DIV");
   wdvlObjs = new Array();
   for (i = 0; i < theelements.length; i++){
      if (theelements[i].id != "") {
	   wdvlObjs[theelements[i].id] =
   			new wdvlNewObject(theelements[i]);
	   }
      }
}

Once the object code for each browser is created, it is saved in its own JavaScript source code file, ie4_obj.js for the IE 4.x object and ns4_obj.js for the Navigator 4.x object. Next up is how to incorporate these objects into a Web page.

Browser-specific Dynamic Positioning Differences
Creating Cross-Browser DHTML Objects
Including the cross-browser objects into a page



Up to => Home / Authoring / DHTML / CB / Objects




Jupiter Online Media: internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and Jupiter Online Media

Jupitermedia Corporate Info


Legal Notices, Licensing, & Permissions, Privacy Policy.

Web Hosting | Newsletters | Tech Jobs | Shopping | E-mail Offers