Using iWidget support

Use the zero.iwidgets package to build and test iWidgets with IBM® WebSphere® sMash.

What are iWidgets?

An iWidget is a browser-oriented component (regardless of whether or not the "browser" or "web platform" is provided by a traditional browser or some application like XULRunner) designed to work within the framework defined by the iWidget specification. Such a component will only occupy a portion of the overall working canvas and is usually designed in a manner that makes it easy for the canvas assembler to connect the iWidget to other iWidgets on the canvas.

For more information on iWidgets, please see the IBM Mashup Center wiki:

Building your first iWidget

This tutorial will walk you through building two separate iwidgets on sMash, wiring them together, testing them, and then publishing those iWidgets either to Mashup Hub or directly to Lotus Mashups.

Create a new application which will contain your iWidgets. In order for you to run your iWidgets, you will need to add a dependency on zero:zero.iwidgets. This dependency contains all the necessary pieces of a client-side framework for running iWidgets directly in WebSphere sMash.

After adding the dependency, create a new folder in public named 'hello'. This folder will contain a simple widget which prints 'Hello World'.

Inside the 'hello' folder, create a new file named hello.xml. This file will contain the descriptor for your widget, including its content, any information about it (name, description, etc.), and any events it handles or publishes.

Add the following to hello.xml:

<iw:iwidget name="Hello World Widget" xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" supportedModes="view" mode="view" iScope="helloScope">
<iw:content mode="view">
<![CDATA[
<span id="helloSpan"><h1>Hello World</h1></span>
]]>
</iw:content>
</iw:iwidget>

Now create a simple html page which will display your iWidget. In public, create a new file called hello.html.

<html lang="en"> 
<head> 
    <title>Hello</title> 
    <script language="JavaScript" type="text/javascript">                   
        djConfig={isDebug:false,baseUrl:'/dojo/'}  
        ibmConfig = { 
            isDebug: false 
        }; 
    </script> 
    <script type="text/javascript" src='/dojo/dojo.js'></script> 
    <script language="JavaScript" type="text/javascript"> 
        dojo.require("dojo.i18n");
        dojo.registerModulePath("com.ibm.enabler","/mashupmaker/js/com/ibm/enabler") 
      </script> 
    <script type="text/javascript" src="/mashupmaker/js/com/ibm/enabler/enabler.js"></script> 
    <script type="text/javascript" src="/mashupmaker/js/semtag/semanticTagService.js"></script> 
</head> 
<body class="tundra"> 
<div style=" border-style: solid;border-width: 3pt;border-color: #999999; padding: 5px;">
<span class="mm_iWidget" style="color:blue;font-size:12pt;font-family: courier;fact-name:Verdan" id="2"> 
      <a class="mm_Definition" href="/hello/hello.xml" ></a>  
</span>
</div>
</body> 
</html>

Start your application and access: http://localhost:8080/hello.html. You should see your iWidget displayed on the page:

The hello world widget

In order to make this iWidget more interesting, we will give it some dynamic behavior. Upon receipt of an event, it will change its output to reflect a new name. This will require us to edit the descriptor to declare that the iWidget can handle the event and to create a JavaScript event handler.

First, let's edit the descriptor. Add the following inside the iw:iwidget tag:

<iw:event id="sendName" eventDescName="sendName" handled="true" onEvent="onReceiveName" />  
<iw:eventDescription  id="sendName" payloadType="nameData"
      description="event to send a name" lang="en" > 
</iw:eventDescription> 
<iw:resource uri="hello.js" />
<iw:payloadDef name="nameData"> 
<iw:payloadDef name="nameStr" type="string" defaultValue="" description="this field shows a name"/>  
</iw:payloadDef>

This declares that the widget knows how to handle the sendName event which sends nameData (consisting of a single string). It also points to the location of a JavaScript file in the same directory which contains any necessary code, in this case the event handler onReceiveName.

Now create a hello.js file in the same hello folder as hello.xml. Add the following:

dojo.declare("helloScope",null,{ 
      onReceiveName:function(iEvent){ 
         var data = iEvent.payload;
          if (typeof data == "undefined" || data == null) {return;} 
            var name = data.enteredName;
            var element = this.iContext.getElementById("helloSpan");
            element.innerHTML = "<h1>Hello " + name + "</h1>"
     } 
});

The name of this class has to match the iScope defined in the descriptor file. The onReceiveName event handler receives event data, extracts a name from it, and then uses that information to update the greeting.

If you accessed hello.html at this point, the iWidget would not have changed in appearance because there is nothing to send the sendData event and cause it to change. Next you will implement a second widget which publishes this event.

Building your second iWidget

Create a second folder in public called name. This folder will contain a second simple iWidget consisting of a text field and a submit button, where a name can be entered.

Create a name.xml file in the name folder and add the following description of the iWidget:

