Tutorial 13 - Getting the bugs outTutorial 12 - Smart Forms - Tutorial 14 - Regular Expressions 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 JavaScript ErrorsThere are several types of error, each with its own method of detection and repair. The basic types of error are:
Using Your Browser's DebuggerMicrosoft Internet Explorer has a built-in debugger but you must first enable it 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: MSIE 5 users will have to first download the debugger utility from Microsoft. Note that the line number given in any error message is only approximately correct ;-] Netscape 7 and Mozilla Group browsers have a current version of the Venkman browser that is accessible from the Tools menu option. Netscape 6 users must download Venkman from Mozilla Projects. The Venkman tutorial is a comprehensive document for learning how to use this important debugging tool Netscape 4 users must enter javascript: in the location bar to obtain an error report. Any error will be listed along with the correct line number. Some messages are very cryptic but at least you know where to start looking ;-] . Alert Windows and the Status LinePrevious 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. And sometimes it is more convenient to use window.status to display variable contents without pausing the program. Using write() and writeln() MethodsAt times you may want to analyze a list of values. You can open a new window and use the write() or writeln() methods. This is the equivalent to the use of print or printf statements in other languages. Using the JSlint ValidatorJSlint 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:
Common JavaScript ErrorsErrors 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:
Browser IssuesIn the nineties, browsers developed at a fast pace and without standards. This led to proprietary ways of doing things and the need for sniffing to see what browser was being used. But in today's world there is a known recommendation for both script [ECMA] and DOM [w3.org]. Unfortunately some recommendations are vague and consequently are implemented differently. Also texts and on-line material continue to use legacy methods which no longer work in the modern browsers. The next few subtopics are a guide as to what to beware in texts, tutorials and ripped scripts. The best way to avoid problems is to stick with the ECMA/w3.org recommendations! Netscape 4Netscape originally used a layers model for DHTML. Netscape 4
introduced a layer element which could be manipulated or positioned with
effects similar to what developed later with the div element in
the DOM model. However the manner in which this was programmed was very
different than that chosen for the DOM method. Because of both technical
and political considerations, w3.org chose to recommend using only
the DOM model. If you are required to support Netscape 4, you must first sniff for it and set a global variable appropriately. Then at any point where DHTML is used, set up a branch that uses either DOM or the layers model as needed. CSS1 technote may help those who are supporting Netscape 4. As it is so very old now, I choose not to support it! You can move Netscape 4 users off a page by using a transfer method, detect and raise an alert message, or just neglect them altogether. Microsoft Internet ExplorerMSIE has properties in addition to those in the DOM model. But it is better to find these and replace with w3.org recommendation coding. For example both pixelTop and pixelLeft can be replaced by top and left. where=styleObj.pixelLeft; //MSIE specific where=parseInt(styleObj.left); // makes integer count in pixels . . . styleObj.pixelLeft=where; // MSIE specific styleObj.left=where + 'px' // guarantees measured in pixels document.all is MSIE specific. It should be replaced with the DOM construct document.getElementById('ident'). 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. JavaScript variable names that are the same as html ids can cause error messages within MSIE. This is an undocumented enhancement in MicroSpeak. ;-] ;-] 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. An example of a vague recommendation in DOM that causes a problem in MSIE is the sequence of actions when both focus and blur (anti-focus) occur at the same time. Here is a fragment that tries to insure that a field is not empty as soon as you move to the next field. Unfortunately, in MSIE it leads to an endless loop. <script type="text/javascript">
function requiredString (control, label) {
if (control.value.length == 0)
{alert("you need to enter a string for "+label); control.focus();}
}</script>
. . .
<input name="Control1" onBlur="requiredString (this, 'Label1');">
<input name="Control2" onBlur="requiredString (this, 'Label2');">
Browser SniffingThe document object model (DOM) is a convenient way of understanding how to access html elements. Unfortunately the major browser makers have chosen to implement the DOM objects differently. And older browsers used a concept called layers to achieve many of the effects now done with the DOM model. Thus there are compatibility problems that must be overcome either by programming branches within a script, offering different pages depending on browsers, defensive programming, warning users of possible conflicts, or benign neglect (playing the percentages that one browser has over 90 percent of the users). It is 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, layered, etc. One strategy that allows for maintainability and documentation is to identify the object properties that are different and build a JavaScript module of functions to deal with the variations. This isolates the selection of processing techniques to one area of your script. Further scripts allow reuse of the functions and if a newer browser requires sniffer tweaking, it is only needed in one file. The first example identifies a browser as a non-dom model and transfers to a page that works ok using layers. This can also be used to skip a page eg a fancy splash screen) entirely if that is the author's method of dealing with variations. var dom=document.getElementById; //browser uses DOM ??
if (dom==0) {top.location.href="http://www.xyz.com/nextpage.htm"}
Variations on this theme is to check for layer users (eg Netscape 4) or MSIE specific browsers. if (document.layers) {ns=1} else {ns=0}
if (document.all) {ie=1} else {ie=0}
The next example is of an older style sniffer that relies on the basic navigator object properties available even in the older browsers. In many cases identifying the browser by name and version is sufficient. But BEWARE! Many browsers have the capabilities of identifying as another browser (aka spoofing). /* Note: sniffer must id older Netscape browsers */
ie=0; ns=0; gecko=0; opera=0;
agent=navigator.userAgent;
browser=navigator.appName;
version=parseInt(navigator.appVersion);
agent=agent.toLowerCase();
browser=browser.charAt(0);
if (agent.indexOf('gecko') != -1) {gecko=1;}
if (agent.indexOf('opera') != -1) {opera=1;}
if (browser=="N" && version < 5) {ns=1;} else {ie=1;}
Important Note: The above example is provided only for historical purposes and to indicate what you should avoid! Modern techniques use feature identification for sniffing. Tutorial 12 - Smart Forms - Tutorial 14 - Regular Expressions |