Thirteenth Parallel /archive/coding-for-portability1/

Coding For Portability, Part 1

By Tom Trenka, March 2002

Introduction

So...you've been playing around with DHTML for a while now, written your own site using DHTML libraries that you've downloaded from the web, and now you're thinking about writing your own.  You've looked at a lot of sources, and think you've got a good idea of what you want to do, how you're going to structure it, and more...

So you happily start coding away.  You write your own wrappers for the DOM functions, create another browser detection script, create your own methods for animation, your own event handlers, blah blah blah ;).  You've got it all together, you've debugged it as much as you can, and your site is about to be launched.

But wait! Another DHTML dude has just released this widget that you think is SO cool, you gotta have it!  You grab the code, go to incorporate it into your site, and suddenly....everything breaks!  What gives?

The problem with most DHTML APIs

You have just fallen victim to one of the biggest problems I see in JavaScript coding today - the lack of containment.  There are a lot of great pieces of code out there, but most of them fail to take into account the idea that someone might want to use it, and have a hell of a time integrating it into their own libraries.  Some APIs (such as the current incarnation of the DynAPI) try to handle it by insisting that you use the DynAPI to do your work (as opposed to writing your own and making it work side-by-side); some release their code to the public without ever thinking that you might want to use it within your own framework, and more.

There are several things that you can do to help avoid these situations.  I'm going to talk about some of them; if you think of some that I've missed, let me know - you can post messages to the 13th Forums, which I read frequently :)

But before I get into some of the techniques you can use to avoid "JS Conflict", let's review some of the basics of the language first. Those of you who know this already can skip this part (but you might find out something you missed)...

Back to the Basics

Variable Scope

To really understand why you can get code conflicts, you need to understand how scoping works in JavaScript.  Scoping is a term used to describe the execution space in which a variable is defined and evaluated. For instance, if we write a piece of code that looks like this:

<script type="text/javascript">
  var x = 0 ;
  var object = {
    x : 2 ,
    anotherObject : { x : 8 }
  } ;
</script>

You'll notice that the variable x appears three times: once in global scope, once in the scope of the object object, and once in the scope of object.anotherObject. Although the variable is named the same thing, Javascript considers it to be three different variables.

What is the global scope, then? Well, the global scope is the main "sandbox" the program is actually running in. For most of you, this means the browser window object.

This is very important to know. Because almost everything in Javascript is an object (except for the simple data types, which themselves have object equivalents), any time you create an object in JavaScript, it is added to the window (global) scope. Including functions! So if you turn around and write something like this:

function myFunction() {
  return "This is my function" ;
}

what you are in reality doing is this:

function window.myFunction() {
  return "This is my function" ;
}

Try it out. If you call myFunction(), or you call window.myFunction(), you will get the same results. Isn't that handy to know!

So, What's the problem then? Well, as far as I've seen, most of the DHTML code available on the Web is written using the global namespace (which is somewhat a synonym of scope). This means that if you've written 500K of JavaScript, odds are you've defined a lot of variables within the global namespace. (Remember, every time you create a function, you're creating a new variable!)

Emulating Class-based OOP

How do we get around this problem? It turns out that JavaScript allows you to create your own objects. There are two ways of doing this: the first, and probably the most commonly seen, is by using the function keyword in conjunction with this and prototype:

function myClass(id,title) {
  this.id = id ;
  this.title = title ;
}
myClass.prototype.getId = function() {
  return this.id ;
}
...etc...

What you are doing here is creating the JavaScript equivalent of a class. I could use this function to return to my code a new instance of myClass, by using the new keyword:

var test = new myClass('test','This is a test');

which is great! Now I can use the power of Object-Oriented Programming by modeling my "problems" using bonafide objects!

Class Modifiers in JavaScript

Wait a minute - in a strongly-typed language, we have object modifiers like public, private, or static. What do these words do, and what do they mean?

Each of these words define some sort of accessibility to the object in question. public and private usually make the "class" definition either available or not available to code outside of the containing scope. So in true OOP, if you're writing a class that you want the world to use, you would define it as public; if you didn't want the world to see it, you'd define it as private.

Unfortunately, all objects in JavaScript are considered public. This means that no matter what you do, a smart user will always be able to access any property or method you've defined in your API.

That doesn't mean they know all the properties and methods, though....

What about the static keyword? In normal OOP, a static object is one that is instantiated immediately, and cannot be created through the use of the new keyword. This holds somewhat true for JavaScript, as well-although not in the true sense of the word.

Two examples of static objects present in the core JavaScript language are the Date and Math objects (the Date object is actually both static and public; you can instantiate new Dates, but you can also call static methods of the Date object).

More on Static Objects and Properties

How can this work for you? You might have seen, in some of the examples out there, code that looks like this:

function myClass(title) {
  this.id = 'myClass-' + myClass.Count++ ;
  this.title = title ;
}
myClass.Count = 0 ;
myClass.prototype.getTitle = function() {
  return this.title;
} ;
...etc...

The property Count, which is added directly to the myClass object, is being created as a static property. This means that even though you might instantiate new myClass objects (which are in fact new Objects), the Count property remains with the original object you've created (which is myClass). This property is only created once (as is the object myClass), and so maintains a single integer - regardless of how many instances of myClass you create. In this case, the Count property is considered static.

(This technique is very handy for uniquely identifying instances of a particular class.)

Making Static "Classes"

Ok, back to the original point. We've seen one way of creating objects, by using function, this, and prototype. This method is handy for emulating a Class-based OOP structure.

What if we only want one instance of an object, though? It turns out there's another way of creating objects. This can be written in one of two ways:

Method One: C-Style syntax
var myObject = {
	property : value ,
	property : value ,
	property : value
}

Method Two: using new
var myObject = new Object() ;
myObject.property = value ;
myObject['property'] = value ;

Combining the two
var myObject = {} ;
myObject.property = value ;
myObject['property'] = value ;

...etc...

Both methods result in the same thing, so which one you use is up to you. My preference is the first method ;)...Notice the use of colons in place of the equal sign, and the use of commas in place of semi-colons...

