I was never a fan of the way Dojo 0.4.x handled debugging. Sans an available console, the debugger would dump text all over the page. Dojo 0.9 no longer uses dojo.debug in favor of Firebug’s world class debugger. Because Dojo 0.4.x wrapped, extended, and essentially hid Firebug’s console, some 0.9 adopters may be even wonder what console.log is. When porting to 0.9 and doing the obligatory fishing: where did that function go, what do they call it, and is it still there?… inevitably, the first function you look for is dojo.debug, and you come across the console object in firebug.js. Dojo.firebug is a port of Firebug Lite. What this means is that if you are viewing your app on a browser without Firebug, not only will you not get runtime errors, but you’ll get a debugger… actually a console! No more messy text all over my page. Just another reason why Dojo rocks.

Firebug Quick Overview

Firebug does an excellent job of representing variable types as the following example shows:

console.log("Vars: ", [1,2,"a", "b", obj], 1, "mike", obj)

Note the comma delineated arguments. No more a+” “+b+” “+c ! Quite the contrary, if you don’t use comma delineation, you lose the strongest feature of Firebug: The object represented by a link. Objects are represented as links, and clicking on the link displays the entire object in a tree hierarchy.

One of my annoyances with Firebug is when I am traversing a very deeply-nested DOM. Firebug often remembers my place, but most of the time, like when I have made an HTML change, I have to re-click through the tree to get to the DOM node in question. However, using something like the following example:

window.onload = function(){
console.log( document.getElementById("sub2") ); 
}
header
content 2

Gives the result in the console:

FirebugLogDom

And then clicking on the result takes you to the HTML pane:

Firebug Log DOM View

Where the DOM tree has opened to the desired location, and the node’s styling can be inspected. Another tip would be to do the same thing but with the info() method. The info style gives you a quicker visual cue to your logged node in a normally crowded console window.

While console.log is the de facto standard, There are many other console types similar to log, differentiated by their styling: info, debug, warn, error. And there are some other incredible features. To find all the methods that the console uses, try:

console.log( console )

Conditional Logging

Some apps use a large number of debug statements. I personally don’t like scrolling through pages of statements looking for the one debug which I’m interested. While some debugs can be commented out, or deleted after the code has been written successfully, there are a good number of them that need to remain; maybe because you are refreshing your memory at a later date, or because some work and broke code in another part of the app, or maybe there’s a problem and you want to check the different sections to isolate its source. It would be nice to be able to switch on entire blocks of debugs without searching out, adding, or deleting all comments, one at a time.

The goal is to provide a prefix to each comment so that we know what type it is. We will use the method logIf(). We can simply add the function to the console object:

console.logIf = function(){ 	
 if(this.debugTypes[arguments[0]]){
 console.log(arguments); 	
 }
}

Then give the console an object map to compare against:

console.debugTypes = {
api:true,
loading:false,
verbose:true 
}

And call the new log commands:

console.logIf( "api", 		"The call was returned");
console.logIf( "loading", 	"The FOO script loaded");
console.logIf( "verbose", 	"Additional info", 0.9, "a", ob);

Firebug Console LogIf

As you can see, because the hash map had ‘loading‘ set to false, it didn’t show. This works well for our needs. The only problems with this approach are the statements include the prefix, and we get the array brackets and commas. We need to maintain the arguments object, but it is (strangely) not a true array and therefore lacks its methods. So we have to get creative. We can apply the arguments to the Array’s slice prototype, to cut off the first argument, then catapult the whole shebang to the log method, getting rid of the array brackets and commas:

console.logIf = function(){ 
if(this.debugTypes[arguments[0]]){ 
this.log.apply(this, Array.prototype.slice.apply(arguments, [1])) 
} 
}

Research

To find out more about Firebug’s methods, especially the useful trace, time, and profile methods, check out the Firebug FAQ.

Justin does some (dated but pertinent) exploring into Firebug Debugging.

And always of interest is Joe Hewitt, the author of Firebug. For those of you disappointed that my post did not involve the iPhone (I took the coward’s way out and ordered mine instead of standing in line in the Texas thunderstorms), Joe’s recent posts talk about debugging possibilities on the iPhone.