Implementing and deploying Google gadgets for the Lotus Connections Home page

This article introduces the IBM®-developed iWidget specification used in various IBM products such as IBM Lotus® Connections 2.0. It describes different aspects of the specification through a practical example, which shows how to implement an iWidget that acts as a wrapper for a Google gadget.

Share:

Vincent Burckhardt (vincent.burckhardt@ie.ibm.com), Software Engineer, IBM

Vincent Burckhardt is a Software Engineer at the IBM Dublin Software Laboratory. Vincent has been working as part of the IBM Lotus Connections development team since 2007. You can reach him at vincent.burckhardt@ie.ibm.com.



29 September 2009 (First published 09 September 2008)

Also available in Chinese Russian Japanese Portuguese

Notice: This article covers the release 2.0 of Lotus Connections. You can refer to the second section of the developerWorks article, "Customizing Lotus Connections 2.5 with Lotus Widget Factory and Google Gadgets," to get a summary of the steps involved to deploy a Google Gadget in Lotus Connections 2.5. Note that the programming details in the present article are still valid and offer a good starting point for developers willing to learn more about the details of the iWidget specifications.

Lotus Connections 2.0 includes a new highly customizable and extensible main page that gives users an aggregated view of information from various and diverse sources. The Home page feature is based on widgets and allows you to extend the Lotus Connections social software platform easily.

The Home page lets you implement and add your own widgets. An iWidget is a new IBM-defined definition for widgets. The iWidget specification defines the structure of such a widget. The iWidget standard is not specific to Lotus Connections and is used in other products such as the Lotus Mashups component of IBM Mashup Center, thus allowing you to write a widget once and run it in different products.

This article gives you an overview of the steps involved in creating a basic iWidget, deploying it, and running it in the Home page. As an example, this article demonstrates how to wrap a Google gadget in an iWidget. After reading this article, you should also be able to create basic widgets that display any other content to the user.

The first two sections of this article give you the necessary theoretical knowledge about both the iWidget specification and Google gadgets. The third section guides you step-by-step in the process of implementing an iWidget acting as a basic Google gadget wrapper. Finally, the article goes into more detail by discussing how you can add enhancements to the Google gadget wrapper.

The process to create and deploy a basic widget is relatively straightforward. This article assumes that you are familiar with the most common Web development technologies such as JavaScript™, Java™ Platform, Enterprise Edition, and XML. An intermediate knowledge is sufficient, as additional pieces of information about less common areas, such as the use of the JavaScript Dojo Toolkit, are given through the article when needed.

Home page widget and iWidget specifications overview

This section gives a quick overview of the IBM's iWidget specification and provides you with the minimum theoretical knowledge required to understand the practical part introduced later in this article. This article does not go too deeply into detail about some features described in the specifications.

Anatomy of a Home page widget

Before we discuss the technical details, let's look at the anatomy of a Home page widget. A Home page widget can be split into two parts:

  • Header. Contains the title of the widget and a few action buttons represented by icons (move widget, edit, refresh, help, and close).
  • Body. Bordered by a red rectangle in figure 1, the body is the place where any iWidget can be displayed to the user.
Figure 1. Home page widget skeleton
Home page widget skeleton

The widget developer has almost full control of the content displayed in the body of a Home page widget. A widget can display anything found on a standard Web page. The only constraint is to follow the component model defined in the iWidget specifications.

The Home page runtime automatically generates the header bar. You have only a limited level of customization on the header bar. You can define which actions are supported by the iWidget. The Home page automatically hides the icons of the actions not supported by the embedded iWidget. The administrator defines the title of the widget at deployment time.

iWidget descriptor

The descriptor is the core part of any iWidget. It is the place where you declare the different capabilities supported by the widget. The iWidget descriptor can be written using two different styles: the microformat or the XML syntax. Because the Lotus Connections Home page supports only the XML definition style, this article does not describe the microformat syntax. Listing 1 shows an example of a Hello World iWidget XML descriptor.

Listing 1. Hello World iWidget XML descriptor
<iw:iwidget name="helloWorld" xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" 
iScope="HelloWorldWidgetClass">
   <iw:resource uri="helloworld.js" />			
   <iw:content mode="view">
      <![CDATA[
         <div id="root">
            Hello World! <br/>
               <button id="click" 
               onclick="iContext.iScope().onClickButton()">Click me!</button>
         </div>
      ]]> 
   </iw:content>     
</iw:iwidget>

This widget displays the string "Hello World" and a button as shown in Figure 2.

Figure 2. Hello World widget
Hello World widget

