JMakiWidgetGuidelines < Projects < TWiki
|
TWiki . Projects . JMakiWidgetGuidelines
|
-- Main.gmurray71 - 28 Feb 2008
Guidelines for jMaki Widget Developers
1) Try to look for a similar model and if possible reuse an existing model.
http://wiki.java.net/bin/view/Projects/jMakiDataModels
In general an item in a widget wether it be a button, a tab, and item in an combobox, or leaf in a tree looks like the following:
{ label : 'Some Lable', value : 'foo'}
And a widget with a action looks like.
{ label : 'Some Lable', value : 'foo', action : { topic : '/topic', message : { targetId : 'foo}}
Our interpretation of the M in MVC can contain some presentation related data. For example a tab in a tabbed view can have a property { iframe ; true } where it tells the widget that it's an iframe. A MVC purist may look at this and frown. Actions would also be considered to be more C. I still believe our approach is good so long as we only use data centric models (no functions allowed). The object literals that are the models MUST be serializable to JSON.
2) Decide what goes in the args
Args properties are widget wide and relate to the rendering of the widget.
Things such as padding, the number of rows to display in a block list, sub type of widget, or anything else you want to make easy to configure belongs in args.
The args should have matching properties in the widget.json which are picked up by Netbeans for customizing the widgets and are used for documenting the properties that a widget supports. These are the configurable options we expect 80% of average users to use. More on this later.
3) Decide if properties should be in the args and model
There are some cases like the columns in tables/grids and chart axes where the line between whether to put it in the args versus model gets a little fuzzy. In many cases you want the server to determine the entire columns of the table / chart and you don't want to require it to be in args while there are other cases where you have a good idea before the data is loaded.
Use caution in these cases.
4) If there are actions to be handled use the processActions code from the Spinner. We plan to move this into the common jmaki soon since this code is used everywhere.
/* This function takes an object literal and performs actions if present
* or it publishes a message to the provided topic.
*
* _t = object literal { topic : 'topic to publish to',
* widgetId : 'source widget id',
* targetId : 'foo',
* action : [
* { topic : '/some topic', message : { payload}}
* ],
* value : 'somevalue'
* }
* The action, targetId, and value properties are optional.
* The topic and widgetId are required
*
*/
this.processActions = function(_t) {
if (_t) {
var _topic = _t.topic;
var _m = {widgetId : _t.widgetId, type : _t.type, targetId : _t.targetId};
if (typeof _t.value != "undefined") _m.value = _t.value;
var action = _t.action;
if (!action) _topic = _topic + "/" + _t.type;
if (action && action instanceof Array) {
for (var _a=0; _a < action.length; _a++) {
var payload = _jmaki.clone(_m);
if (action[_a].topic) payload.topic = action[_a].topic;
else payload.topic = _t.topic;
if (action[_a].message) payload.message = action[_a].message;
jmaki.publish(payload.topic,payload);
}
} else {
if (action && action.topic) {
_topic = _m.topic = action.topic;
}
if (action && action.message) _m.message = action.message;
jmaki.publish(_topic,_m);
}
}
};
For now since the code above is not in jmaki.js we are placing it in the widgets that have actions. In 1.1 we plan to have this code shared. Basically this code is able to look at a model element and based on whether or not if it has an action it will publish a generic message or process that action. It's best to see this in context in the Spinner to get a better feel for it.
5) Make sure that the relevant properties and functions are public. Public is :
this.someFunction = function() {}
Where private is:
function privateFunction(){
}
6) Internal in the widget we are setting a property _widget as an internal reference to the widget instance. This prevents problems within closures where "this" can get a little confused.
7) Widgets can be loaded using a service or value. The service loads the data using a jmaki.doAjax request and generally that code path following that request should be the same as if a inline value was provided to the widget.
8) We are using _widget.wrapper to refer to the native widget we are wrapping. This is the real spinner, clock, table widget. We want to keep this consistent so users know what to look for.
9) Try to do widget parameter in a this.postLoad function. This function gets called automatically (if it exists) after the widget instance is created.
10) If you create subscribers make or have other cleanup you need to do make sure to implement a this.destroy function. The destroy function is called before a widget is unloaded. In cases where we do dynamic injection where widgets are replaced jMaki will call destroy on widgets in that region (if the function exists).
11) Don't forget to comment JavaScript code. Even a little comment could go a long way. While we don't expect the average user to go into the JavaScript code the do so comments can go a long way.
12) Add all configurable parameters to widget.json. The dojo clock from the older 0.4.3 Dojo is a good place to look for how to handle all the different types of configuration.
https://widgets.dev.java.net/source/browse/*checkout*/widgets/trunk/code/widgets/dojo/src/resources/dojo/clock/widget.json?rev=627
13) Don't forget to include a screen shot of the image. We use a 150x150 JPG of the widget. These images exist in a images directory under the widget.
----- Revision r1 - 28 Feb 2008 - 04:36:01 - Main.gmurray71
|