<iw:iwidget id="nameWidget" name="Name Widget" xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" iScope="nameScope" allowInstanceContent="true" supportedModes="view" 
mode="view" lang="en"> 
    <iw:event id="sendName" eventDescName="sendName"  published="true" onNewWire="sendName" />  
   <iw:eventDescription  id="sendName"  payloadType="nameData" description="event to send a name"  lang="en" > 
   </iw:eventDescription> 
   <iw:resource uri="name.js" />
   <iw:payloadDef name="nameData"> 
        <iw:payloadDef name="nameStr" type="string" defaultValue="" description="this field shows a name"/>  
    </iw:payloadDef> 
    <iw:content mode="view"> 
        <![CDATA[     
            <div> Name: <span id="name"></span></div> 
            <div><span id="nameField" class="nameField">
                <input type="text" dojoType="dijit.form.TextBox" maxlength="32" name="nameBox" id="nameBox" /></span></div> 
            <div><input type="button" name="send" value="Send Name" onclick="iContext.iScope().sendName()"/></div> 
  ]]> 
     </iw:content>
</iw:iwidget>

This declaration is similar to that of the hello widget, except that the sendName event is published rather than handled. The one interesting thing to notice is what happens when the button is clicked. When the button is clicked, a sendName function is invoked via the iScope encapsulation object. This function must be defined in your nameScope class, which you will create in name.js. Create a name.js file in the name folder along with name.xml and add the following:

dojo.declare("nameScope",null,{ 
      sendName:function(){ 
          var data = {}; 
          data.enteredName = this.iContext.getElementById("nameBox").value;
          this.iContext.iEvents.fireEvent("sendName",null,data); 
     } 
});

Again, the name of the class must match the iScope declared in the xml descriptor. The sendName method retrieves the name that has been entered in the text box and fires an event with the name as data. Now we can add this second iWidget to the page we created. Return to hello.html, and add the following above the closing body tag:

<br/>
<br/>
<div style=" border-style: solid;border-width: 3pt;border-color: #999999; padding: 5px;"> 
<span class="mm_iWidget"  style="color:blue;font-size:12pt;font-family: courier;fact-name:Verdan" id="1"> 
      <a class="mm_Definition" href="/name/name.xml"></a> 
</span>
</div>

Even though you have declared that the hello widget handles the sendName event and the name widget publishes it, if you go back to hello.html, enter some text, and click OK, nothing will happen. This is because you need to wire the two iWidgets together. Return to the source for hello.html add the following after the line <a class="mm_Definition" href="/hello/hello.xml" ></a>

<span class="mm_ReceivedEvent" > 
        <a class="mm_SourceEvent" href="#1" style="visibility:hidden">sendName</a> 
        <span class="mm_TargetEvent" style="visibility:hidden">onReceiveName</span>  
</span>

You should now be able to return to http://localhost:8080/hello.html, enter a name into the text box, press OK, and have the greeting change. On the button click the name widget is sending the sendName event and the hello widget is receiving it and calling onReceiveName.

The hello world widget and the name widget working together

Publishing iWidgets to Mashup Hub and Mashups

If you have Mashup Center installed, you can publish your iWidgets running on sMash there. Log in to Mashup Hub and click on "Upload Widget". Select "iWidgets" as the feed data source and click on "Next". Select "Register a Widget URL". For the widget URL, enter the location of the hello.xml page. If Mashup Center is installed on the same machine as sMash you can use http://locallhost:8080/hello/hello.xml. Otherwise replace localhost with the appropriate hostname or ip address of the machine running sMash.
Upload or register a widget
After entering the URL, click on "Next". On the next page you should see the title "Hello World Widget" which was pulled from your descriptor file. Enter a description since it is required and then click on "Finish".

Repeat the process with http://localhost:8080/name/name.xml (replacing localhost as appropriate).

Now that the iWidgets are in Mashup Hub we will add them to Lotus Mashups. Choose "List Widgets" in the Catalog section of MashupHub.


A list of widgets

Click on the name of the Hello World Widget. In the Actions section of the iWidget details, click on "Add to Lotus Mashups". If necessary enter your User ID and password and then click on "Next". Choose what category you want your widget to appear under (for instance, Demo) and an icon to represent your widget in the Lotus Mashups menu. Then click on "Finish".


Adding to Lotus Mashups

Repeat this process with the "Name Widget".

Now that these iWidgets have been added to Mashups, you can go to a new or existing page in Mashups and choose "Go to Edit" in order to add the two iWidgets to a Mashups page and wire them together.

Choose the category that contains each iWidget and drag both the name widget and the hello widget on to the page.


The two widgets on a Mashups page

The next step is to wire the two widgets together using the Mashups gui. On the name widget click on the button which reads "Click to wire widgets". Under "Select content to send" click on "nameData from sendName". Under "Select a widget to receive content" choose the "Hello World Widget". Select the sendName action and then click on "Done".


Wiring the two widgets together

The two iWidgets are now wired together. Click on "Go to view" at the top to test out your iWidgets. The two iWidgets should work just like they did when running purely on sMash.

Version 1.1.0.0.21442