Entries from August 2009 ↓
August 27th, 2009 — Beginner, Development, Example
In this post, I will discuss how to create a simple gadget that has the capability to show an external web application inside a wave. The purpose of this blog is to simply show how it is possible to create a gadget that can interact with an external web application. I have a vision that by creating gadgets will help developers create an external web application that interacts with a database storage residing in a server that supports Google Wave Robots’ APIs and whenever the form is updated, it will only need to send request to its server and not inside wave and later on the robot will send an information to the wave regarding its notifications or create a wave robot/gadget that has the capabilities to add an external web applications dynamically to a wave . Writing this gadget is just as simple as coding a traditional XHTML /HTML page since Google gadgets are created using JavaScript and html.
Creating the gadget
First things first, I have created this gadget using iGoogle Gadget Editor. If you don’t have an account, you can use your Gmail account to sign in here, or if you don’t have any, you can also sign up to the given link and add the Google Gadget Editor in your iGoogle page.
Note: You can also use any text editor and upload the gadget in any available public host and add it in a wave. Or Host it in any site that has the ability to run Google gadget such as iGoogle.
First step is to construct your XML gadget specifications:
- Content Section. The <Content> section is where the real work of your gadget happens. It is where you specify the type of gadget, your programming logic, and often the HTML elements that determine the appearance of your gadget.
- User Preferences. The <UserPrefs> section defines controls that allow users to specify settings for the gadget. For example, a personalized greeting gadget might provide a text field for users to specify their names.
- Gadget Preferences. The <ModulePrefs> section in the XML file specifies characteristics of the gadget, such as title, author, preferred sizing, and so on.
You can find out more about it here.
This is how it looks after you have declared your gadget specification.
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs
title="inline_external_page" height="350" width="1280"/>
<Content type="html">
<![CDATA[
]]></Content>
</Module>
Note: Most of the gadgets written for non-Wave containers can run in Wave. However, these gadgets are not able to take advantage of the live and multi-user environment that is Wave. The main difference between Wave gadgets and non-Wave gadgets is that a Wave gadget lives in a wave and can interact with the wave.
The next step is basically like writing a primitive XHTML/HTML code. You will need to create a <div> section that will serve as the main container of your external page.
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs
title="inline_external_page" height="350" width="1280"/>
<Content type="html">
<![CDATA[
<div id="main"><!--Main container for the iframe-->
<span>Title</span>
</div>
]]></Content>
</Module>
The next step you need to do is to create an <iframe> section that will hold the external web application that you are trying to show on the container.
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs
title="inline_external_page" height="350" width="1280"/>
<Content type="html">
<![CDATA[
<div id="main"><!--Main container for the iframe-->
<span>Title</span>
<iframe name="check" id="check" height="100%" src ="https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/pcd!3aportal_content!2fcom.sap.sdn.folder.sdn!2fcom.sap.sdn.folder.application!2fcom.sap.sdn.folder.iviews!2fcom.sap.sdn.folder.crp!2fcom.sap.sdn.app.crp.mypoints?userid=J%2BrvmxDK7BA%3D" width="100%" frameborder="0">
<p>Your browser does not support iframes.</p>
</iframe> <!-- this is where contents of the links are displayed -->
</div>
]]></Content>
</Module>
Those are the steps that you need to follow on creating an inline gadget that holds an external web page. The next thing you need to do is to put it inside a wave, considering that you have already uploaded your gadget in a site/host that can hold a Google gadget.
Putting it in a wave:
First step is to login to your wave account here or if you don’t have any account, you can register here.
Once logged in; Create a new wave. Select Debug>Extensions>Add Gadget…

Place the URL of your gadget on the “Enter the URL for a gadget you want to add” text box and click Add by XML.
This is how it looks after you have successfully added your gadget inside the wave.

Those are the steps that i have done to create this simple gadget inside wave. Thank you and if there are any questions or suggestions please do feel free to leave a comment.
References:
http://code.google.com/apis/gadgets/docs/basic.html
http://code.google.com/apis/spreadsheets/spreadsheet_gadgets.html
August 27th, 2009 — Beginner, Development
When I was just starting to learn Google Wave Robots, I decided to create a robot that replaces the “at” phrase to “@” since Google does not allow Danish users to create an “@” in the current wave implementation. I’ll give you a walk-through on how I managed to create the “at-buddy.”
I started this robot using the wave robot tutorial which can be found here.
What we need to do is to replace the blip’s text while the user is typing so we need to register the event “DOCUMENT_CHANGED” in the capabilities.xml. For more information regarding capabilities.xml, you can refer to this post.
Once the capabilities are updated, we can now catch the event in our servlet. Let’s insert this in our “Process Events” method.
for (Event e
: bundle.
getEvents()) {
if (e.
getType() == EventType.
DOCUMENT_CHANGED) {
if(!e.
getModifiedBy().
equalsIgnoreCase("at-buddy@appspot.com"))
{
// get event blip
Blip blip
= e.
getBlip();
TextView textView
= blip.
getDocument();
// get blip text and replace (at) to @
String strBlip
= e.
getBlip().
getDocument().
getText().
toLowerCase();
//check if text has an "(at)"
if(match
(strBlip,
".*\\([aA][tT]\\).*").
length()>
;0)
//if(strBlip.indexOf("(at)")>0)
{
//get the index of the first "(at)"
int index
= strBlip.
indexOf("(at)");
//replace "(at)" to @
textView.
replace(new Range
(index, index
+4),
"@");
}
}
}
}
That’s it! now you can deploy your robot and try it out.
August 24th, 2009 — News
It is really fun to be a part of how much Google Wave is being hyped and talked about. I’ll try to write about some resources that I found in the last week or so. If you have other post that I should post please send them using master@masteringwave.com, and will try to put them in the next news.
- I have written a blog at SAP developer network, with information about how SAP can Google wave can collaborate. There is a demo of calling enterprise services (ES) from Wave robots.
August 20th, 2009 — Beginner
I have created an application to simulate how it is possible to make workflow applications in Google Wave. A description and reason why workflows are interesting can be found on this page. Also look at the robot wave samples to test out the solution. In this blog I’ll describe how workflows and forms can be created inside waves. The code can be found at hire.
Forms
Forms are a quite basic part of all types of application, where the application requires some structured data to handle its processing. This could be Google search page with text field to enter the query and a submit button. It is also possible to create forms in Wave applications. A form in a wave can be created with the following commands.
Blip blip
= wavelet.
appendBlip();
TextView textView
= blip.
getDocument();
textView.
appendMarkup("<p><b>Welcome to the First Wave Bank</b></p>");
FormView form
= textView.
getFormView();
form.
append(new FormElement
(ElementType.
LABEL,
"labelname",
"Your name"));
form.
append(new FormElement
(ElementType.
INPUT, NAME_FIELD
));
form.
append(new FormElement
(ElementType.
LABEL,
"labelamount",
"Borrow amount in $"));
form.
append(new FormElement
(ElementType.
INPUT, AMOUNT_FIELD
));
form.
append(new FormElement
(ElementType.
BUTTON,
"submit",
"Apply"));
First the blip we want on insert the form in is created. On the blip is it then possible to append XHTML styled text like showed.
The FormView element is created from the TextView. It is possible to add form elements to the FormView. Elements is added to the form with new FormElement(ElementType.INPUT, NAME_FIELD). The ElementType covers the different values which can be used. Second parameter is the name of the field. After that the value which could be showed is placed. This could be the text on the submit button or the text of a label.
When the user has completed the form he presses the submit button. It is then possible to validate and use the content from the forms.
FormElement name
= form.
getFormElement(NAME_FIELD
);
FormElement amount
= form.
getFormElement(AMOUNT_FIELD
);
FormElement reject
= form.
getFormElement(REJECT_BUTTON
);
String errorMessage
= "";
// check the content of a text field
if (name.
getValue() == null
|| name.
getValue().
trim().
length() == 0) {
errorMessage
+= "Please enter name:\n";
}
// check if the approve button is pressed
approve.
getValue().
equalsIgnoreCase("clicked"));
First the FormElement is retrieved using getFormElement with the field name. It will be a good idea of to use the constants variables, to make sure you time the name of the field correct.
The value of a text element can be found by using the getValue(). For buttons you can find the button by find the button with the value “clicked”.
The current limitation with forms is that you cannot create dropdown lists. An alternative could be to use Radio buttons.
For this application the robots sends responds as plain text commands back to the user. I don’t know if some other way for communication should be created. The response could be made in a blip and then this communication blip is overwritten every time the user interacts with the robot. I don’t like the usability aspect of any of the two solutions, because it is not clear to the user what have changed.
Workflows
TheWaveBank robot guides the participant’s trough a process of completing the loan application. First when the robot is added it inserts a form using the commands showed in the first java code example.
To get the response, when the users press a button, the robot needs to subscribe to FORM_BUTTON_CLICKED.
If there is multiply forms in a wave it can be difficult to find the correct for to do the processing for. The best way would be to store information about which forms where placed which blips. Alternative is to use the approach used hire, where I check for a given form element to see which form I’m processing.
It is possible to see the user how has submitted a form with the getModifiedBy() on the blip. This can be compared to how are allowed to change the form. The elements of the forms then have to be set back to the original values. It would be better if it was possible to block access to blips for certain users.
August 20th, 2009 — Example
I was talking to a friend yesterday. He is a PR person working in a political environment.
One of his tasks was to make a brochure with a description of a large venue. The venue is a collaboration between multiply political organizations in the area.
His first task was to clear his draft with his own organization. This took some time to write and find the right voice and communication. Then he had to clear the content with the other organizations. When one of the organizations got their homepage on the brochure, all the others also wanted to have their homepage on as well.
To make matters worse the brochure had to go through a graphical person, so the result of the revisions was displayed like the will be in the final brochure.
If could use Google Wave for the process. He could a have created a Wave with his proposed content. When the content was cleared in his organization, he could create a new wave with the result. The new wave could then be shared with the other organizations, and they could agree on the text. They could see what each other wanted to correct and comment on these changes.
It will not be possible to use have the graphical layout created in the Wave. But if everybody is sure about the content, then it would only be the graphical layout which needed to be discussed. If wave also was used for this, then it would be easier to agree on the changed that was required.
So if my friend and his organization were able to use Google Wave they could collaborate easier and probably also save some meetings.