JavaScript guidelines

Related Topics ...

Overview: Creating Pages

HTML Guidelines

JSP Guidelines

You just finished authoring a great new model with lots of client side scripts. You test it on your machine and it looks and works great. However, when associates run your model in a different setting, they report a dozen problems related to script errors. Yet for some reason, every time you use the model it runs great. What's going on here? Most likely, you did not script defensively!

There are a few cases where the client's browser is causing the error: for example, the well-documented Internet Explorer window.open command error, "Interface not found" or the fact that you are using features not supported by a particular browser version. In many cases, however, the problems are due to your code. Remember, the web is a fragile place - a user may or may not have reliable connections, a page may fail to completely download, an image may be delayed causing an expected onload event not to fire, and so on. That is why you should always code your model defensively.

 

Get Defensive About JavaScript

Coding defensively involves always checking for the existence of an element before scripting it. For example, did you know that events and code can start executing before the page is fully loaded? This means that you may attempt to access an element before it exists. This simple issue causes a large number of script errors. Consider the following case:

The user is on a slow connection. They click a button that is supposed to process a form farther down the page. The script tries to access the element that does not yet exist and returns an error. In IE, the user usually sees "The 'xxxx' is not an object." In Netscape the error is "A JavaScript error has occurred on the page."

This problem is avoided. Before accessing the element, we need to check whether it exists in the document. Do this by testing whether or not the element is null. If the element is null, it does not yet exist in the object model.

To implementing this fix create a simple function that takes and tests an object. If the test fails, the user receives an error message, and if the test succeeds the code continues to execute as expected. Here's what the solution might look like:

function isTheObjectAroundYet(object) {
  var passed = (object!=null)
  if (!passed)
  alert("The page is not completely loaded.
  Please wait a moment and try again.")
  return passed
}

function exampleFunction() {
  var theformneededtobeprocessed = document.forms["myForm"]
  if (isTheObjectAroundYet(theformneededtobeprocessed)) {
  // its okay to script to the form
  }
}

This test is appropriate for small, localized tests. However, if you author a script that really requires the entire document to be loaded, it may be easier to just test whether the page is loaded. Before you use the window's onload event to determine whether the page is loaded, remember that the onload event does not fire until after the content and all the images on your page have been downloaded. If a user has a slow connection, this means the event may not fire for quite some time. While there are a few cases where you really do need to wait for the onload event (for example, you want the images to be loaded or you are doing dynamic content in IE4), many times you just care about knowing whether the elements are ready for scripting (images that are not yet loaded can still be scripted).

Rather than use the onload event, just make the script the last item on your page. Here's an example:

<SCRIPT>
  function doLoad() {
  // This is the script that will
  // execute when the page content is
  // loaded
  }
</SCRIPT>
<BODY>
  ...body content...
  <SCRIPT>
  // The last element in your document
  // is a script calling the doLoad()
  // function
  doLoad()
  </SCRIPT>
</BODY>
</HTML>

Let's take this technique a bit further and create a flag variable for tracking whether the page content is available. This approach can be used instead of testing each individual element. Here's how:

<SCRIPT>
  var isLoaded = false
  function doSomething() {
  if (isLoaded) {
  // run script
  }
  }
</SCRIPT>
<BODY>
  ...body content...
  <SCRIPT>
  // The last element in your document
  // is a script that sets the isLoaded
  // flag
  isLoaded = true
  </SCRIPT>
</BODY>

In summary, script defensively! Don't discount how different timing can affect your scripts since events and scripts can start executing before a page is completely loaded. Test for the existence of objects, be careful with the onload event and images.