AJAX Debugging with Firebug

Firebug is a Firefox extension that includes all the tools you need for efficient debugging during the Web development process.


January 10, 2007
URL:http://drdobbs.com/tools/ajax-debugging-with-firebug/196802787

Joe is the Chief Technology Officer at Parakey Inc. and is the creator of Firebug. Contact him at [email protected].


In the early days of the Web, all you needed to know to craft web sites was HTML. More than a decade later, the situation has changed. Modern web sites are a product of several distinct technologies, and web developers must be proficient in all of them—HTML, CSS, JavaScript, and the DOM, among others.

Then a couple of years ago, AJAX came along and every web development tool on the market became obsolete overnight. Today you can no longer rely strictly on tools that were designed for the creation of static pages. This is where Firebug comes in.

Firebug, an extension I wrote for the Firefox browser (www.mozilla.com), makes web development fun again. Combined with your favorite text editor, the freely available Firebug (www.joehewitt.com/software/firebug/) is a highly productive IDE for the complete stack of AJAX technologies.

Firebug Overview

Firebug's biggest draw is its convenience. As you browse with Firefox, you can open Firebug at any time to begin working on any page. Firebug appears either as a separate window or as a small panel at the bottom of your browser. Tabbed browsing and Firebug are best friends; each tab can hold a separate Firebug session, which always reflects the current page as you browse.

Firebug breaks the page down into a set of tabs that depict its most important aspects—HTML, CSS, JavaScript, the DOM, network activity, and a console for errors and log messages. No tab is an island; Firebug lets you browse code just as you browse the Web by presenting objects as hyperlinks that can take you from one view to another.

The Firebug Workflow

Firebug knows that most developers have a tight relationship with their favorite text editor, and it isn't out to make you switch. Instead, Firebug gives you a place to experiment by playing with a live page in a separate text editor. This makes the browser's Reload button the equivalent of the Run button in a standalone IDE. For this reason, Firebug preserves the state of its views when you reload, so you can glide smoothly between your editor and browser without losing your place. However, you needn't always reload the page. Firebug lets you modify the page in place and see the result immediately.

Exploring Objects

Web development starts and ends with HTML, so Firebug gives you a lightning-quick way to find and inspect HTML elements that you are interested in. Hit the Inspect button, point your mouse at any part of the page, and Firebug unveils its place in the live HTML source. As you continue to move your mouse, Firebug follows you, which makes for a fun way to learn about the structure of web pages others have created.

An AJAX-ian web page never stands still. HTML nodes are constantly being created, modified, and removed by JavaScript. As changes occur, Firebug's HTML view stays up to date in real-time and highlights the changes in yellow. When you see things moving and changing in a page, this gives you a quick way to learn how it was accomplished.

The HTML view includes a second strip of tabs that give you other ways to inspect an HTML node. The CSS tab shows you the full cascade of CSS rules that affect the style of the selected node. One quick glance at the CSS view solves the mystery of why something doesn't look the way you expected it to.

Pixel Perfection

One issue that confounds new CSS developers is the box model, which defines the way a box is sized and where its contents are placed. The box model can be hard to pick up with the naked eye because of the transparency of margins and padding.

Firebug helps visualize the previously invisible. When your mouse moves over anything that represents an HTML element in Firebug, the element's rectangle in the page is highlighted, and its margin, border, padding, and content are each shaded a different color.

Positioning elements with CSS can also be challenging because you must always remain conscious of the container that defines its local coordinate space. Firebug helps you visualize this by using rulers and guidelines. While viewing the Layout tab, moving your mouse inside the box causes rulers to appear along the bounds of the element's container. Guidelines also appear tangent to each edge of the box so that you can see where the edges intersect the rulers.

Experimenting and Tweaking

Firebug is not just an inspector, it's also an editor. Virtually every object in Firebug can be edited inline just by clicking or double-clicking it. As you type, Firebug applies changes immediately, giving you constant feedback. All editors support autocomplete. The CSS editor autocompletes as you type, and the DOM editor autocompletes property names when you hit the Tab key.

