About this task
Create a JavaScript file that declares the
iScope and then define the iScope by identifying its interface. Create the implementation for your
widget by using JavaScript. Continue to develop the
iScope in parallel with developing the widget implementation.
It is recommended that you use
separate JavaScript files for your widget implementation
and the iScope implementation. The iScope implementation loads the widget implementation file using
the Dojo Asynchronous Module Definition (AMD) loader and defers all iWidget handlers to the widget
implementation file.
Tip: Two JavaScript
sample files that define an iScope implementation (MyCustomWidgetNotAMD.js)
and a widget implementation (MyCustomWidget.js) are provided in the sample
.zip file within a sample/custom/widget subdirectory. The
contents of these files correspond to the examples shown in the following procedure. You can use
these files as a starting point for defining your own implementations, and follow the documented
steps to customize the files as required.
- Create the JavaScript iScope implementation with
handlers for the modes that you added in the iWidget definition and for the various events that are
defined in the interface, including the predefined events from the iWidget specification. For the
following predefined iEvents (from the iWidget specification), the dashboard provides default event
handlers, which you can override if needed:
- onLoad
- Is called when the widget loads for the first time and when the browser refreshes. The widget
can initialize the initial view in this handler. The iScope implementation should load the widget
implementation in this handler and pass it a reference to the iWidget. There is no event payload.
You can retrieve the item values by using code similar to these examples: var att =
this.iContext.getiWidgetAttributes(), and this.name =
att.getItemValue("name").
For example, if the widget implementation is in the
sample.custom.widget.MyCustomWidget class, the
onLoad method
is:
onLoad: function() {
// get location of the sample directory
var root = this.iContext.io.rewriteURI("sample");
var context = this;
require(["dojo/Deferred"], function(Deferred) {
context.def = new Deferred();
require({
packages: [
{name: "sample", location: root}
]
}, ["sample/custom/widget/MyCustomWidget"], function(MyCustomWidget) {
try {
if (!context.isUnloaded) {
context.amdModule = new MyCustomWidget();
context.amdModule.onLoad(context);
}
context.def.resolve();
} catch(e) {
console.log(e);
}
});
});
},
In the widget implementation file, the
onLoad method is passed a reference to
the
iWidget:
onLoad:function(iWidget) {
try {
// store the iWidget reference
this.iWidget = iWidget;
console.log("onLoad");
} catch(e) {
console.log(e);
}
},
- onReload
- Is called when the widget is reloaded. This event handler is similar to
onLoad, however, this handler is called in slightly different circumstances. When
a user is in edit mode and selects one of the options at the bottom of the
Settings window, the onReload event handler is called when
the view mode is refreshed. This is slightly different behavior than the iWidget specification calls
for, because the specification specifies that this event must fire before the reload, rather than
during an edit mode refresh of the iWidget content. There is no event payload.
- onUnload
- Is called when the widget is about to be unloaded. There is no event payload.
Important: Ensure that all Dojo widgets that you create are cleaned up during this event
handler. You must call destroyRecursive() to ensure that all child Dojo widgets are
cleaned up in terms of memory usage.
- onRefreshNeeded
- Is called when the iContext determines that the data in the widget is stale. If applicable, this
event signals to the iWidget to refresh its data.
- Create a mode handler for each mode specified in the supportedModes attribute in the widget
definition. For example, if your widget has a view mode and an edit mode, create
onView and onEdit methods.
In the iScope implementation,
the
onView method should wait for the load of the iWidget implementation, and
then defer to the
onView method defined in the iWidget implementation. In the
iScope implementation, the
onView method can be coded as
shown:
onView: function(iEvent) {
var context = this;
this.def.then(function() {
if (!context.isUnloaded) {
context.amdModule.onView(iEvent);
}
}, function(err) {
console.log("ERROR: " + err);
});
},
In
the iWidget implementation, the
onView method can be coded as shown:
onView: function(){
...
}
- Create a handler for the onSizeChanged event in both the iScope and
iWidget implementation. The event has a payload that contains values for the
newWidth and newHeight attributes. The handler uses this
information to resize the widget to the specified width and height. If the user has minimized the
widget, these attributes have a value of 0. The following code shows how to use the
onSizeChanged handler in the iScope implementation to defer to the iWidget
implementation:
onSizeChanged: function(iEvent) {
if (this.amdModule) {
this.amdModule.onSizeChanged(iEvent);
}
},
The following code shows how to use the
onSizeChanged handler in the iWidget
implementation:
onSizeChanged:function(event) {
try {
..
}catch(e) {
console.log(e);
}
},
- Optional: If your widget is accessing data
through REST APIs, use Uniform Resource Identifiers (URIs) in code,
as shown in the following example:
var def = xhr(this.iContext.io.rewriteURI(uri), {
method: "GET",
}, true);
def.then(successFunc, function(err) {
errorFunc(err, def.response);
});
You
can use a similar approach for HTTP actions such as PUT, POST, and DELETE.The variable
def is a Dojo Deferred object. For more information on Deferred objects, read the
dojo/Deferred
article on the Dojo website.
The statement
this.iContext.io.rewriteURI(uri) will generate a URL that uses the Ajax proxy if
the uri refers to a website that is different from the site which is serving the
JavaScript. For information about configuring the proxy, see Configuring the Ajax proxy.
- Optional: If your custom widget uses images
or other files that the browser must retrieve then you must use the getResourceUrl method
provided by the CustomWidgetHelper to generate an absolute URL that
the browser can use. The getResourceUrl method
accepts the iContext class and a URI relative to
your iWidget XML file. See the reference topic CustomWidgetHelper.js helper for custom widgets for details. You must
set the <src> attribute of an <img> tag programmatically by
using the return value from the getResourceUrl method.
The following example references the file myImageFile.png in
a directory named images. The directory is in
the same location as the iWidget XML file.
var myWidgetImage = document.createElement("img");
var myWidgetImageUrl = this.customWidgetHelper.getResourceUrl(this.iContext,"./images/myImageFile.png");
myWidgetImage.setAttribute("src", myWidgetImageUrl);