Although you can instantiate new versions of objects defined by this method, you should only use this method of definition if you only want one instance of the object in your code. It is slightly more efficient, and helps to clarify your code for both yourself and others.

Isolating your code through Namespaces

Now that we have the background, we can address the original problem: preventing "JS Conflict" between your code and someone else's code. To do this, we take more hints from true OOP languages: we create a set of namespaces, and place our code inside of them.

What's a namespace? A namespace is a device used by more robust OOP languages that sets up the scope of the objects within the namespace. In other words, it is an additional level of scoping. For instance, in C# (the new .NET language), I could isolate my code from all of the other code by writing something like this:

public namespace TomsCode {
	public class myClass {
		...put stuff here...
	}
}

Now, in order to get to myClass, I would have to qualify it using the namespace TomsCode. Without that qualification, the compiler doesn't know what myClass means, and it barfs.

In JavaScript, you can emulate this functionality by using static objects as namespaces. For instance:

var TomsCode = {} ;
TomsCode.myClass = function (title) {
  this.id = 'myClass-'+TomsCode.myClass.Count++;
  this.title = title ;
}
TomsCode.myClass.Count = 0 ;
TomsCode.myClass.prototype.getTitle=function(){
  return this.title ;
} ;

Notice something else: I used dot notation within the function name itself. This is perfectly legal in JavaScript, and you can go as far as you want with it!

When creating a namespace, you should use the conventions that Sun put forth for namespacing in Java: start with your domain name (or something very similar), and go from there. For instance:

var org = {} ;
org.ThirteenthParallel = {} ;
org.ThirteenthParallel.Columns = {} ;
etc.

This way you are (almost) assured that your namespace is unique...and you get (unless you're dealing with a very sharp coder) to keep credit of your library, which is becoming a big problem nowadays.

What if your domain name is really long (see the above example)? Well, I know most of you DHTMLer are pretty lazy ;), so here's another factoid of JavaScript: all objects are passed by reference. So if you don't feel like typing the full name all the time, you can simply assign an alias like this:

var org = {} ;
org.ThirteenthParallel = {} ;

//Here's the alias
var _13th = org.ThirteenthParallel ;

_13th.Columns = {} ;
...etc...

(This site's domain name presents a problem-it begins with a number, which is not allowed as a variable name in JavaScript...we get around it by beginning with an underscore :)

Making sure the namespace exists

Last problem: your API is split into a number of different files. How do you know if the namespace has been created or not?

This one is fairly easy: you test for it's existence in the beginning of each file, and if it doesn't exist, you create it:

if (!org) {
  var org = {} ;
  org.ThirteenthParallel = {} ;
} else {
  if (!org.ThirteenthParallel)
    org.ThirteenthParallel = {} ;
}
..etc...

By the way, all of this would work in older versions of JavaScript too!

Conclusion?

I've introduced you to some of the basics of the JavaScript language, and shown you how you can emulate some of the more powerful features of a truly robust OOP through careful understanding of variable scope and object handling. So, for all of you API wanna-bees out there, I have one piece of advice - use the namespacing! (I'm gettin' tired of rewriting all of your code... ;D )

Well, I'm pressed for time, so that's all for now....tune in next month as.... ;)