||
Skip to end of metadata
Go to start of metadata

This tutorial guides you in creating, deploying and using a gadget in the WSO2 Gadget Server. Whether you are a developer or a business user, this guide will help you to write a simple gadget and get it up and running in no time. This tutorial outlines three key points as follow:

  • Explains the fundamentals in gadget authoring via a simple HelloWorld gadget. 
  • Explains more advanced features such as the usage of API via a gadget with the use of the Google Gadget API.
  • Explains a gadget's extensibility factor via a simple URL gadget (a hint on limitless possibilities).

To follow this tutorial, you only need a text editor and some basic knowledge in HTML, JavaScript and XML.

WSO2 Gadget Server's Role

WSO2 Gadget Server adheres to the Google Gadget Specification and supports the hosting and management of gadgets developed using this standard. This means that the gadgets written for Google gadget containers (and many other containers such as Hi5, Orkut, etc.) can be added to the WSO2 Gadget Server portal and vise versa.

Gadgets written according to the Google Gadget Specification are essentially HTML and Javascript applications that can be hosted in a platform of choice. The WSO2 Gadget Server only needs the publicly accessible URL of a gadget to add it to its portal. A significant benefit of these mini-applications is that they have a higher reach. In other words, write once and run in multiple locations. The applications are simple to build with the help of many Javascript libraries available. It is simply an XML file which is located in any publicly accessible location. This file can contain all the logic in it or it can refer to URLs to fetch content, depending on the gadget's purpose.

WSO2 Gadget Server is a container built using open standards. Based on Apache Shindig (http://shindig.apache.org/), an Open Source implementation of the Google Gadget Specification, the Gadget Server provides a comprehensive portal solution where users can write, deploy and use enterprise or open-social gadgets with ease.

The HelloWorld Gadget

The hello world gadget is the simplest of its kind and contains only XML and HTML.

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
   <ModulePrefs title="hello world example" />
   <Content type="html">
      <![CDATA[
         Hello, world!
      ]]>
   </Content>
</Module>
  • The first line is the XML file declaration where it indicates that this files contains XML data.
  • The <Module> tag declares that this is a Gadget XML. This tag is declared in the gadget specification, so that the container will then know that the processing XML is a gadget.
  • <ModulePrefs /> contains metadata about the gadget (i.e : Title, Author name, etc). It can also have static rendering parameters for the gadget such as gadget height, width and scrollability.
  • In between <Content> tag, all the logic that belongs to the gadget resides (i.e JavaScript logic)
  • <![CDATA[ ...insert HTML here... ]]> is used to enclose HTML when a gadget's content type is html. It tells the gadget parser that the text within the CDATA section should not be treated as XML. The CDATA section typically contains HTML and JavaScript.

The following screen shows how the HelloWorld gadget is rendered in the WSO2 Gadget Server.

Feed Reader Gadget (Use of the Google Gadgets API)

Blogs, magazines and newspapers allow their feeds to be read by third party software tools and they expose the content in RSS and Atom formats. With the use of the Google Gadgets API, we can write a simple feed reader gadget to retrieve these feeds and display inside your enterprise or personal portal.

The gadget which is demonstrated below, demonstrates more advanced features of gadget composition and the use of the Google Gadgets API. The gadget's task is to read an RSS or Atom feed from any given URL and display it in a nicely styled format.

As the default feed, let's take the SOA-Platform Blog (http://soa-platform.blogspot.com/feeds/posts/default), and keep it as the default URL in gadget preferences.

<span id="1258900958984S" style="display: none;">
</span>
<span id="1258901005527S" style="display: none;">
</span>
<Module>
   <ModulePrefs title="SOA Platform Blog"
                description="SOA blog articles Syndicated via WSO2 Blogs"
                author="WSO2 Gadget Server"
                author_email="contact@wso2.org"
                author_link="http://www.wso2.org/"
                title_url="http://www.wso2.org/"
                height="100"
                scrolling="true">
       <Require feature="dynamic-height"/>
       <Require feature="settitle"/>
       <Require feature="setprefs"/>
   </ModulePrefs>
   <UserPref name="feed_url" display_name="Feed URL:"
             default_value="http://soa-platform.blogspot.com/feeds/posts/default/"/>
   <UserPref name="show_date" display_name="Show Dates?" datatype="bool" default_value="true"/>
   <UserPref name="num_entries" display_name="Number of Entries:" default_value="5"/>
   <Content type="html">
   .................
   </Content>
</Module>
<span id="1258900958218E" style="display: none;">
</span>
<span id="1258901005788E" style="display: none;">
</span>

There are a few syntaxes which are important and should be noted in the above code snippet. The XML element <Require feature=""> is the method to inform the gadget container (in our case the WSO2 Gadget Server) that this gadget needs a few extra features to function. These features are pre-written Javascript code, which are loaded to the gadget by the gadget container, on demand. For instance, if the gadget needs its height to be adjusted dynamically, the gadget author should import the dynamic-height feature. If he or she needs to set the gadget title the settitle feature needs to be imported. Likewise, there are many features that the WSO2 Gadget Server supports. More information about these features can be found in Gadgets XML Reference in this URL: http://code.google.com/apis/gadgets/docs/reference.html.

<UserPrefs> is the mechanism to provide additional gadget specific preferences (Gadget Settings). These properties can be persisted and read from the gadget to do necessary processing. (i.e. Default feed URL for this sample gadget)

<Content type="html">
   <![CDATA[
   <style>
      …............
   </style>
   <script type="text/javascript">
      .............
   </script>
   <div id="content_div"><img src="waiting.gif" alt="" /> loading...</div>
   ]]>
</Content>

The gadget body's skeleton looks like the above code, where we specify that the content type is HTML. In between meta-data tags, the styles and Javascript logic are implemented. The javascript logic is as follows:

var prefs =new gadgets.Prefs();
var showdate = prefs.getBool('show_date');
var entries = prefs.getInt('num_entries');
var feedUrl = prefs.getString('feed_url');

if (entries > 100) {
  alert('You cannot display more than 100 entries.');
  entries = 100; }

var params = {};
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.FEED;
params[gadgets.io.RequestParameters.NUM_ENTRIES] = entries;
params[gadgets.io.RequestParameters.GET_SUMMARIES] ='true';
gadgets.io.makeRequest(feedUrl, readFeed, params);

What should be noted in the code snippet is the use of gadget.* API methods. This is called the Gadgets API originally developed by Google. Google Gadgets API provides many functionalities such as reading content from a given URL (in many formants), skins, tabs inside gadgets, flash content etc. The full reference for the Google Gadgets API can be found in Gadget API Reference in this URL: http://code.google.com/apis/gadgets/docs/reference

In the above code  var prefs = new gadgets.Prefs(); creates a preferences object and let us handle user preferences for this particular gadget.    

gadgets.io.makeRequest(feedUrl, readFeed, params);

The makeRequest API method retrieves the feed via HTTP from the given URL, and by providing a callback method (readFeed(feed)) we can do further processing on the retrieved feed.

function readFeed(feed) {
            if (feed == null) {
                alert('There is no data.');
                return;
            }

            // Start building HTML string that will be displayed in gadget.
            gadgets.window.setTitle(feed.data.Title + ' | ' + feed.data.Description);
            var html = '';
            // Access the data for a given entry
            if (feed.data.Entry) {
                for (var i = 0; i < feed.data.Entry.length; i++) {
                    html += '<div id="item-' + i + '">'
                            + '<table id="feedTitle"><tr><td><a href="javascript:showContent(' + i + ')" style="text-decoration:none;">+</a></td>'
                            + '<td><a target="_blank" href="' + feed.data.Entry[i].Link + '">'
                            + feed.data.Entry[i].Title
                            + '</a></td></tr></table>';

                    if (showdate) {
                        // The feed entry Date field contains the timestamp in seconds
                        // since Jan. 1, 1970. To convert it to the milliseconds needed
                        // to initialize the JavaScript Date object with the correct date,
                        // multiply by 1000.
                        var milliseconds = (feed.data.Entry[i].Date) * 1000;
                        var date = new Date(milliseconds);
                        html += '<span>';
                        html += date.toLocaleDateString();
                        html += " ";
                        html += date.toLocaleTimeString();
                        html += '</span>';
                    }
                    var sumString = feed.data.Entry[i].Summary;
                    html += '<div id="sum-' + i + '" style="display:none;">' + sumString + '</div>';
                    html += '</div>';
                }
            }
            document.getElementById('content_div').innerHTML = html;
            gadgets.window.adjustHeight();

        }

You can also provide a method to display the feed content on demand as follows,

function showContent(id) {
    if (document.getElementById('sum-' + id).style.display == '') {
    document.getElementById('sum-' + id).style.display = 'none';
    document.getElementById('item-' + id).className = '';
    } else {
          document.getElementById('sum-' + id).style.display = '';
          document.getElementById('item-' + id).className = 'item';
           }
   gadgets.window.adjustHeight();
}

A noteworthy point here is the use of dynamic height feature. The imported feature of the container <Require feature="dynamic-height"/> can be used by invoking gadgets.window.adjustHeight() to adjust the  gadget height according to the dynamically created content. With these simple steps, you can author your own feed reader gadget quite easily.

Bellow is how it looks like when deployed in the WSO2 Gadget Server, 

The URL Gadget (Pull content from a URL instead of embedding in the gadget XML)

In order to demonstrate that gadgets can be used to load external content directly, this example shows you how to display content from a URL. The Gadget XML logic is quite simple where instead of  <Content type="html"> it should be  <Content type="url" href="......"/> and point to the URL which will render the content you want to display inside the gadget. The ability to render external content comes handy, when the gadget author wants to implement the application with other programing languages and still display it as a gadget in a portal. A good example for a URL gadget is the Moon Phase gadget which is available in the iGoogle gadget repository. http://www.calculatorcat.com/gmodules/current_moon.xml.

The gadget XML code looks like follows,

<p><?xml version="1.0" encoding="UTF-8" ?></p><Module>
<p>  <ModulePrefs title="URL example" /></p>  <Content type="url" href="http://myURL"/>
<p></Module></p>

For more resources on gadget authoring, refer to the following URLs as well:

For detailed information on how to deploy and manage these gadgets in the WSO2 Gadget Server, refer to the WSO2 Gadget Repository section.

Summary

Gadgets are handy applications that can display chunks of data in a unified portal view. Even though portlets can be written in many different methods, authoring can be done simply with some HTML and JavaScript. Apart from that, with the least amount of changes, these gadgets can be embedded in many web pages over Internet that would make a great benefit. This tutorial is a complete guide demonstrating how to write, deploy and use gadgets for enterprises and for personal use, using WSO2 Gadget Server.

  • No labels