The important parts of the XML descriptor in the example are these:

  • iScope attribute. This attribute designates the name of the class that contains the logic of your iWidget. It is typically a JavaScript class defined in one of the resources declared in your XML descriptor (see the next item in this list). The iWidget framework instantiates an iScope object for each instance of your iWidget.
  • iw:resource tags. These tags point to the different resources required by your iWidget. The Home page supports JavaScript and cascading style sheet (CSS) resources. Each resource declared in the XML descriptor is fetched and evaluated. The attribute named "uri" (Uniform Resource Identifier) is relative to the location of the XML descriptor. In this example, we declare only one resource, a JavaScript file named helloworld.js, which is located under the same directory as the XML descriptor file.iw:content tags. These tags define the markup of a given mode. The markup fragment is the HTML code rendered by the Home page for the iWidget when it is showing a given mode. In this example, the widget has only one mode, view, which is the default mode.

Listing 2 shows the code from the helloworld.js file that defines the iScope class HelloWorldWidgetClass. This class defines only one method, onClickButton, which is the handler associated with the onclick event of the button as defined in listing 1. When users click the button, a window displays the string "Button clicked."

Dojo syntax

JavaScript is a prototype-based language. To make things easier for developers used to object-oriented programming, the Dojo Toolkit provides a few object-oriented class helpers. The example uses the method dojo.declare for the declaration of the HelloWorldWidgetClass extending no parent class (null) and having one single method (onClickButton).

Listing 2. Contents of helloworld.js
dojo.provide("HelloWorldWidgetClass");

dojo.declare(
   /* class name */                                            
   "HelloWorldWidgetClass",  
   /* parent class */ 
    null,
   /* methods and variables */ 
   {	
      onClickButton: function(){
         alert("Button clicked");
      }
   }
}

Using the services provided by the iWidget framework

The iContext object is the central point used to interact with the services provided by the iWidget framework. The iWidget framework automatically injects an object named iContext in the iScope class of your widget, as a member (this.iContext). You can leverage the capabilities of the iWidget framework through the iContext object.

Additionally, the iContext object can be used in the HTML markup of the widget to call a method of the associated instance of the iScope class, in an encapsulated way. The example in listing 1 uses this technique to invoke the onClickButton method.

Encapsulation and iContext

Encapsulation is an important part of the iWidget specifications. Each iWidget requires encapsulation to avoid clashes between resources declared by several widgets opened on the same page at the same time. The iWidget framework helps you with encapsulating your widgets, but you need to do some work as well. In particular, as the iWidget developer you need to do the following:

  • Correctly declare the scope of the iWidget class (iScope), as described in the “iWidget descriptor” section of this article. Any method or variable used by the iWidget must be declared within the iScope.
  • Avoid the use of global JavaScript functions and variables in the resources of your iWidget because you cannot guarantee that other widgets on the page do not declare objects with the same name, resulting in clashes and conflicts.
  • Interact with the iWidget framework through the iContext object to get the appropriate scope object. In the Hello World example, you do that with the iContext.iScope() statement.

ItemSets

An ItemSet is a set of name-value pairs managed by the iWidget framework. They are typically used to store properties of an iWidget. ItemSets are manipulated in the code of your iScope class through methods such as getItemValue, and getAllNames. (For more details, refer to the iWidget specification.) ItemSets can be declared in the XML descriptor as shown in listing 3.

Listing 3. ItemSets declaration
<iw:itemSet id="itemSetId">
   <iw:item id="item1" value="value1" />
   <iw:item id="item2" value="value2" />
</iw:itemSet>

The final section of this article, "Further enhancements of our gadget wrapper," provides a concrete example of how to use an ItemSet to store the preferences of the Google gadget wrapper that you implement in this article.

Other services provided by the iWidget framework

