I just made my first Google Gadget - a Digg roundup tool. Here are some quick notes on making a Google Gadget for Ajax developers. I assume you know Ajax and also that you’ve played around with iGoogle as a user.

What's a Gadget?

  • The gadget is an XML file sitting on your server. In my case, http://ajaxify.com/run/widgets/google/diggroundup.xml. It will get cached, so effectively it must be a static file.
  • The user adds your gadget to their igoogle portal, or codes it into their own website, by specifying this URL (it may be done indirectly - via the gadget registry. You'll appear in the registry if you've submitted your gadget to igoogle.)
  • The gadget is rendered as an iframe, so you have all the usual security constraints which stop you borking the portal and other gadgets. This also means you can't communicate with other Gadgets other than via than remote calls to a common third-party server (or has anyone tried hooking them together using the iframe-fragment identifier hack? ). </ul>

    The Gadget Content

    • The XML file contains three main sections: module settings, user preferences, and the iframe content.
    • Module settings (<ModulePrefs>) are the usual demographic stuff - module name, your email, blood type, etc. Mostly optional.
    • User preferences (<UserPref>) are things users can edit by hitting the Edit button. Note that these aren't dynamic app variables like a user's search query - they are longer-term preferences like background colour and number of results to show. Each time the user changes then, the entire gadget is reloaded, so you can assume in initialisation that the preferences have already been established, and you don't need to bother checking if they're changed. The nice thing about preferences is they're declarative, so you don't have to manage input and persistence. You just say "I need a number called resultAmount from the user" (<UserPref name="resultAmount" display_name="No. of Results" default_value="5" datatype="string" ></UserPref>). Later on, you'll be able to interrogate a prefs object to get back the data.
    • The content. The content is pretty much the "body" part of an IFrame. ie. your html and ... you'll never expect this ... the javascript. You probably expected the JS to be in a separate section of the XML file, but you simply include it using an inline script tag (<script tag="text/javascript">the script...</script>, wherever you fancy. The same goes for CSS - just include a <style type="text/css"> section at the start of your script or inline it. So much for unobtrusive Javascript/CSS, but you can and should still separate things out within your page content.

    User Prefs example

    This is what the user prefs looks like: It comes from this definition: [xml] · · [/xml] and is accessed like this: [javascript] var prefs = new _IG_Prefs(__MODULE_ID__); message.style.backgroundColor = prefs.getString("bgColor"); [/javascript]

    Remote Content

    • Your gadget probably takes remote content. Remember it's a static XML file, so you can't output such content on the fly - you have to use some kind of web remoting. Because of cross-domain restrictions, you will want to use a Cross-Domain Proxy. (I experimented with direct On-Demand Javascript, but no cigar.) Fortunately, Google provides a nice API for proxying, which also caches the content you're grabbing. The main call is _IG_FetchContent(url, callbackFunc). The callback function is given the contents of URL. As mentioned in my previous post, this might cause some problems if you need to refresh the cache more than once an hour.

    Development Tips

    • igoogle can give some pretty poor error messages when you're just starting up. If there's nothing at the URL you specify, you will get a weird XML parsing error rather than a good old 404 warning. I also found if you have certain errors such as a typo in your XML file, igoogle says the gadget doesn't exist at that URL, even though in this case, it does! For those reasons, be sure to start with Google's Hello World and work from there!
    • Develop on your server directly. (If the gadget is live, you might make a test copy of it for debugging.) You don't want to be developing on your local box and continuously uploading/checking it in, because igoogle needs to fetch it from a URL each time you want to test it.
    • The secret sauce is this: The Developer Gadget. This is a special gadget provided by igoogle that, if you include it on your portal, will let you suppress caching of your app, which you absolutely have to do. It also makes it a bit easier to add a new gadget and view the gadget source code.
    • Speaking of gadget source code, you can view the entire gadget XML for any gadget you come across, so take advantage of that and avoid reinventing the wheel.
    The Developer Gadget looks like this: