Building a very basic Google Wave extension

Alhough seems that all of us who have been invited recently to Google Wave have some limitations (can't invite others, don't have the "Extension Installer" wave...), we can still play a little with it and develop some wave extensions.

I've based my article in the official gadgets tutorial. You can't create robots too, but to get the feeling of how all works I prefered something very simple. I'm going to create a small extension to be able to search in the posts of Kartones.Net and list the results inside the wave (google names ‘wave' to a conversation thread).

An extension is just an XML file, containing two parts:

  1. XML nodes detailing all configuration options, name, default size, etcetera.
  2. A special XML node containing the full HTML of the wave.

Yes, as you will have noticed this is a bit clumsy and not the best option to debug, but at least works (I suggest to build the basic HTML and Javascript first in an HTML file and then add the extension XML and rename it).

I'm not going to repeat what it's perfectly explained in the tutorials, so I'll just show what my extension contains:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Kartones.Net Wave" height="50">
<Require feature="dynamic-height"/>
<
Require feature
="wave"/>
</
ModulePrefs>

<Content type="html">
<![CDATA[

]]>

</Content>
</Module>

The <Content> node will contain the HTML and javascript, we will store data inside the wave (<Require feature="wave"/>) and the extension will change its height when needed (<Require feature="dynamic-height"/>).

Our HTML will be quite simple:

<p>
<img src="http://kartones.net/images/mb_kartonesnet.gif" alt="Kartones.Net" title="Kartones.Net"
style
="vertical-align:middle" />
<
input type="text" id="searchText" size="20"
/>
<
input type=button value="Search content" id="searchButton" onClick="SearchButtonClicked()"
/>

<
br
/>
<
div id="searchResultsContainer">&bnsp;</div>

</p>

And the JS a bit more but nothing too complex:

<script type="text/javascript">

function
SearchButtonClicked()
{
var currentSearch = wave.getState().get('search', '')
;
var
new_search = document.getElementById('searchText').
value;

if
(new_search != '' && new_search !=
currentSearch)
{
wave.getState().submitDelta({
'search': new_search})
;
}
}


function
StateUpdated()
{
var currentSearch = wave.getState().get('search', '')
;

if
(currentSearch != null && currentSearch != ''
)
{
if(document
.all)
{
var resultsDiv = document.all('searchResultsContainer')
;
}
else
{
var resultsDiv = document.getElementById('searchResultsContainer')
;
}

resultsDiv.innerHTML
= "<iframe id='resultsFrame' width='600' height='600' src='http://kartones.net/search/SearchResults.aspx?q=" + currentSearch + "'></iframe>"
;

// Tells gadget to resize itself
gadgets.window.adjustHeight()
;
}
}

function
WaveInit()
{
if
(wave && wave.isInWaveContainer())
{
wave.setStateCallback(StateUpdated)
;
}
}


// Initialization code
gadgets.util.registerOnLoadHandler(WaveInit)
;

</script>

Basically, if we're inside a wave, we setup a callback handler for state changes (SearchButtonClicked() sends state changes, that are nothing else than variables) and StateUpdated() gets called when we input something and click on the Search Content button (to avoid too many calls, if we haven't wrote anything or is the same as was previously, no data is sent).

We use an iframe to render the search results, and we tell our gadget to update its height (to the iframe's one in this example).

This is the final result (with a search performed):

Screenshot

If you are on a wave with multiple users, you can all search. Just remember that as this state is shared between all participants of the wave, only one search can be active at once (last value will override previous one).

You can test this extension inside Google Wave by adding this gadget url: http://Kartones.net/Demos/015/kartonesnet_wave.xml
Gadget URL

Comments?

Posted by Kartones on 2009-10-20