This section describes other services defined in the specifications. Not all these services are used in our Google gadget wrapper. The capabilities provided by the specifications are as follows:

  • Event system. This system allows an iWidget to fire and catch events. In the Home page, this mechanism is used to fire events to your iWidget when the user selects one of the actions located in the header bar (such as edit or refresh).
  • IO module. Due to the same origin security policy enforced by JavaScript (more details at http://www.mozilla.org/projects/security/components/same-origin.html), it is not possible to fire Ajax requests to a domain different from the Home page domain by default. To provide the ability to send requests to other domains, the Home page comes with an Ajax proxy. The IO module specified can be used to rewrite any URL to reroute the Ajax requests through the build-in Home page AJAX proxy. It can also be used to locate a resource relative to the location of the XML descriptor.
  • Wiring system. Users can configure two or more widgets to exchange data using the eventing system described in the first item in this list. Note that this feature is not enabled in the Lotus Connections Home page, but is enabled in Lotus Mashups.

Google gadget overview

Google gadgets are small, lightweight applications that are made of XML, HTML, and JavaScript. Google gadgets can be added to Gadget containers such as iGoogle (the Google customizable home page), Orkut, Google Maps, or Google Desktop. Gadget development is open to anyone. Google provides a public directory in which you can publish your gadgets.

Just like iWidgets, the core part of a Google gadget is contained in its XML definition file. You can find more details about the anatomy of a gadget XML descriptor in the "Writing Your Own Gadgets" chapter of the official developer's guide. In a nutshell, the XML definition of a gadget specifies two mains aspects: the markup of the gadget (HTML code) and a set of preferences.

Note that there are currently two distinct Google gadget APIs. This article refers to the legacy API that Google supports for syndicated gadgets.

Adding a Google gadget to any Web site

Google offers the ability to run gadgets on any Web page, known as syndication. You can leverage this capability to create your wrapper that allows you to display Google gadgets in the Lotus Connections Home page.

  • To let you run a gadget outside a gadget container, Google provides a Web service that returns a formatted output consisting of JavaScript and HTML that is responsible for initiating the dependencies of the gadget and rendering it. The service takes several request attributes, in particular: URL to the Google gadget XML definition file.
  • User preferences defined in the XML descriptor of the gadget, which can be assigned a value by passing the name of the preference, preceded with _up, as a request parameter to the service. The passed user preferences values override the default values specified in the XML definition of the Google gadget.
  • Display preferences such as the title, width (w), height (h), and border style.

The base URL of the Google service is the string http://www.gmodule.com/ig/ifr. Here is an example of a complete URL including the request attributes to the Google service returning JavaScript code for the Date Time Google gadget:

http://www.gmodules.com/ig/ifr?url=http://www.google.com/ig/modules/
datetime.xml&up_color=blue&up_firstDay=0&
w=320&h=136&output=js

In that example, notice the following parameters:

  • URL to the XML descriptor of the Date Time gadget is provided: the string http://www.google.com/ig/modules/datetime.xml.
  • Color and firstDay user preferences (specific to this gadget) are set to blue and 0 (for Sunday).
  • Width (w) and height (h) display parameters are set to 320 px and 136 px.

Although you can craft the URL to the Web service manually, to include any request parameter needed, as a best practice use the Page Creator tool provided by Google. This tool can easily construct the URL in a graphical way. This tool allows you to specify values for the preferences of the gadget and generates the URL to the service including the correct request parameters for the different preferences defined in the XML definition of the gadget. To use the Page Creator tool, follow these steps:

  1. Go to the Google gadget library.
  2. Pick a gadget, and then select the Add to your webpage option. Customize the gadget settings and user preferences values. The page shows a preview of the gadget with the new values.
  3. After you are done with the settings, select the Get the code option.
  4. The page shows the code to include. The URL to the Web service is the string in the src attribute of the script tag.

NOTE: As you might have noticed, the URL returned by the Page Creator has some special characters escaped. For instance the ampersand (&) character is escaped as &. Because the URL is built to be placed in an HTML or XML document, escaping the special characters is required to make sure that the document remains valid.


Wrapping a Google gadget in an iWidget descriptor

Now you are ready to write a wrapper for the Date Time Google gadget. Figure 3 shows the result after its deployment in the Home page.

Figure 3. Google Date Time gadget deployed in the Home page
Google Date Time gadget deployed in the Home page

The method exposed in this section is the same for any other Google gadget, with only one line of code to modify to point to the appropriate gadget.

As a first approach, your wrapper stays basic: its only purpose is to render the gadget in the Home page. The final section of this article focuses on adding capabilities to this wrapper, such as an edit view where users can modify the values of the gadget preferences.

Method to render the gadget and XML descriptor

To render a Google gadget in the Home page, call the Google Web service discussed in the section “Adding Google gadgets to any Web site” with the appropriate request parameters. The response, a mix of HTML and JavaScript, is inserted in a script element. The Script element is located in an HTML document loaded in the IFRAME part of the iWidget.

IFRAME

An IFRAME is an inline frame that contains another document. It is a standard HTML element, with no specific relation with the iWidget specifications. The src attribute of an IFRAME points to the URL of the document to load.

Listing 4 shows the code skeleton of the XML descriptor of your iWidget. Listing 5 contains a fragment of the JSP document (gadgetWrapper.jsp) with the script element pointing to the Google service.

Listing 4. iWidget wrapper definition for a Google gadget
<iw:iwidget name="googleDateTime" 
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget">
   <iw:content mode=”view”>
   <![CDATA[
      <iframe scrolling="auto" width="100%" height="300px" frameborder="0" 
      src="/gadgetWrapper/gadgetWrapper.jsp?url=<google gadget xml url>">
      </iframe>
   ]]> 
   </iw:content>     
</iw:iwidget>
Listing 5. gadgetWrapper.jsp
<%
   StringBuffer url = new StringBuffer();
   url.append("http://www.gmodules.com/ig/ifr?");
   url.append(request.getQueryString());	
 %>

<script src="<%= url.toString() %>"></script>

As you can see, the iWidget renders an IFRAME HTML element pointing to the gadgetWrapper JSP page. The JSP page is responsible for the following tasks:

  • Get the query string part of the URL. This is the substring after the character ? in the URL. In this case, the query string part of the /gadgetWrapper/gadgetWrapper.jsp?url=<google gadget xml url> is url=<google gadget xml url>.
  • Build the URL to the Google service by appending the query string to the context root of the service at gmodule.com.
  • Set the src attribute of the script element to point to the Google service with the appropriate gadget parameters from the query string.

If you do not use Java, you can adapt the behavior described for the JSP page in the service-side language of your choice (PHP or .NET, for example). The important part is simply to set the script element with the URL to the Google service.

Notice three aspects at this point:

  • We could have inserted the script element directly in the XML definition of the iWidget code. Some conflicts between the JavaScript code returned by the Google service and the iWidget framework, however, force you to choose the solution of isolating the SCRIPT tag in an IFRAME element.
  • The Google service accepts the value of html for the output request parameter (instead of js). This results in generating HTML code that can be inserted directly in the IFRAME shown in listing 4, without having to use the JSP page solution. This solution, though, does not include the "gadget powered by Google" and "+Google" buttons under the Google gadget, which violates the Google gadget terms of service.
  • There is no backing logic for this iWidget. Therefore, the XML definition does not contain any reference to the iScope or JavaScript resources. You add some logic to your iWidget in the final section of this article.

Google Date Time gadget

Listing 6 shows the code of the XML descriptor for an iWidget that wraps the Date Time Google gadget shown in figure 3. The src attribute of the IFRAME element points to the URL of the XML descriptor of this gadget located at http://www.google.com/ig/modules/datetime.xml. It also sets the user parameters specific to this gadget, such as the background color (orange) and the first day of the week (0 is for Sunday). As described previously, you can either inspect the XML definition of the gadget to find out which user parameters are available for a given gadget, or you can use the Google Page Creator tool.

Listing 6. iWidget wrapper definition for the Google Date Time gadget
<iw:iwidget name="googleDateTime" 
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget">
   <iw:content mode="view">
   <![CDATA[
      <iframe scrolling="auto" width="100%" frameborder="0"
	   src="/gadgetWrapper/gadgetWrapper.jsp?url=
http://www.google.com/ig/modules/datetime.xml&amp;up_color=
orange&amp;up_firstDay=0&amp;title=&amp;border=
&amp;output=js"></iframe>
        ]]> 
     </iw:content>
</iw:iwidget>

To get the URL of the Google gadget of your choice to insert in the src (source) attribute of the IFRAME, follow the steps described in the section "Adding Google gadgets to any Web site." At this point, you hard-code the user preferences as part of the URL request string. In the last section of the article, you modify this coding so that users can change the preferences.

NOTE: In listing 6, notice that we also set two display parameters (title and border) to empty values. This setting lets you render the Google gadget without a title and without any border style.


Deploying the Google gadget in the Home page

You deploy an iWidget to the Home page in two main steps:

  1. Deploy the XML descriptor and all the resources of the iWidget to a Web server.
  2. Register the widget in the Home page catalog by pointing to the URL of the deployed iWidget XML descriptor.

Deploy the iWidget

The deployment of the iWidget to a Web server is flexible because you are not bound to any specific server technology. For instance, your iWidget can be a PHP project and deployed to a PHP server. You can also implement your widget as a Java Platform, Enterprise Edition project and deploy it in a servlet/Java Platform, Enterprise Edition container such as WebSphere® Application Server or Tomcat. The choice is up to you. Note that if you don't use a Java Platform, Enterprise Edition container, you must adapt the JSP page described in the section "Method to render the gadget and XML descriptor."

The following steps detail the process to create the iWidget project in Eclipse as a Web project and to export it as an EAR file. The EAR file can then be deployed to a Java Platform, Enterprise Edition container.

NOTE: You need to have the Web tools plug-in installed to create a Web project under Eclipse. You can download it at http://download.eclipse.org/webtools/downloads/. The Java Platform, Enterprise Edition version of Eclipse includes this plug-in.

Let's create your project and EAR file ready to be deployed. In Eclipse, first create the project:

  1. Go to File - New - Project.
  2. Select Web - Dynamic Web Project in the window, and then click Next.
  3. Input the project name of your choice, for instance gadgetWrapper. You can select a target runtime if you want to deploy the project directly from Eclipse; otherwise, select None.
  4. Select the Add Project to an EAR option to tell Eclipse to create and associate an EAR project for this Web Project.
  5. Select Next to get the last window. Don't modify any of the default settings. Click Finish to create the Web project.

At this point, you are ready to work on the project.

Next, add the iWidget XML descriptor to the project:

  1. Under WebContent, create a new XML file by right-clicking the directory name and selecting New - File. Enter gadgetWrapper.xml for the file name.
  2. Open the file in Eclipse by double-clicking it, and then paste the code shown in listing 6. If you cannot edit the file, make sure that the source tab is selected. See figure 4.
  3. Save the file.
Figure 4. gadgetWrapper.xml being edited in Eclipse
gadgetWrapper.xml being edited in Eclipse

Repeat the same steps as for adding the XML descriptor to add the JSP defined in listing 5 to the project. You can find the full version of this file inside gadgetWrapper.ear in the Download section of this article.

Next, generate the EAR file to deploy to a Java Platform, Enterprise Edition container such as WebSphere Application Server:

  1. Select the EAR project associated to the Web project that you created previously.
  2. Right-click and select Export - EAR file.
  3. Select a destination on your disk.

That's it! The EAR file containing the iWidget resources and XML file is ready to be deployed to any Java Platform, Enterprise Edition container.

At this point, you can deploy the EAR file to the Java Platform, Enterprise Edition container just as you would deploy any other EAR file.

NOTE: The IFRAME shown in listing 6 has a reference to the JSP page (shown in listing 5) with the context root set to /gadgetWrapper. You might have to adapt that setting depending on the real context root under which your EAR file is deployed. In the final section of this article we show you how to get rid of this limitation using the iWidget IO module.

Register the widget in the Home page catalog

The Home page provides an administration user interface to add new widgets to the catalog database. Note that only users with administrator rights can add new widgets to the Home page catalog.

Follow these steps to add our iWidget by using the Home page Web administration user interface:

  1. Log in with an administrator account to the Home page.
  2. Select the Administration tab in the Home page as shown in figure 5.
    Figure 5. The Administration tab
    The Administration tab
  3. Select the Add another widget option at the bottom right of the page.
  4. The form shown in figure 6 is displayed. Enter the title name and the location of the XML descriptor of the iWidget.
    Figure 6. The Administrators Home page
    The Administrators Home page
  5. Enter a title for the widget. The title that you enter is displayed in the title bar of the widget; for instance, the title can be Google Date Time.
  6. Enter the location of the XML descriptor. This field depends on where you deployed your widget in the previous “Deploy the iWidget” section.
  7. The other text fields are optional and can be left blank. You can point to an icon, for instance. The icon is displayed in the sidebar when the widget is closed.
  8. Leave all the boxes cleared. They are required only for widgets dealing with other Lotus Connections features, which is not the case for your iWidget wrapping a Google gadget.
  9. Click Save.

You can find more details about the administration options to manage widgets in the Lotus Connections v2 Information Center.


Further enhancements to the gadget wrapper

This section describes how you can add more capabilities to the basic iWidget. In particular, you can add the ability for users to modify some of the preferences declared in the Google gadget definition. Note that the user preferences are handled by the Google gadget itself as they are declared as <UserPrefs> elements in the XML definition of the Google gadget. The goal is to let users pick values for those preferences and pass them to the Google service.

To allow users to customize the wrapped Google gadget, do the following:

  1. Implement an edit view for the iWidget where users customize the values of the preferences declared in the Google gadget definition.
  2. Pass the entered values to the Google service. introduced in the “Adding Google Gadget to any Web site” section above. You do so by passing the new preference values to the Google service as part of the URL.

Through these steps, you also can see a practical example of the use of several concepts introduced in this article such as ItemSets, the encapsulation mechanisms provided by the iWidget framework, and the event system.

Date Time gadget preferences

In this section, we modify our existing iWidget to allow users to set the preferences for the Google Date Time gadget. Note that the steps to follow are the same for any other Google gadget; thus, it is not difficult to adapt the concepts presented here to customize any gadget in the Home page.

Typically, there are two ways to get a list of the user preferences of a Google gadget:

  • You can inspect the XML descriptor of the gadget and look for the <UserPrefs> elements.
  • You can use the Page Creator tool. The preferences are listed under the Gadget settings section.

By inspecting the XML definition of the Date Time gadget, you see that there are two user preferences:

  • The background color
  • The first day of a week in the calendar

These two parameters have a list of allowed values defined in enumerations. Listing 7 shows a snippet of the enumeration code from the gadget XML definition of the user preference for color. The preference for the first day of the week also uses the same type of enumeration. In the rest of this section, we let users pick one of the values listed in those enumerations for each of the two preferences.

Listing 7. Extract of the XML definition of the Date Time gadget showing the color user preference enumeration
<UserPref name="color" datatype="enum" default_value="blue" 
display_name="__MSG_color__">
   <EnumValue value="blue" display_value="__MSG_blue__"/>
   <EnumValue value="green" display_value="__MSG_green__"/>
   <EnumValue value="orange" display_value="__MSG_orange__"/>
   <EnumValue value="pink" display_value="__MSG_pink__"/>
   <EnumValue value="purple" display_value="__MSG_purple__"/>
   <EnumValue value="red" display_value="__MSG_red__"/>
   <EnumValue value="yellow" display_value="__MSG_yellow__"/>
</UserPref>

Adding logic to the iWidget

The iWidget presented previously is a basic widget that contains only some markup but does not include any JavaScript logic. In that case, the URL to the Google service was hard-coded directly in the markup (iw:content) section of the iWidget. Now, you want to build the URL dynamically based on the values entered by users. To do this step, you need to write some backing code that implements the logic for generating the URL string. The first objective here is to move the location of the Google service URL from the HTML markup of the iWidget to the backing code in these steps:

  1. Remove the URL from the markup by removing the src attribute from the IFRAME in the iWidget XML definition. The content part should now look like the code shown in listing 8.

    Listing 8. Markup of the view of the iWidget wrapper
    <iw:content mode="view">
       <![CDATA[
          <iframe id="frame" scrolling="auto" width="100%" 
          frameborder="0"></iframe>
       ]]> 
    </iw:content>
  2. Create the JavaScript file containing the backing logic. As described previously, the logic is implemented in a JavaScript class called the iScope. In Eclipse, the process to create and add the JavaScript file by following the same steps as those for adding the XML definition file to the project, described in “Deploy the iWidget” section. Name the JavaScript file googleGadgetWrapper.js. Listing 9 shows the code to add to this file.

    Listing 9. First version of googleGadgetWrapper.js
    dojo.provide("GoogleGadgetWrapper");
    
    dojo.declare("GoogleGadgetWrapper", null, {	
    
       onLoad: function(){
       },
    	
       onview: function(){
       // get the frame DOM object declared in the widget markup
       var frame = this.iContext.getElementById("frame");	
    
       // get the URL to the JSP page location without having to hard-code
       // the context root in the code. For instance, if the context root  
       // after deployment is /gadgetWrapper/, jspLocation is set to
       // /gadgetWrapper/gadgetWrapper.jsp
       var jspLocation = this.iContext.io.rewriteURI("gadgetWrapper.jsp");
    	
       // set the src attribute of the iframe		
       frame.src = jspLocation + "?url=http://www.google.com/ig/modules/datetime.xml&
       title=&border=&output=js&w=400";
       }
    }

Let's walk through the code in listing 9:

  1. The iWidget framework sends an iEvent named Load to the widget. Without going into too many details about the event handling mechanism, you need to know that it results in invoking a method named on + <name of the event> on the iScope of your iWidget. In this case, this mechanism results in invoking the method onLoad.
  2. The iWidget framework loads the default mode (view) of the widget. A mode is loaded in two steps:
    • The markup (the content element in the XML descriptor) corresponding to the mode is shown to the user. Notice that you declare the markup of your widget within this mode in listing 7 (mode="view" attribute).
    • An iEvent with the name of the mode is sent to the widget. In your case, it results in invoking the method onview.

The result is that the methods onLoad and onview are invoked automatically by the framework when the widget is placed onto the page.

Additionally, notice that we use the rewriteURI method from the IO module provided by the iWidget framework (through the iContext object). This approach allows you to get the real location of the JSP file without having to include the context root of the project in the code. You cannot be sure at development time what is the context root under which the iWidget is deployed because this value can be modified by the administrator at deployment time.

The back-end logic needs to be connected to the XML definition of the iWidget. This connection is made in two steps:

  1. Add a resource element tag to point to the JavaScript file that you just added to the project:
    <iw:resource uri="googleGadgetWrapper.js" />
  2. Set the iScope attribute in the iw:widget tag element of the iWidget XML descriptor to point to the JavaScript class defined in googleGadgetWrapper.js. Because the name of your JavaScript class is GoogleGadgetWrapper, the iw:widget tag should now look like this:
    <iw:iwidget name="googleDateTime"
    xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" iScope="GoogleGadgetWrapper">

That's it! Now the src attribute of the IFRAME is set dynamically on widget initialization. At this point, there is no difference in the behavior of the widget to users. You are now ready to generate the query part of the URL to the Google service.

Storing the parameters and generating the URL to the Google service

You've seen an easy way to generate and modify the URL to the Google service before setting the URL to the IFRAME. In this section, you modify the URL to append the values of the user preferences in three steps:

  1. Store the values of the user preferences of the Google gadget in an ItemSet in your iWidget. Use an ItemSet for storing the preferences for these reasons:
    • It provides a convenient data store that you can use in different parts of your code to set and get the values picked by users.
    • It allows you to persist the preferences across user sessions on the Home page server. This point is implemented in the “Persisting the user preferences” section later in this article.

    To do so, let's modify the XML definition of the iWidget to declare the ItemSet. You name the ItemSet userPrefs. Listing 10 shows the code snippet for the two user preferences that you want to surface later in the edit view.

    Listing 10. ItemSet storing the user preferences for the Date Time gadget
    <iw:itemSet id="userPrefs">
       <iw:item id="color" value="green" />
       <iw:item id="firstDay" value="0" />
    </iw:itemSet>

    Note that you also specify a default value for each of the user preferences (green and 0 for Sunday).

  2. You have to implement the mechanism to generate the URL to the Google service dynamically from the values stored in the ItemSet. To do so, add an additional method named getQueryString in the iScope class of the iWidget. Listing 11 shows the code of the method.
    Listing 11. Method returning the query string from the preference ItemSet
    getQueryString: function(){
       // get the ItemSet object
       var userPrefs = this.iContext.getItemSet("userPrefs");
    		
       // get the names ("id") of the items as an array		
       var prefNames = userPrefs.getAllNames();
    		
       // initialize an empty JavaScript object used as a map		
       var params = {};
    		
       // populate the params map with the user parameters
       dojo.forEach(prefNames, function(name) { 
          // we need to prefix the name with "up_" to pass it to the Google Service 
          as discussed in “Google gadget overview” part
          var upName = "up_" + name;
    	params[upName] = userPrefs.getItemValue(name);		
       });
    		
      // generate the string from the params map
      return dojo.objectToQuery(params);		
    }

    This method returns a string encoding the values of the user preferences. For instance, for the Date Time gadget, it returns the string up_color=green&up_firstDay=0. This string can be directly used to build the URL to the Google service, which returns the corresponding markup for the Google gadget.

  3. You have to modify the onview method presented in listing 8 to call the getQueryString to build the URL to the Google service, before setting it to the src attribute of the iFrame. Listing 12 shows the new version of onview.
    Listing 12. New version of onview with dynamic generation of the URL string including the user preference values
    onview: function(){   
       var frame = this.iContext.getElementById("frame");	
    	
       var query = this.getQueryString();
    
       var jspLocation = this.iContext.io.rewriteURI("gadgetWrapper.jsp");
    			
       frame.src = jspLocation + "?url=http://www.google.com/ig/modules/datetime.xml&
       title=&border=&output=js&w=400&" + query;
    }

Implementing the edit view

At this point, you have implemented the mechanism to store the user preferences and to generate the URL to the Google service including the preference values. In this subsection, you populate the ItemSet from the values that are enetered by users. You do this task in three steps:

  1. Implement a graphical interface that lets users pick values for the preferences. To do so, you have to implement the markup of the edit view. This implementation is the view that users interact with when the edit view is enabled. In the case of the Date Time Google gadget, you are interested in letting users customize the background color and the first day of the week. Therefore, you simply implement the edit view as a form with two drop-down lists with the allowed values for the two user preferences.

    Figure 7 shows the edit view of your iWidget wrapping the Date Time gadget.

    Figure 7. Edit view of the iWidget wrapper
    Edit view of the iWidget wrapper

    Listing 13 shows a snippet of markup code as part of the XML descriptor of the iWidget.

    Listing 13. Code of the edit view of the widget <iw:content mode="edit">
       <![CDATA[
       <table>
       <tr>
          <td>Color: </td>
    	<td>
          <select id="color">
    	   <option value="blue">Blue</option>
    	   <option value="green">Green</option>
    	   <!—other options here 
    	</select>
    	</td>
       </tr>
       <tr>
      —-- same principle as for the color drop-down list here -->
       </tr>
       </table>
       <br/>
       <input id="saveButton" type="button" value="Save" 
       onclick="iContext.iScope().onSave()" />
       <input id="cancelButton" type="button" value="Cancel" 
       onclick="iContext.iScope().onCancel()" />
       ]]> 
    </iw:content>

    Note the following from the listing:

    • The markup is placed in an iw:content element with the mode attribute set to edit.
    • The iContext.iScope() method is used to ensure correct encapsulation.
    • The markup is simply an HTML table with two drop-down lists and two buttons (Save and Cancel).
  2. Add methods to the backing logic of your iWidget to populate the ItemSet from the user inputs. To do so, you have to implement the backing logic for the buttons (onSave() and onCancel() methods). Listing 14 shows the code for the onSave() method invoked whenusers click the Save button.
    Listing 14. Code for onSave() method
    onSave: function(){
       // get ItemSet object
       var userPrefs = this.iContext.getItemSet("userPrefs"); 
    
       // set the item values from the drop-down list selections
       userPrefs.setItemValue("color", 
       this.iContext.getElementById("color").value);
       userPrefs.setItemValue("firstDay", 
       this.iContext.getElementById("firstDay").value);
    		
       // switch back to the view mode (widget normal view with the gadget)		
       this.iContext.iEvents.fireEvent("onModeChanged", 
       null, "{newMode: 'view'}");		
    }

    The onSave() method sets the new values for the two preferences in the ItemSet from the user inputs. The last line of the save method is used to return back to the view mode of the widget. To do this, you fire an onModeChanged event against the widget. This event is interpreted by the framework as a request to change the current mode of the widget from edit to view. Following this step, the mechanism about mode handling described in the section “Adding logic to our iWidget” is invoked.

    The objective of the Cancel button is to return to the view mode, without saving the preferences in the ItemSet. Thus ,onCancel() is just the last line of onSave(), which fires the onModeChanged event.

  3. Register the edit mode in the XML descriptor of your iWidget. To do so, add the supportedMode attribute to the iw:iwidget element of your XML descriptor as shown here:
    <iw:iwidget name="googleDateTime"
    xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
    iScope="GoogleGadgetWrapper" supportedModes="edit view">

    When you make this change and redeploy the widget, users see an edit icon in the header bar of the widget in the Home page as shown in Figure 8.

Figure 8. Edit button in the header bar of the iWidget
Edit button in the header bar of the iWidget

When users click the Edit button, the Home page runtime triggers the onModeChanged event against the embedded iWidget. This event causes the framework to render the edit view and invoke a method called onedit in the iScope of the iWidget. To finish, listing 15 shows how to add some logic in the onedit method to set the two drop-down lists in the edit view with the values stored in the ItemSet.

Listing 15. onedit method setting the drop-down lists in the edit view with the stored values
onedit: function(){
   var userPrefs = this.iContext.getItemSet("userPrefs"); 
   this.iContext.getElementById("color").value = userPrefs.getItemValue("color");
   this.iContext.getElementById("firstDay").value = userPrefs.getItemValue("firstDay");
}

Persisting the user preferences

Update: Lotus Connections 2.5 now supports the persistence of user preferences according to the iWidget specifications. While the information in this section is still valid as Lotus Connections 2.5 offers backward compatibility, it is advised to use the standard iWidget way. Refer to the section "iWidget specification v1.0 in Lotus Connections 2.5” of the article "Customizing Lotus Connections 2.5 with Lotus Widget Factory and Google Gadgets” for more details.

The final enhancement for your iWidget wrapper is to persist the user preferences stored in the ItemSet. When you do this task, the customizations made by the user are not lost. The Home page runtime provides two methods (_save and _load) to persist an ItemSet server side.

NOTE: This implementatioon is an extension to the iWidget framework specific to the Home page; it does not work in other iWidget containers, such as Lotus Mashups.

The _save and _load methods accept a URI as the parameter, which is the location where you persist the ItemSet. The serialization used by these methods to encode and decode an ItemSet is beyond the scope of this article. You need to know only that the Home page provides a service (Servlet) accepting and returning the serialized string located at handleUP?Act=XXX&FId=XXX, with Act taking SaveCustomization and LoadCustomization as values and FId being the iWidget ID.

NOTE: In the Home page, you can get the widget ID from the iContext (iContext.widgetId). This variable is specific to the Home page and not part of the iWidget specification.

Listing 16 shows the code of the onLoad method (called just after the widget is placed onto the page) that is responsible for populating the userPrefs ItemSet with the values from the persistence layer. Note that if no value is persisted (meaning that the user has not edited and saved the preferences for this widget), the defaults values are the ones defined in the XML descriptor of the iWidget (listing 9).

Listing 16. Loading the user preferences from the Home page persistence layer
onLoad: function(){
   var userPrefs = this.iContext.getItemSet("userPrefs");
   userPrefs._load("handleUP?Act=LoadCustomization&FId=" + this.iContext.widgetId);
}

Finally, you need to save the ItemSet values. You must do this step whenusers click the Save button in the edit view. Thus, you have to call the _save method on the userPrefs object in the onSave method, just before triggering the onModeChanged event. You can refer to the source code in the EAR file in the Download section of this article.


Conclusion

This article covered the different steps to implement and deploy a basic iWidget wrapping a Google gadget to the Lotus Connections Home page. Besides the implementation of the wrapper itself, this article introduced you to some of the features provided by the iWidget framework through a concrete example. After reading this article, you should know enough about concepts such as XML descriptor, ItemSets, modes, and events to be able to write basic widgets for the Home page. Moreover, you can also continue to implement enhancements to the Google wrapper such as, for example, allowing users to enter the location of the gadget descriptor in the edit view of the iWidget.


Acknowledgments

The author would like to extend his thanks to Luis Benitez for guiding him through the whole process of writing an article for developerWorks. The author would like to thank Adrian Spender for suggesting writing an article about this topic.

Additionally, the author wants to thank Luis, Adrian, and Li Xu for reviewing this article and making suggestions to improve it.


Download

DescriptionNameSize
Code samplegadgetWrapper.ear4KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into IBM collaboration and social software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Lotus
ArticleID=336440
ArticleTitle=Implementing and deploying Google gadgets for the Lotus Connections Home page
publish-date=09292009