2011/11/19
19 Nov, 2011

Writing Google Gadgets – A Tutorial – Part 01

  • Samisa Abeysinghe
  • VP, Training - WSO2

Curated on 08th March 2012

Writing Google Gadgets – A Tutorial – Part 01

We will start small and simple and then gradually move onto
more useful and advanced features in these tutorials. Along the way, we will
evolve a gadget from ground up to a user configurable, comprehensive gadget. We
will use WSO2 Gadget Server as the hosting environment to test the gadget,
along the way. WSO2 Gadget
Server
adheres to the Google Gadget Specification [1], thus, allows hosting
gadgets written for Google gadget container.

Writing Google Gadgets – A tutorial – Part 02

        Processing Fetched HTML with JavaScript

        Using TEXT vs DOM Content Type when Working with HTML

        Using External JavaScript Libraries

Writing Google Gadgets - A tutorial - Part 03

        Setting User Preferences

                Using enum Data Type as an Options List

                Using Boolean Data Type

                Integer Settings with String Data Type

                Setting Preferences from Within the Gadget

        Dealing with Views

Writing Google Gadgets – A tutorial – Part 04

        Versatility of Google Gadgets as a Presentation Instrument

        The Complete Google Gadget Code

        Tips and Tricks

                Error Handling

                Incremental Development

                When Things go wrong: F12

                Always Test with IE

                Use an IDE


Google Gadgets Basics



Anatomy of a Gadget

The source code of a gadget is written in XML. In other words, a gadget is an XML document. The root element of a gadget is <Module>.
And a gadget consists of three main sections:

  1. Gadget Preferences: Specifies characteristics of the gadget. Wrapped with <ModulePrefs> XML element. Mandatory.
  2. User Preferences: Defines controls that allow users to specify settings for the gadget. Wrapped with <UserPrefs> XML element. Optional.
  3. Content Section: Specifies the content of the gadget, often using HTML and JavaScript programming logic. Wrapped with <Content> XML element. Mandatory.

The following diagram portrays the overall gadget structure, which consists of the three main sections described above.

Anatomy of a Gadget

You can find more information on the anatomy of a gadget on Google gadget basics documentation page [2].


Basic Gadget Example – Hello Gadget

Here is a sample gadget that demonstrates the three elements of a gadget.

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
    <ModulePrefs title="Hello Example" />
    <UserPref name="Name" display_name="Your Name" default_value="World" />
    <Content type="html">
     <![CDATA[
       Hello, <span id="nameSpan"> Name goes here </span>
       <script type="text/javascript">
          var prefs = new gadgets.Prefs();
          document.getElementById('nameSpan').innerHTML = prefs.getString("Name");
      </script>
      !
     ]]>
    </Content>
</Module>

In this gadget, we set the gadget title in the gadget preference section on line 3. The title is "Hello Example".

On line 4, we set a user preference with the preference name being "Name", display name being "Your Name" and default value being "World".

In the content section, we print a greeting message, based on the value set by the user for Name preference field.

We have a span with the ID "nameSpan", preceded by "Hello," on line 7.

From lines 8 to 11 we have some JavaScript logic to pick the name
preference value, and set the "nameSpan" with the preference value.

As the default value for "Name" is "World", the gadget would greet with "Hello, World!" when it loads initially, and if the user sets the name preference, would greet accordingly.


Hello Gadget in Action

The following figure shows how the gadget behaves in action. This simple gadget is capable of picking the user settings and greets the user accordingly. Later in this tutorial series, we will explore in more detail, how to make use of user preferences and make gadgets configurable.

Hello Gadget Example

To try this gadget with WSO2 Gadget Server, you can upload the gadget to the gadget repository, on Gadget Server management console, by going to

Home > Manage Gadget Server > Gadget Repository > Add / Modify Gadget

You can find documentation on uploading a gadget to gadget repository [3], adding the gadget to the portal [4] and if you are a newbie to WSO2 gadget server – how to install [5] on WSO2 developer portal.


