1 % The MasterKey Widget Set developer's guide
9 Development with MKWS consists primarily of defining new types of
10 widgets. These can interact with the core functionality is several
13 You create a new widget type by calling the `mkws.registerWidgetType`
14 function, passing in the widget name and a function. The name is used
15 to recognise HTML elements as being widgets of this type -- for
16 example, if you register a `Foo` widget, elements like
17 `<div class="mkwsFoo">` will be widgets of this type.
19 The function promotes a bare widget object (passed as `this`) into a
20 widget of the appropriate type. MKWS doesn't use classes or explicit
21 prototypes: it just makes objects that have the necessary
22 behaviours. There are _no_ behaviours that Widgets are obliged to
23 provide: you can make a doesn't-do-anything-at-all widget if you like:
25 mkws.registerWidgetType('Sluggard', function() {});
27 More commonly, widgets will subscribe to one or more events, so that
28 they're notified when something interesting happens. For example, the
29 `Log` widget asks to be notified when a `log` event happens, and
30 appends the logged message to its node, as follows:
32 mkws.registerWidgetType('Log', function() {
35 this.team.queue("log").subscribe(function(teamName, timestamp, message) {
36 $(that.node).append(teamName + ": " + timestamp + message + "<br/>");
40 This simple widget illustrates several important points:
42 * The base widget object (`this`) has several baked-in properties and
43 methods that are available to individual widgets. These include
44 `this.team` (the team that this widget is a part of) and `this.node`
45 (the DOM element of the widget). See below for a full list.
47 * The team object (`this.team`) also has baked-in properties and
48 methods. These include the `queue` function, which takes an event-name
49 as its argument. See below for a full list.
51 * You can add functionality to a widget by subscribing it to an
52 event's queue using `this.team.queue("EVENT").subscribe`. The
53 argument is a function which is called whenever the event is
54 published. The arguments to the function are different for different
57 * As with so much JavaScript programming, the value of the special
58 variable `this` is lost inside the `subscribez` callback function,
59 so it must be saved if it's to be used inside that callback
60 (typically as a local variable named `that`).
63 Widget specialisation (inheritance)
64 ===================================
66 Many widgets are simple specialisations of existing widgets. For
67 example, the `Record` widget is the same as the `Records` widget
68 except that it defaults to displaying a single record. It's defined as
71 mkws.registerWidgetType('Record', function() {
72 mkws.promotionFunction('Records').call(this);
73 if (!this.config.maxrecs) this.config.maxrecs = 1;
76 Remember that when a promotion function is called, it's passed a base
77 widget object that's not specialised for any particular task. To make
78 a specialised widget, first promote that base widget into the type
79 that you want to specialise from -- in this case, "Records" -- using
80 the promotion function that's been registered for that type.
82 Once this has been done, the specialisations can be introduced. In
83 this case, it's a very simple matter of changing the "maxrecs"
84 configuration setting to 1 unless it's already been given an explicit
85 value. (That would occur if the HTML used an element like <div
86 class="mkwsRecord" maxrecs="2">, though it's not obvious why anyone
90 Widget Properties and Methods
91 =============================
94 A string containing the type of the widget.
97 The team object to which this widget belongs. The team has
98 several additional important properties and methods, described
102 The DOM element of the widget
105 A table of configuration values for the widget. This table
106 inherits missing values from the team's configuration, which
107 in turn inherits from the top-level MKWS configuration, which
108 inherits from the default configuration. Instances of widgets
109 in HTML can set configuration items as HTML attributes, as in
110 <div class="mkwsRecords" maxrecs="2">.
112 String this.toString()
113 A function returning a string that briefly names this
114 widget. Can be useful in logging.
116 Void this.log(string)
117 A function to log a string for debugging purposes. The string
118 is written on the browser console, and also published to any
122 A function returning the value of the widget's HTML element.
128 Since the team object is supposed to be opaque to widgets, all access
129 is via the following API methods rather than direct access to
133 Bool team.submitted()
135 Num team.totalRecordCount()
136 Num team.currentPage();
137 String team.currentRecordId()
138 String team.currentRecordData()
139 Simple accessor functions that provide the ability to read
140 properties of the team.
143 Another accessor function, providing access to the array of
144 prevailing filters (which narrow the search results by means
145 of Pazpar2 filters and limits). This is really too complicated
146 an object for the widgets to be given access to, but it's
147 convenient to do it this way. See the "Navi" widget, which is
148 the only place it's used.
151 Access to the team's configuration settings. There is almost
152 certainly no reason to use this: the settings that haven't
153 been overridden are accessible via this.config.
155 Void team.set_sortOrder(string)
156 Void team.set_perpage(number)
157 "Setter" functions for the team's sortOrder and perpage
158 functions. Unlikely to be needed outside of the "Sort" and
161 Queue team.queue(eventName)
162 Returns the queue associated with the named event: this can be
163 used to subscribe to the event (or more rarely to publish it).
165 Bool team.targetFiltered(targetId)
166 Indicates whether the specified target has been filtered by
167 selection as a facet.
169 Void team.newSearch(query, sortOrder, maxrecs, perpage, limit, targets, targetfilter)
170 Starts a new search with the specified parameters. All but the
171 query may be omitted, in which case the prevailing defaults
175 Using the existing search, re-shows the result records after a
176 change in sort-order, per-page count, etc.
178 String team.recordElementId(recordId)
179 Utility function for converting a record identifer (returned
180 from Pazpar2) into a version suitable for use as an HTML
183 String team.renderDetails(recordData)
184 Utility function returns an HTML rendering of the record
185 represented by the specified data.
187 Template team.loadTemplate(templateName)
188 Loads (or retrieves from cache) the named Handlebars template,
189 and returns it in a form that can be invoked as a function,
192 Some of these methods either (A) are really too low-level and should
193 not be exposed, or (B) should be widget-level methods. The present
194 infelicities reflect the fact that some code that rightly belongs in
195 widgets is still in the team. When we finish migrating it, the widget
196 API should get simpler.
200 Copyright (C) 2013-2014 by IndexData ApS, <http://www.indexdata.com>