The Firebug command line, found at the bottom of the Console tab, is no different than any command line you've used in UNIX, DOS, or Windows—except that it accepts commands written in JavaScript.

The result of executing each command is displayed in the console. The results are not just static text, they are hyperlinks. For example, if the result of a command is an HTML element, clicking the link takes you to the HTML tab with the element selected, and moving your mouse over the link highlights the element itself in the page above.

The command line is more than just a place for one-liners. You can expand it to become a full-size editor. When you're working in your external editor, you can quickly copy-and-paste code into the Firebug editor to execute them immediately and how they effect the live page. Once you've gotten the result you'd like, copy the finished code and paste it back into your editor.

Network Activity

The core idea of AJAX is that small snippets of data will be fetched from the server using a channel called "XMLHttpRequest", then used to update the page. Without Firebug, all that traffic is invisible. But with Firebug, you can observe the progress of each request and inspect the sent/received text.

There are two places that you can observe XMLHttpRequests. The first is the Console tab. Each request is logged to the console so that you can see when it took place in the flow of other messages. You can also click each request to expand it and see the headers and text in transit.

The other place to observe XMLHttpRequests is in the Net tab (Figure 1). This tab shows a real-time view of every file loaded in the page, including HTML, CSS, JavaScript, Flash, and image files. The timeline of requests is animated as each one moves across the wire, helping you understand when each one began and ended, and how large it was.

[Click image to view at full size]

Figure 1: Net tab.

Log Debugging

Firebug is not just a way for you to examine a page from the outside; it is also a place for you to send messages from within the page itself. To facilitate this, Firebug provides every web page loaded in Firefox with the console object that contains a number of functions for logging. As your script executes, you can fill the console with an ongoing stream of data for you to analyze.

The simplest way to write to the Firebug console is by calling the console.log function:


 >>> console.log("Hello World!")
 Hello World

When you want to write program data to the console, you have a number of options. First, console.log accepts an infinite number of arguments that are joined together when written to the console:


>>> console.log
    ("My aunt", auntName, 
        "has", sonCount, "sons.");
My aunt Susie has 3 sons.


The function is also capable of formatting arguments in the tradition of C's printf. The same line, therefore, can be written as:


>>> console.log
    ("My aunt %s has %d sons.", 
        auntName, sonCount);
My aunt Susie has 3 sons.

The output of console.log is an undecorated line of text. If you'd like to add some visual distinction to each line to make the log easier to read, you can try one of console.log's cousins—debug, info, warning, and error:


>>> console.debug
    ("%s - %d", title,  
        lastAccess)
Guestbook - 1342391823

>>> console.info
    ("%d new objects created", 
        objects.length)
18 new objects created

>>> console.warning
    ("The connection to %s was 
        aborted.", url)
The connection to 
    http://example.com was aborted.

>>> console.error
    ("The file '%s' could not 
        be opened.", filePath)
The file 'c:/data.txt' could 
    not be opened.


Another advantage of using debug, info, warning, and error is that they output a hyperlink to the line of the script where they were called. When you click this link, the Firebug debugger opens the pertinent script and highlights the line that caused the log message.

One problem with logging is that it can easily lead to a long list of messages that blur together, making it difficult to understand when they were called in the program flow. The console object provides the functions group and groupEnd to create nested blocks that illustrate which processes are on the stack when a message is logged.

Most programming consoles offer little more than lifeless streams of text, but the Firebug console is fully interactive. If you pass a structured object (such as a JavaScript object or DOM element) to any logging function, the result is not a textual snapshot of that object but a hyperlink. Click the link to open the relevant Firebug tab and inspect the object in greater detail. An HTML element, for instance, is shown in the live HTML inspector. A function is shown in the context of its source file in the Script tab. All other objects are shown in the DOM inspector:


>>> console.log
    ("element:", document.body)
element: body

>>> console.log
    ("header: %o",
        document.getElementById
            ("header1"))
header: h1#header1

Breakpoint Debugging

Firebug's Script tab contains a powerful debugger that lets you pause JavaScript execution on any line. You can then step forward line-by-line to analyze how the state of the program changes in real time. Breakpoints need not be triggered indiscriminately; Firebug lets you specify the circumstances under which a breakpoint is triggered.

Setting Breakpoints

The simplest way to set a Firebug breakpoint is to find the desired script in the Script tab, then click on the number of the line at which execution should stop. The debugger pauses execution upon reaching that line and shows you the current call stack (Figure 2). The watch pane on the right lets you inspect the value of local variables. If the value is an object, you can click on the object to view its properties, just as you can in all other Firebug contexts. You can also enter arbitrary JavaScript expressions and trace their values as execution progresses.

[Click image to view at full size]

Figure 2: Debugger with breakpoint set and execution paused.

While the debugger is stopped, the Firebug toolbar contains a horizontal view of every function in the call stack. Click a function to move to the file and line where its execution stopped and inspect the local variables in that context.

Conditional Breakpoints

Sometimes you'd rather not have the debugger stop every time a line is hit, but rather, only when certain conditions are true. Right-click a line number in Firebug's Script tab to open a little bubble where you can enter a JavaScript expression. The debugger pauses execution only when the expression evaluates to be true.

Error Breakpoints

One of the most common reasons to use the debugger is to investigate an error that you weren't expecting. When an error occurs in JavaScript, a detailed description of the error is logged to Firebug's Console. After reading the message, you might wish you could have been in the debugger when the error occurred so that you could inspect the objects and call stack when it occurred.

Error messages have a red button that you can toggle to set a special kind of breakpoint that stops whenever the exact error occurs again. Toggle this button on, then try to reproduce the error. Firebug switches you to the debugger when it happens.

Sometimes, Firebug can save you the trouble of having to reproduce the error. Error messages have an attached stack trace that you can see by expanding the description. The trace exposes not only the names of the functions on the stack, but also the values of each of the arguments that were passed to each function.

The debugger Keyword

When working in your editor, it's sometimes easier to locate the spot where you want to set a breakpoint than to switch to Firebug and find it separately. JavaScript has the built-in keyword debugger, which comes in handy. Put the debugger keyword on any line where you want the debugger to stop, and script execution pauses when that line is reached—just as if you'd set a breakpoint within Firebug.

Profiling

Finding and squashing bugs is only half the battle; the other half is identifying and killing performance bottlenecks. Firebug gives you two ways to measure the performance of your scripts and separate the tortoises from the hares.

Traditionally, the most low-tech way to measure performance is to record the time before and after a suspect code block and then log the delta. Firebug gives you a pair of functions, time and timeEnd, which do this:


 console.time("loading");
 loadWidgets();
 console.timeEnd("loading");

This technique works well if you already have an idea where your bottlenecks are, but what if you don't? Firebug includes a JavaScript profiler that gives you detailed reports on the performance of every function called during a given period.

There are two ways to start the profiler. The most direct is to click the Profile button in the toolbar of the Firebug Console tab. While this button is toggled, the profiler is working in the background, recording data about each function call. When you're ready to see a report, click the Profile button again, and you see a report that lists every function that was called, how many times it was called, and different statistics about the aggregate time spent in the function.

The other way to start the profiler is from code. The console object has two functions, profile and profileEnd, which let you create profile reports in between specific blocks of code in your scripts:


 console.profile();
 loadWidgets();
 console.profileEnd
    ("Loading widgets");

Conclusion

In short, FireBug lets you explore the far corners of the DOM. All the tools you need to poke, prod, and monitor your JavaScript, CSS, HTML and Ajax are brought together into one seamless experience, including a debugger, error console, command line, and a variety of fun inspectors.

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.