Pulling Information from the Web into a Gadget

Now that we know the basic structure of a gadget, let’s move on to a more useful use case.

One of the common use cases is to pull information from the Web and display information within a gadget.
Often we might want to extract some useful information from the Web URL, and display on the gadget, rather than showing the Web data as they are.
However, before diving into the complex case, let’s look at the simple case of pulling a page and displaying as it is.


Content Type URL Gadgets

The simplest way to fetch content from a URL and display is to set the <Content> elements "type" attribute to "url" and provide
the URL location with the "href" attribute. Following is a sample where WSO2 mailing list information is fetched from MarkMail [6] and displayed on a gadget.

<?xml version="1.0" encoding="UTF-8"?>
<Module>
    <ModulePrefs title="MarkMail WSO2 Lists">
    </ModulePrefs>
    <Content type="url" href="https://wso2.markmail.org/search/?q="/>
</Module>

This gadget, once deployed with WSO2 Gadget Server will render like following.

MarkMail Gadget Simple

The gadget renders successfully, but there is a problem. The content is clipped, and there is no way to see the full content.

We can try setting "height" attribute and "scrolling" attribute on the content element:

    <ModulePrefs title="MarkMail WSO2 Lists" height="350" scrolling="true" />
 

MarkMail Gadget Height

Now the height setting has worked, and we can see the graph on the top left hand side of the original page within the gadget. However, we do not still see scrolling. This is due to an issue [7] in the Apache Shinding engine that is used as the core engine of WSO2 Gadget Server. Hopefully this would be fixed in the near future.
A workaround would be to use larger height, and view the gadget in the maximized mode. Yet, since the main objective is not to load the page as it is, let’s move on and look at more useful forms of this gadget.

Google gadget API documentation on URL content type [8] might provide more details on URL content type, if you are interested in.


Content Type HTML Gadgets

The "Hello" gadget given earlier in this tutorial, used <Content> element's "type" attribute as "html".

    <Content type="html">

This content type is what we have to use when we want to pull information from the Web, process it, and extract information that we need and display within the gadget, using various visualization forms that we need.
One point that must be kept in mind when using "html" content type gadget, is that, it must include a CDATA section, within element and any HTML that we write must go within that section. This in fact was done in the Hello gadget sample we used earlier as well:

   <Content type="html">
     <![CDATA[
       Hello, <span id="nameSpan"/>
       <script type="text/javascript">
          var prefs = new gadgets.Prefs();
          document.getElementById('nameSpan').innerHTML = prefs.getString("Name");
      </script>
      !
     ]]>
    </Content>

Another important aspect to note is that with URL content type gadgets, the gadget engine triggers the pulling of content from the URL given. However, when we use HTML content type gadgets, we have to write our own logic, to pull the Web URL into the gadget. Though this might sound complex, there are built-in mechanisms and APIs that we can use to pull a URL content and this also yields flexibility to make our lives easy, when processing the pulled content.

Google gadget API documentation on HTML content type [9] might provide more details on HTML content type, if you are interested in.


Pulling Information into a Gadget with makeRequest

Google gadget API provides a call named "makeRequest" [10] to fetch content from a URL. Let’s look at a sample, where we fetch WSO2 Carbon and Stratos SVN commits data from MarkMail and display them content in the gadget.

This gadget, has a

