Using Firebug to Aid GME Development - Google Mashup Editor - Google Code
My favorites | English | Sign in

Using Firebug to Aid GME Development

Phil Rees, GME developer
September 2007

Introduction

In this article I'll show you how to use the Firebug plugin for Firefox to help style and develop your mashups. I'll describe some of its CSS features and also show how it can be used in JavaScript development and debugging.

Firebug lets you inspect and change CSS styles in a running web application and has many additional features that come in handy when developing web applications. Among other things, you can:

  • Inspect custom stylesheets included by GME.
  • Modify in-memory stylesheets to see the changes reflected immediately.
  • Place watches and breakpoints into running JavaScript.
  • Execute arbitrary JavaScript in the context of your running application.
  • Monitor AJAX calls, showing response times, posted content, and results.
  • Profile JavaScript functions to help you identify bottlenecks and optimise your application.

For these reasons and more, Firebug has become an essential component in my web development toolkit. To demonstrate it, I'll build a simple mashup to display a feed of technology articles from Digg with a condensed display that sits comfortably in a Google Gadget. I'll also use Firebug to explore some of the code used in my DanceMaps mashup.

Creating the initial mashup

I'll start by defining a simple list and template to display a listing of Digg entries:

<gm:list data="http://www.digg.com/rss/containertechnology.xml" template="diggItemListTemplate" />

<gm:template id="diggItemListTemplate">
  <div class="diggItem" repeat="true">
    <gm:html ref="atom:title" class="title"/>
    <gm:textarea ref="atom:summary" class="summary"/>
    <gm:link ref="atom:link/@href" label="more..." class="more"/>
  </div>
</gm:template>

I've included a few classes in the template to give some semantic meaning to the data, and these will come in quite handy when building my stylesheet. Instead of creating inline styles, I'll define my styles in a separate CSS file and reference it in my source. First, I'll create a new file in a desktop-based text editor such as Notepad or TextEdit named 'diggtech.css' and define a very simple style to change the color of my application's background:

body {
  background-color: #e0e0e0;
}

Next, I'll add my stylesheet to my project's file listing by selecting "Upload Resource File" from the Editor's 'File' menu and browsing to 'diggtech.css' in the file browser that appears. I can then reference it in my source using the gm:page tag's css attribute:

<gm:page title="Digg Technology Articles" authenticate="false" css="resources/diggtech.css">

As a final step, I will save, test, and "popup" the application.

Listing of Digg entries
Figure 1: Listing of Digg entries

Exploring CSS in Firebug

Before I do any styling of my own, I'm going to take a look at the styles that the Google Mashup Editor includes when compiling applications. To do this, I right-click on a part of the page that I'm interested in and choose "Inspect Element" from the contextual menu. This opens the Firebug panel in the bottom half of the screen and highlights the HTML source for the selected element.

Firebug's 'HTML' tab
Figure 2: Firebug's 'HTML' tab

The 'CSS' tab shows:

  • which properties have been set for the selectors associated with a given element and where these properties are set
  • which inherited styles are being applied and how they are being overridden (if at all)

Back in the 'HTML' tab, I can see the classes that GME has included. These are fairly easy to spot as they begin with "gm-". From this inspection, I can make a few observations:

  • Odd items are given the class 'gm-item-odd.'
  • Even items are given the class 'gm-item-even.'
  • Selected items are given the class 'gm-item-selected.'

I can view the content of every stylesheet referenced in my source in the 'CSS' tab. This gives me more than enough information to start refining my stylesheet. To begin, I'll select my stylesheet ('diggtech.css') from the drop-down list in Firebug's 'CSS' tab and click "Edit." I can now make changes to my stylesheet and see the results of those changes rendered on the fly.

Modifying the in-memory stylesheet
Figure 3: Modifying the in-memory stylesheet

It's important to remember that all of these changes are stored in memory—none or your changes are saved, and if the page refreshes, all of your edits disappear. So whenever I get to the point where I'm happy with a change, I copy it back into my original file.

Final CSS

My finished CSS file looks like the following:

#app {
  border-top: solid #006600 1px;
}
body {
  background-color: #e0e0e0;
  font-size: x-small;
  margin: 0px;
  color: #003300;
}
.diggItem {
  border-bottom: solid #00cc00 1px;
  border-left: solid #006600 1px;
  border-right: solid #006600 1px;
  padding: 5px;
}
.gm-item-even {
  background-color: #e0ffe0;
}
.gm-item-odd {
  background-color: #ccffcc;
}
.gm-item-selected {
  background-color: #ffffff;
}
.gm-item-selected .summary {
  display: block;
}
.gm-item-selected .more {
  display: block;
}
#gm-signin {
  display:none;
}
.more {
  display: none;
}
.summary {
  display: none;
}
.title {
  font-weight: bold;
}

I am using .gm-item-selected to control the display property of the .summary and .more classes. This gives me a nice dense display suitable for use in a Gadget on my iGoogle page. In doing so, I'm integrating my class names that describe the semantics of the data (e.g. "This element is a summary") with GME's classes that describe a presentational state (even, selected, etc.). I am also setting the display of #gm-signin to "none" so that the login bar doesn't show. There's no reason to distract users with a login that doesn't expose any additional features.

