02 February 2009

iWidgets: Referring to iContext from innerHTML

Recently, I started creating some widgets for IBM mashup center.

For HTML that is added in the iw:content section of the iWidget xml file, the iContext can used to access the widget functionality:
<iw:content mode="view">
<![CDATA[
<div id="main">
<input type="button" value="update settings"
onclick="iContext.iScope().updateSettings();"/>
</div>
]]>
</iw:content>

Unfortunately, that does not work if you generate the HTML from inside the javascript and use innnerHTML to insert it into the iWidget. For example, the
following code leads to the javascript error "iContext is not defined".
var node = this.iContext.getElementById("main");
var html = '<input type="button" value="update settings"';
html += 'onclick="iContext.iScope().updateSettings();"/>';
node.innerHTML = html;

The reason for this problem is that Mashup Center rewrites the iContext calls from HTML and replaces iContext with the concrete iContext for the widget (something similar to _ns_0643e0a0e66511ddbf33c9dc98c8dde1_iContext, with the ID of the current widget).

To work around this problem, this identifier has to be used instead of iContext when creating HTML with iContext calls from javascript. The following function returns the complete, resolved iContext identifier:
getCompleteiContextIdentifier : function() {
return "_" + this.iContext.widgetId + "_iContext";
}

Using this function, the fixed version of the javascript from above would be the following:
var node = this.iContext.getElementById("main");
var html = '<input type="button" value="update settings"';
html += 'onclick="' + this.getCompleteiContextIdentifier();
html += '.iScope().updateSettings();"/>';
node.innerHTML = html;

This code was tested with IBM Mashup Center 1.1. I don't know if the same problem exists in other versions of Mashup Center.