Early in 2009, Google introduced Google Wave, a different way of communicating and collaborating. Although there are many descriptions out there about what Google Wave is and what its capabilities are, I think of Google Wave as a union of various successful technologies: wikis, e-mail, and instant messaging (IM). At the end of the day, a wave is a real-time communication environment that can include multiple participants.
When you start a wave in Google Wave, you can add human and non-human participants to the discussion. Because "non-human participant" is a mouthful, it's easier to think of these "participants" as Google Wave extensions. There are basically two types of extensions: bots and gadgets. This article doesn't cover bots — suffice it to say that a bot is an automated participant in a wave. Think of a chatbot, for example, which can read the contents of a wave, respond in its own fashion, acknowledge new participants, etc.
The extension this article focuses on is the gadget. A gadget differs from a bot in that it's a specialized mini-application that helps you perform a focused task. Without further ado, let's jump in and figure out what they're all about.
You've probably had some kind of experience with gadgets (or widgets) in the past. If you're using Mac OS X, you've probably used a dashboard widget (calculator, weather, Apple iPod controller) to complete some kind of specialized task. If you have a Google or My Yahoo! account, you've probably added widgets or gadgets to your customizable home page. Each widget or gadget offers a set of limited functionality in some area. For example, you might add a gadget that shows you what movies are playing at local theaters based on your ZIP code.
In short, a gadget or widget is any mini-application that's easy to build, easy to deploy, and easy to consume. So, what's the difference between a regular gadget/widget and a Google Wave gadget? A Google Wave gadget is designed to take advantage of the live, multi-user environment of a wave — in particular, the state object that's shared among participants.
For example, if you have 20 people participating in a wave, any gadget you add to the wave (such as allowing participants to vote Yes or No on a proposed motion à la Robert's Rules of Order) would need to interact with each participant. You might have a requirement that all participants must be able to see any vote cast by a single participant. In Google Wave parlance, a vote cast by a participant using this particular voting gadget would represent a state change, and it's the tracking of this state change that makes Google Wave gadgets different from the basic non-wave gadgets you've probably run across.
So far, nothing here is too difficult to understand. But what is a gadget physically? It's an XML file with certain instructions and an embedded content payload. This payload can be simple HTML, but most gadgets contain some kind of JavaScript logic, as well.
This may sound a bit scary if you're not familiar with XML or JavaScript. While fluency in (or at least comfort with) JavaScript coding is helpful, the XML portion of a gadget is so minimal that really what it amounts to is a simple wrapper for your code.
For example, Listing 1 provides an extremely simple gadget that says "Hello, Wave!" and nothing else. It doesn't even contain JavaScript — just HTML.
Listing 1. A simple gadget
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Hello, Wave">
<Require feature="wave" />
</ModulePrefs>
<Content type="html">
<![CDATA[
Hello, Wave!
]]>
</Content>
</Module>
|
Each Google Wave gadget has a root-level tag
called <Module> that contains all the
other elements of the gadget. Specifically, it contains a ModulePrefs section, which you can use to store
information about the module and its author, and a Content section that contains the actual content of the
gadget. So far, even if you don't know anything about XML, you're still on
pretty solid ground.
In the case of the simple example, the ModulePrefs section contains a single Require line, to force the use of the wave
feature. (There are other supported features, as well. See Resources.) The Content section contains a CDATA node with the
content—in this case, a simple statement that says
"Hello, Wave!"
When you've finalized your XML file, you need to save it to a public server of some kind. (You can use a Web server, a public folder service, such as Dropbox, or any other kind of resource). Take note of the URL (for example, http://example.com/path/to/hello.xml) because you'll need it once you're in Google Wave.
To use your new
gadget, log in to Google Wave and start a new wave. On the far right side
of the toolbar, there is a button that looks like an ellipsis (...). Click that button, then click the green
jigsaw puzzle piece. You'll be prompted to enter the URL of your gadget.
When you enter that URL and click Add, Google Wave processes the gadget you've built. If everything is OK, it displays the content in your gadget. In this case, it displays "Hello, Wave!" and nothing else.
That's really all you need to know about creating and deploying a Google Wave gadget. However, because this first example was a bit too simple, let's walk through one more gadget — this time, something a bit more complex.
Building a more complex gadget
You now know what a gadget is and how to create its content. However, the content in the first gadget was merely simple text, and you need to know a bit more than that to actually create a working gadget. This section shows you how to create the basic building blocks for a gadget using JavaScript.
Begin by creating a simple gadget that generates a random number
between 0 and 100. There may be some situations in which you need a random
number that represents a probability (as in, 30 percent or 55 percent). In this gadget,
you add some basic HTML (including a button to launch the random number
generator and an empty HTML div to contain the
generated number) and all the necessary components to make things work.
Listing 2 shows the gadget with the Content
section just roughed in.
Listing 2. A more complex gadget, part 1
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Random Number Generator">
<Require feature="wave" />
<Require feature="dynamic-height" />
</ModulePrefs>
<Content type="html">
<![CDATA[
<!-- fill this in later -->
]]>
</Content>
</Module>
|
Next,
enter the content (shown in Listing 3). This gadget will contain a bit of
HTML and some JavaScript to make things work properly. First, create
a simple bold header, an empty div to hold your
generated number, and a button that will fire off the entire process. All
of this will go inside the Content section.
Listing 3. The HTML portion of the content
<b>Generate a random number....</b>
<div id="content" style="height: 50px;"></div>
<input type=button value="Click Me!" id="btnCount" onClick="genRandomNumber()">
|
If
you've had even superficial experience with HTML, you're not in unfamiliar
territory. When a Google Wave participant clicks the button, the genRandomNumber() function runs. Next, add the
JavaScript that will make your button work within Google Wave.
Instead of showing it to you piecemeal, I'll show the entire JavaScript
portion (see Listing 4), then walk you through
it.
Listing 4. The JavaScript portion of the content
<script type="text/javascript">
var content = document.getElementById('content');
function genRandomNumber(){
var random_number = Math.floor(Math.random()*101);
wave.getState().submitDelta({'random': random_number});
}
function stateUpdated() {
if(!wave.getState().get('random')) {
content.innerHTML = ""
}
else {
content.innerHTML = wave.getState().get('random');
}
}
function init() {
if (wave && wave.isInWaveContainer()) {
wave.setStateCallback(stateUpdated);
}
}
gadgets.util.registerOnLoadHandler(init);
</script>
|
First,
you use the document.getElementById() function
to select the content div; you'll need to
access it later when you're ready to display the random number generated
by the script.
The next step is to create the genRandomNumber() function. In this case, you're using some
math functions to create a random number from 0 to 100. Save that number
to a variable called random_number, but instead
of immediately printing it to the content div,
you're going to use the built-in wave functions getState() and submitDelta() to
push the value you just generated into the overall wave state object.
Notice that essentially, you're creating a JSON key-value pair; the key is
random, and the value is whatever number
the process generates.
The next function in line is stateUpdate(). Google Wave uses this callback
function to display any changes in the state object. In this case, you're
using a simple if . . . else block to see
whether any value stored in the state is accessible via the random key. (In other words, has a number been
generated via the genRandomNumber() function?)
If there's no value, then keep the content div
empty. If there is a value, then use the innerHTML function to display whatever value might be in the
content div. Notice that you can easily
retrieve this value by using the get() wave
function.
Simple enough, but how do you make the stateUpdate() callback function work? You have to
create an init() function that will set that
callback function — appropriately enough, with a setStateCallback() function. Very
straightforward.
Last but not least, you need to invoke gadgets.util.registerOnLoadHandler(init) to fire
off the init() function. All that's left now is
to save the file as randomnumber.xml to the Web server of your
choice and add it to a wave.
You
now know how to create a gadget that actually uses the Google Wave state
object. From here, you can do all kinds of things on your own. Just
remember, you can do anything inside the Content section that you can do in a regular HTML document. If
you want to display images, then you have to add the absolute path to the
src attribute. If you are more comfortable
using jQuery or Scriptaculous instead of raw JavaScript, remember to
include URLs to those tools before you start coding away.
Learn
-
Visit Googlewave.com.
-
Read the official Google Wave gadgets tutorial.
-
The Gadgets
XML Reference can answer many of your
gadget-related questions.
-
Read the official Google Wave Gadgets API Reference.
-
Check out the Google
wave API
Overview.
-
Learn more about extensions in Google Wave by reading the Google Wave
Extensions Overview.
-
See Google Wave Extension Design Principles to learn more about the
design principles behind extensions in Google Wave.
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Stay current with developerWorks' Technical events and webcasts.
-
Follow developerWorks on Twitter.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products, as well as our most popular articles and tutorials.
-
The My developerWorks community is an example of a successful general community that covers a wide variety of topics.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
-
Make your gadget
editing easy with Eclipse or Rational Development
products.
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
- Download
IBM product evaluation versions
or explore
the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
-
Participate in developerWorks blogs and get involved in the developerWorks community.

Thomas Myer is a consultant, author, and speaker based in Austin. He runs Triple Dog Dare Media and tweets as @myerman on Twitter. You can reach him at tom@tripledogs.com.