HTML element defined in the content section, fetches content from mailing list archive URL and fills in the div content with the fetched data.
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
    <ModulePrefs title="WSO2 Carbon and Stratos SVN Data from MarkMail" />
    <Content type="html">
          <![CDATA[
          <div id="contentDiv"></div>
          
          <script type="text/javascript">
            
              function getHtml() {    
                  var parameters = {};  
                  parameters[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;  
                  var url = "https://markmail.org/browse/org.wso2.carbon-commits";  
                  gadgets.io.makeRequest(url, processResponse, parameters);
              };
            
              function processResponse(response) {  
                   document.getElementById('contentDiv').innerHTML = response.text;
              };
            
              gadgets.util.registerOnLoadHandler(getHtml);
        
         </script>
          ]]>
    </Content>
</Module>

The data fetching and filling in the div is done using JavaScript logic. There are two functions, one that gets the HTML form the URL and one that process the response.

On line 21 we register the "getHtml" function, to be triggered on the loading of the gadget.

Within "getHtml", on line 12, we set the request parameter saying that content type is TEXT, meaning that we would expect to deal with the fetched content in text format.

On line 14, we make the request to fetch, with the mailing list URL, the name of the callback function into which "makeRequest" will feed the content, and request parameters.

When "makeRequest" receives the fetched content, "processResponse" will be called with the response object, and the text field will have the received HTML as text.
So we can use that text and set the

element’s innerHTML as seen on line 18.

Here is the output from this gadget.

MarkMail Gadget SVN Data

So it works. But yet, the content is clipped. We have hit the scrolling problem again? Not really, with a preference setting and an API call we can fix this.


Dynamic Height with Google Gadgets

The fix to clipping of the content can is to adjust the height of the gadget, dynamically, when content gets updated. For this, we can use the combination of "dynamic-height" feature and a call to "adjustHeight" API when the content changes.

So there are two changes to be made to the gadget.

    <ModulePrefs title="WSO2 Carbon and Stratos SVN Data from MarkMail">
        <Require feature="dynamic-height" />
    </ModulePrefs>

Update the <ModulePrefs> to require "dynamic-height" feature.

              function processResponse(response) {  
                   document.getElementById('contentDiv').innerHTML = response.text;
                   gadgets.window.adjustHeight();
              };

Update "precessReponse" JavaScript function to call "adjustHeight", right after setting the <div> element’s content.

And we can see the content in full within the gadget.

MarkMail Gadget SVN Data Dynamic Height

More information on dynamic height settings can be found in Google gadget documentation [11].

This gadget still display the content from the URL as it is. But we might want to process this data and present this data in a more appealing format,
like using a graph. MarkMail of course display data using a graph on its home page, but the intention here is to learn how to write better gadgets and
not re-do what MarkMail is already doing.

In the next part of this tutorial, we will explore how to use a third party JavaScript library and content from mark mail, to come up with more colorful gadgets.
And in the process, will dig more into the Google gadget API usage, tips and tricks.

References

[1] href="https://code.google.com/apis/gadgets/docs/spec.html">Google Gadget Specification

[2] href="https://code.google.com/apis/gadgets/docs/basic.html#Anatomy">Anatomy of a
Google gadget

[3] href="https://wso2.org/project/gadget-server/documentation/gadget_repo.html">Adding
Gadgets to Gadget Repository

[4] href="https://wso2.org/project/gadget-server/1.4.2/docs/add_gadgets.html#repo_add">Adding
Gadgets to the Portal

[5] href="https://wso2.org/project/gadget-server/1.4.2/docs/installation_guide.html">Installation
Guide

[6] MarkMail
WSO2 mailing lists

[7] href="https://issues.apache.org/jira/browse/SHINDIG-180">Apache Shinding gadget
scrolling issue

[8] href="https://code.google.com/apis/gadgets/docs/fundamentals.html#URL">Google
gadget API documentation on URL content type

[9] href="https://code.google.com/apis/gadgets/docs/fundamentals.html#HTML">Google
gadget API documentation on HTML content type

[10] href="https://code.google.com/apis/gadgets/docs/reference/#gadgets.io.makeRequest">gadgets.io.makeRequest
API

[11] href="https://code.google.com/apis/gadgets/docs/ui.html#Dyn_Height">Google
gadget API documentation on dynamic height




This brings us to the end of this four part tutorial. Please feel free to provide us the feedback, and help us improve the content.

Please refer to the table of contents section to find out about the other parts of this tutorial.

 

About Author

  • Samisa Abeysinghe
  • VP, Training
  • WSO2 Inc.