INTRODUCTION
============
Development with MKWS consists primarily of defining new types of
widgets. These can interact with the core functionality is several
defined ways.
You create a new widget type by calling the mkws.registerWidgetType
function, passing in the widget name and a function. The name is used
to recognise HTML elements as being widgets of this type -- for
example, if you register a "Foo" widget, elements like
will be widgets of this type.
The function promotes a bare widget object (passed as `this') into a
widget of the appropriate type. MKWS doesn't use classes or explicit
prototypes: it just makes objects that have the necessary
behaviours. Widgets have *no* behaviours that they have to provide:
you can make a doesn't-do-anything-at-all widget if you like:
mkws.registerWidgetType('Sluggard', function() {});
More commonly, widgets will subscribe to one or more events, so that
they're notified when something interesting happens. For example, the
"Log" widget asks to be notified when a "log" event happens, and
appends the logged message to its node, as follows:
mkws.registerWidgetType('Log', function() {
var that = this;
this.team.queue("log").subscribe(function(teamName, timestamp, message) {
$(that.node).append(teamName + ": " + timestamp + message + "
");
});
});
This simple widget illustrates several important points:
* The base widget object (`this') has several baked-in properties and
methods that are available to individual widgets. These include
this.team (the team that this widget is a part of) and this.node
(the DOM element of the widget).
* The team object (`this.team') also has baked-in properties and
methods. These include the queue function, which takes an event-name
as its argument. It's possible to subscribe to an event's queue
using this.team.queue("EVENT").subscribe. The argument is a function
which is called whenever the event is published. The arguments to
the function are different for different events.
* The value of `this' is lost inside the subscribe callback, so it
must be saved if it's to be used inside that callback (typically as
a local variable named `that').
SPECIALISATION (INHERITANCE)
============================
Many widgets are simple specialisations of existing widgets. For
example, the "Record" widget is the same as the "Records" widget
except that it defaults to displaying a single record. It's defined as
follows:
mkws.registerWidgetType('Record', function() {
mkws.promotionFunction('Records').call(this);
if (!this.config.maxrecs) this.config.maxrecs = 1;
});
Remember that when a promotion function is called, it's passed a base
widget object that's not specialised for any particular task. To make
a specialised widget, first promote that base widget into the type
that you want to specialise from -- in this case, "Records" -- using
the promotion function that's been registered for that type.
Once this has been done, the specialisations can be introduced. In
this case, it's a very matter of changing the "maxrecs" configuration
setting to 1 unless it's already been given an explicit value. (That
would occur if the HTML used an element like
, though it's not obvious why anyone would do that.)
WIDGET PROPERTIES AND METHODS
=============================
this.type -- a string containing the type of the widget.
this.team -- the team object to which this widget belongs. The team
has several additional important properties and methods,
described below.
this.node -- the DOM element of the widget
this.config -- a table of configuration values for the widget. This
table inherits missing values from the team's configuration,
which in turn inherits from the top-level MKWS configuration,
which inherits from the default configuration. Instances of
widgets in HTML can set configuration items as HTML
attributes, as in
.
this.toString() -- a function returning a string that briefly names
this widget. Can be useful in logging.
this.log(string) -- a function to log a string for debugging
purposes. The string is written on the browser console, and
also published to any "log" subcribers.
TEAM PROPERTIES AND METHODS
===========================
team.queue(eventName)
team.name()
team.targetFiltered(targetId)
team.config() -- no reason to use this.
team.log(string)
team.newSearch(query, sortOrder, maxrecs, perpage, limit, targets, targetfilter)
team.totalRecordCount()
team.perpage()
team.currentPage();
team.recordElementId(recordId)
team.currentRecordId()
team.currentRecordData()
team.renderDetails(recordData)
team.loadTemplate(templateName)
team.filters()
team.set_sortOrder(string)
team.submitted()
team.resetPage()
team.reShow()
team.set_perpage(number)