HTML Markup | JavaScript | Java | Computer Sci | Home & Links

Tutorial 14 - Debugging

Bugs or programming errors occur often when learning a new programming language or when developing a new routine or utility. Ripped or cut/pasted scripts are often filled with latent bugs as well. This tutorial will hopefully give you some successful strategies for squashing any bugs that occur in your JavaScript writings or trying to get ripped scripts to work correctly.

Types of Errors

There are several types of error, each with its own method of detection and repair. The basic types of error are:

Common Errors

Errors can take some of the fun out of programming but experience will gradually eliminate (or at least make you more watchful for) certain commonly made ones. Some of the most common errors are:

Testing Methods

Brute force or 'poor-man's tests include inserting print statements and/or breakpoints where problems are suspected and running the program. Previous tutorials have shown how to use the alert window to provide feedback to the user. This same technique can be used by a JavaScript programmer to set breakpoints (ie pauses) and watch the value of variables within the code. Don't forget to use the typeof() operator to check the type of the variable. Sometimes it is more convenient to use window.status to display variable contents without pausing the program. You can dump and analyze a list of values by opening a new window and using the write() or writeln() methods.

Static tests are used to reduce known causes of programming problems. You can use lint-like tools such as jsLint to spot issues such as variable use before definition, conditions that are constant, loop range problems, etc. Watch out for utilities that are style-dependent unless you use that specific style.

Dynamic tests are used to check logic and regression (worked ok in last version) errors. They involve writing test drivers and rerunnable scripts to specifically test each object. These drivers and scripts must call each method TWICE! once with valid data, and once with invalid data.

Opera and FireFox browsers have script error displays that are accessible from the Tools menu. The Firefox add-on FireBug is an extremely useful debugging tool for script and CSS problems.

Microsoft Internet Explorer has a script error display but it must be enabled by selecting Tools -- Internet Options -- Advanced. Uncheck the box labeled 'disable script debugging' and check the box that says 'display a notice about every script error'. Note that the line number given in any error message is only approximately correct ;-[

Using the jsLint Validator

jsLint is an on-line validator that is very easy to use. Simply cut and paste your script into the text entry zone and press the JSlint button. Any error will generate a simple text message and a line number reference. This is an excellent way of getting the lint out of the wash ;-]

jsLint enforces a style that is tighter than what most browsers need but which detects many common mistakes that programmers make. Some of the guidelines are as follows:

Browser Issues

There are known recommendations for both script [ECMA] and DOM [w3.org] but some recommendations are vague and implemented differently in alternate browsers. Some texts and on-line material continue to use legacy methods which no longer work in modern browsers. The next few subtopics are a guide as to what to beware of in texts, tutorials and ripped scripts. The best way to avoid problems is to stick with the ECMA/w3.org recommendations!

DOM Level 0 Objects

The original document object had properties that could be read and/or written using script. The window.screen object also provided useful readable properties. Refer to client objects for specifics. DOM level 0 has been superceded by DOM level 1. Some examples of DOM level 1 access that should be replaced (often by CSS) are:

textColor=document.fgcolor;
document.bgColor='thistle';
colors=screen.colorDepth; // note windows. omitted as redundant!
document.myform.outbox.value=xyz; // accessing form controls 

Microsoft Internet Explorer

MSIE has properties in addition to those in the DOM model. If possible replace them with w3.org recommendation codes. For example both pixelTop and pixelLeft should be replaced by top and left as in the following:

where=styleObj.pixelLeft;  //MSIE specific
where=parseInt(styleObj.left,10); // makes integer count in pixels
. . .
styleObj.pixelLeft=where;  // MSIE specific
styleObj.left=where+'px' // guarantees measured in pixels

Note: Although MSIE defaults property dimensions to pixels, CSS specs require explicit settings (such as +'px').

MSIE has objects in addition to those in the DOM model. If possible replace them with w3.org recommendation codes. For example document.all should be replaced as in the following:

x=document.all.ident.value;  // MSIE specific
x=document.getElementById('ident').value; // DOM way

JavaScript variable names that are the same as html ids can cause error messages within MSIE. This is an undocumented enhancement in MicroSpeak. ;-] ;-]

For some reason MSIE does not like smart forms to be nested in definition lists even though it is a valid html construct. This can result in SELECT box text becoming inaccessible.

MSIE has filters and transitions which look slick but only in MSIE. Avoid the use of any proprietary feature! It is just not worth the maintenance hassle.

Browser Sniffing

The document object model (DOM) is a convenient way of understanding how to access html elements. Unfortunately major browser makers have chosen to implement some DOM objects differently. There are compatibility issues that must be overcome either by programming branches within a script, offering different pages depending on browser, defensive programming, warning users of possible conflicts, or benign neglect (playing the percentages that one browser has over 85 percent of the users). It is very important to realize that there is an issue! Decide how you will deal with these differences. And know your clients, their browsers, and their ability to upgrade to newer, better ones! Browser sniffing is commonly used:

Sniffers can be designed to either return a single value denoting the appropriate browser and version or to set global variables which flag capabilities such as DOMable, etc.

The best strategy allows for maintainability and documentation by identifying the object properties that are different or missing and building a JavaScript module of functions to deal with those variations. This isolates the selection of processing techniques to one area of your script. Further scripts allow reuse of these functions and if a newer browser requires sniffer tweaking, it is only needed in one file.

This example identifies a browser as a non-DOM model and then transfers to another page. This method can be used to skip a page (eg a fancy splash screen) entirely or transfer to a new one. My favorite technique is to redirect users of older versions to available upgrade sites (not subtle but many need this type of HINT).

var dom=document.getElementById; //browser uses DOM ??
if (dom==0){window.location.href="http://www.xyz.com/nextpage.htm";}
/* shield page from geezer browsers -- try to get them to upgrade */
if (document.layers){window.location.href="http://www.mozilla.com";}
if (document.all && !document.getElementById){ //oops - MSIE v5
   window.location.href="http://www.microsoft.com/windows/ie/";}


JR's HomePage | Comments [jstutore.htm:2009 04 19]