DanceMaps overview

My DanceMaps mashup is designed to help people to find particular styles of dance performances and classes in their local area and when travelling. To do this, DanceMaps queries Google Base for events and activities, constructing the most relevant queries on the fly. In the next sections, I'll tell you about three ways Firebug helped in the construction of this applicaton.

Styling tabs

A simple gm: tag can generate a lot of markup. Take a simple gm:tabs declaration:

<gm:tabs target="dmContainer"/>

This is expanded at runtime into a div element containing a table with one cell for each section in the gm:container it references.

Each tab is styled with gm-section-tab apart from the currently selected tab which has an additional style: gm-section-tab-selected. Now I have enough information to start restyling the tabs. I start by uploading a couple of background graphics (blue for normal, green for selected), storing the uploads in the resources folder. I then use the styles that I've found to set my graphics as background images in the appropriate styles.

.gm-section-tab {
  background-image:url(http://dancemaps.googlemashups.com/resources/buttonbackground2.png);
  color:#E0E0E0;
  margin:0px;
  padding:2px 10px;
  display: inline;
}
.gm-section-tab-selected {
  background-image:url(http://dancemaps.googlemashups.com/resources/buttonbackground4.png);
  border:medium none;
  color:#E0E0E0;
  margin:0px;
  padding:2px 10px;
  display:inline;
}

This gives my tabs a custom appearance:

DanceMaps' custom tabs
Figure 4: DanceMaps' custom tabs

Showing and hiding loading graphics

DanceMaps is complex. Every time it loads, it retrieves data, graphics, and scripts from several servers, renders a map and several Flash components, submits a Google Base query, and manages the display of tabbed items. This takes time. To reassure the user that the application has not stalled, I have included a loading graphic which is hidden as soon as the page finishes loading.

DanceMaps' loading graphic
Figure 5: DanceMaps' loading graphic

Using Firebug's 'HTML' tab, take a look at the code for the "LoadingMessage" div. The code is grayed-out because the element is not visible at the moment.

HTML inspection with Firebug
Figure 6: HTML inspection with Firebug

If you look at the GML source for DanceMaps' index page, you'll see that the page calls a function named startMeUp() when it loads.

<gm:page title="DanceMaps" authenticate="false" onload="startMeUp()" css="resources/dmstyle.css">

You can use Firebug's 'Script' tab to see the contents of this function. I'm just using a simple DOM call to switch off the display of the loader message. I then call the setEventDateRangeToThisMonth() function to set a default date range and trigger the loading of the first set of data. This in turn causes the list to be repainted and the map to be redrawn.

Constructing queries

DanceMaps queries Google Base for dance-related events through Yahoo Pipes. Using Pipes lets me do advanced sorting and formatting before GME processes the data. It also gives me options for future refinements like feed aggregation, duplicate record removal, and spam filtering. My query builder is in changeEventListDataSource(), which checks the values of several global variables, and, if they're set, adds another clause to the bq query parameter before updating the data source of the event list.

var eventPipeBaseUrlDefault = "http://pipes.yahoo.com/pipes/pipe.run?_id=lASxbTRF3BGxSYbknkartA&_render=rss";

...

function changeEventListDataSource() {

  // Build the 'bq' query

  eventPipeBQ = "";

  if(eventFilterDateRange > ""){
    eventPipeBQ = eventPipeBQ + "[event date range:" + eventFilterDateRange + "]";
  }

  if(eventBQ > "") {
    // eventPipeBQ = eventPipeBQ + "[title:" + eventFilterKeywords + "]";
    eventPipeBQ = eventPipeBQ + eventBQ;
  }

  if(eventFilterLocation > "") {
    eventPipeBQ = eventPipeBQ + "[location:" + eventFilterLocation + "]";
  }

  if(eventPipeBQ == ""){
    eventPipeBQ = eventPipeBQDefault;
  }

  var eventDataSourceUrl = "";
  eventDataSourceUrl = eventDataSourceUrl + eventPipeBaseUrl;
  eventDataSourceUrl = eventDataSourceUrl + "&bq=" + eventPipeBQ;
  eventDataSourceUrl = eventDataSourceUrl + "&max-results=" + eventPipeMaxResults;

  // There's a problem passing spaces in URLs from GME to Yahoo Pipes.  The usual
  // escapes don't work so I've set up my pipe to use underscore.  This passes through OK.

  eventDataSourceUrl = eventDataSourceUrl.replace(/ /g,"_");

  // Set the new Data Source
  google.mashups.getObjectById('eventList').setData(eventDataSourceUrl);
  showEventListLoader();
}

My user interface components then only need to update the global variables and call the query builder. For example, the location input field calls setEventLocation() after its value has changed. This sets a global variable and changes the data source of the event list.

The dance style radio buttons call setEventBQ() when they are clicked, passing a hard-coded parameter for a Google Base bq query that returns the cleanest set of results available for that style. This again sets a global variable and calls the query builder to update the event list data source. The format of the query is not identical for different dance styles as different communities have adopted different approaches when adding their records to Google Base. For example, "Contemporary Dance" searches the description field as many relevant groups do not include the phrase "contemporary dance" in their title:

<input type="radio" onclick="setEventBQ('[description:contemporary dance]')" name="eventBQRadio"/>

In contrast, "Jazz Dance" requires that I search the event title as searching the description gives me too many irrelevant results:

<input type="radio" onclick="setEventBQ('[title:jazz dance]')" name="eventBQRadio"/>

Google Base's openness means that there is quite a bit of variation in the quality and accuracy of records. Using this flexible approach for style selection means that I am able to tailor my query parameters to deal with the reality of the data sources as they are now. A long term aim is to encourage some standardizing between data providers, so that queries can be constructed using "event type" or "style" parameters. This is likely to take some time.

Finally, I've assembled a series of routines to build appropriate date range strings to feed into Google Base bq queries. FireBug has proven very useful here by helping me monitor the contents of my variables as my code executes. To see how this works, switch to Firebug's 'Script' tab and select dmgme.js from the drop-down list. Find the function setEventDateRangeToThisMonth() and click the line number in the left hand margin. This sets a breakpoint.

Setting a breakpoint
Figure 7: Setting a breakpoint

With a breakpoint set, execution of the program will pause at that point when the function is called next and we will be able to look at the values of variables as we step through each line of code. Trigger the function call by clicking on the "This Month" radio button. (You may need to click "Next Month" and then click back again.) The script's execution will pause and the current line will be highlighted. You can now step through it by pressing F11; each line is highlighted in the left hand panel as it is executed. In the right-hand panel, you can see the values assigned to variables as you are stepping through. Once you have inspected the code to your liking, click the blue triangle to continue running the program.

Inspecting variables with Firebug
Figure 8: Inspecting variables with Firebug

This feature of Firebug has saved me a lot of time, letting me quickly find the flaws in my code, or in my assumptions about third party code that I'm trying to work with.

Firebug's Console

Finally, I want to take a look at FireBug's console and tell you about three things you can do with it.

Monitor AJAX calls

Firebug's 'Console' tab is dominated by an output area, which in my screen shot is already filled with reports about the AJAX calls that have been made to the server. In the summary of each call, you can see the protocol used, the script that made the call, the URL that was called, and the response time. Expanding one of the calls shows even more information about the parameters sent, request headers, response headers, and the full content of the response. This is extremely useful, particularly when making calls to an unfamiliar web service.

Monitoring asynchronous HTTP requests and responses
Figure 9: Monitoring asynchronous HTTP requests and responses

Ad-hoc scripting

Sometimes I like to try a piece of ad-hoc JavaScript, just to check that I have the correct syntax. FireBug lets me do this by typing JavaScript on a command line. At the bottom of the console panel is a single line input area. You can type any JavaScript you like in that area and it will execute in the context of the running application. This means that you can try out code, inspect and manipulate objects, and trigger events from the command line, completely on the fly.

Ad-hoc JavaScript
Figure 10: Ad-hoc JavaScript

I have found this useful when building an interface to make sure I'm addressing elements correctly. It has helped a lot with debugging function calls and determining whether the errors I've encountered are in the functions themselves or in the way that my interface is calling my functions.

Profiling

The console also has a nice profiling feature that can be toggled by clicking the profile button. With the profiler running you can execute JavaScript from the command line and see the time taken to execute each function. This is very handy for identifying bottlenecks and determining the relative benefits of different implementation strategies.

Firebug's Profiler display
Figure 11: Firebug's Profiler display

Conclusion

The Firebug plugin for Firefox is an invaluable tool for web development in any context, whether you're concerned with JavaScript and AJAX inspection, CSS styling, or performance tuning. Using it has helped me see undocumented details of the markup and style information Google Mashups injects in a running application. Being able to make live changes to the in-memory stylesheet has saved a lot of work and monitoring JavaScript as it executes has been a great help in eliminating errors. Observing AJAX calls and profiling JavaScript is also extremely useful, especially now that I'm concentrating on tuning the application to improve performance.

Firebug has dramatically improved my development time while teaching me a lot about the GME framework, CSS, and JavaScript. I'd recommend it to any web developer.

Resources

To learn more about the Google Mashup Editor, check out the following resources:

Author Bio

Phil Rees I'm a freelance learning technologist and web developer. I've been pushing buttons for about twenty-seven years, sometimes in the right sequence. In the last decade I've spent most of my time at Oxford University creating and maintaining marketing websites, intranet applications, and e-learning systems for Templeton College and the University's Medical Sciences Division. I'm fascinated by the effects that large scale web applications and data repositories are having on personal and cultural empowerment. Within the next year, I plan to establish a small consultancy in Vancouver, British Columbia. Until then I can be contacted through my personal website ( http://phrees.googlepages.com ).