From: Wolfram Schneider Date: Thu, 10 Apr 2014 09:55:04 +0000 (+0000) Subject: Merge branch 'master' of ssh://git.indexdata.com:222/home/git/private/mkws X-Git-Tag: 1.0.0~974 X-Git-Url: http://sru.miketaylor.org.uk/?a=commitdiff_plain;h=62c7a550d8ec552fdd92b42c4fff5462730527b1;hp=54ad8cc4e00ba20759b1af5b616e47e41acadc74;p=mkws-moved-to-github.git Merge branch 'master' of ssh://git.indexdata.com:222/home/git/private/mkws --- diff --git a/doc/mkws-developer.txt b/doc/mkws-developer.txt new file mode 100644 index 0000000..321a9c1 --- /dev/null +++ b/doc/mkws-developer.txt @@ -0,0 +1,184 @@ +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 +============================= + +String this.type + A string containing the type of the widget. + +Team this.team + The team object to which this widget belongs. The team has + several additional important properties and methods, described + below. + +DOMElement this.node + The DOM element of the widget + +Hash 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 +
. + +String this.toString() + A function returning a string that briefly names this + widget. Can be useful in logging. + +Void 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 METHODS +============ + +Since the team object is supposed to be opaque to widgets, all access +is via the following API methods rather than direct access to +properties. + +String team.name() +Bool team.submitted() +Num team.perpage() +Num team.totalRecordCount() +Num team.currentPage(); +String team.currentRecordId() +String team.currentRecordData() + Simple accessor functions that provide the ability to read + properties of the team. + +Array team.filters() + Another accessor function, providing access to the array of + prevailing filters (which narrow the search results by means + of Pazpar2 filters and limits). This is really too complicated + an object for the widgets to be given access to, but it's + convenient to do it this way. See the "Navi" widget, which is + the only place it's used. + +Hash team.config() + Access to the team's configuration settings. There is almost + certainly no reason to use this: the settings that haven't + been overridden are accessible via this.config. + +Void team.set_sortOrder(string) +Void team.set_perpage(number) + "Setter" functions for the team's sortOrder and perpage + functions. Unlikely to be needed outside of the "Sort" and + "Perpage" widgets. + +Queue team.queue(eventName) + Returns the queue associated with the named event: this can be + used to subscribe to the event (or more rarely to publish it). + +Bool team.targetFiltered(targetId) + Indicates whether the specified target has been filtered by + selection as a facet. + +Void team.newSearch(query, sortOrder, maxrecs, perpage, limit, targets, targetfilter) + Starts a new search with the specified parameters. All but the + query may be omitted, in which case the prevailing defaults + are used. + +Void team.reShow() + Using the existing search, re-shows the result records after a + change in sort-order, per-page count, etc. + +String team.recordElementId(recordId) + Utility function for converting a record identifer (returned + from Pazpar2) into a version suitable for use as an HTML + element ID. + +String team.renderDetails(recordData) + Utility function returns an HTML rendering of the record + represented by the specified data. + +Template team.loadTemplate(templateName) + Loads (or retrieves from cache) the named Handlebars template, + and returns it in a form that can be invoked as a function, + passed a data-set. + +Some of these methods either (A) are really too low-level and should +not be exposed, or (B) should be widget-level methods. The present +infelicities reflect the fact that some code that rightly belongs in +widgets is still in the team. When we finish migrating it, the widget +API should get simpler. + diff --git a/src/mkws-team.js b/src/mkws-team.js index 4447457..9d9e34c 100644 --- a/src/mkws-team.js +++ b/src/mkws-team.js @@ -48,12 +48,12 @@ function team($, teamName) { // The following PubSub code is modified from the jQuery manual: - // https://api.jquery.com/jQuery.Callbacks/ + // http://api.jquery.com/jQuery.Callbacks/ // // Use as: // team.queue("eventName").subscribe(function(param1, param2 ...) { ... }); // team.queue("eventName").publish(arg1, arg2, ...); - + // var queues = {}; function queue(id) { if (!queues[id]) { @@ -240,6 +240,7 @@ function team($, teamName) { that.reShow = function() { + resetPage(); m_paz.show(0, m_perpage, m_sortOrder); }; diff --git a/src/mkws-widgets.js b/src/mkws-widgets.js index 8b43400..6370952 100644 --- a/src/mkws-widgets.js +++ b/src/mkws-widgets.js @@ -288,7 +288,6 @@ mkws.registerWidgetType('Sort', function() { $(this.node).change(function() { that.team.set_sortOrder($(that.node).val()); if (that.team.submitted()) { - that.team.resetPage(); that.team.reShow(); } return false; @@ -302,7 +301,6 @@ mkws.registerWidgetType('Perpage', function() { $(this.node).change(function() { that.team.set_perpage($(that.node).val()); if (that.team.submitted()) { - that.team.resetPage(); that.team.reShow(); } return false;