Merge remote branch 'origin/master' into wosch
authorWolfram Schneider <wosch@indexdata.dk>
Mon, 19 May 2014 11:25:47 +0000 (11:25 +0000)
committerWolfram Schneider <wosch@indexdata.dk>
Mon, 19 May 2014 11:25:47 +0000 (11:25 +0000)
20 files changed:
doc/README.markdown
doc/whitepaper.markdown
examples/htdocs/mike.html
examples/htdocs/mkws-widget-credo.css [new file with mode: 0644]
examples/htdocs/mkws-widget-credo.js [new file with mode: 0644]
examples/htdocs/mkws-widget-ru.css [new file with mode: 0644]
examples/htdocs/mkws-widget-ru.html [new file with mode: 0644]
examples/htdocs/mkws-widget-ru.js [new file with mode: 0644]
examples/htdocs/mkws-widget-ru.readme [new file with mode: 0644]
src/mkws-core.js
src/mkws-filter.js
src/mkws-jquery.js
src/mkws-team.js
src/mkws-widget-authname.js
src/mkws-widget-builder.js
src/mkws-widget-categories.js
src/mkws-widget-log.js
src/mkws-widget-main.js
src/mkws-widget-termlists.js
src/mkws-widget.js

index 49d415d..667cf4f 100644 (file)
@@ -75,6 +75,7 @@ possible options:
         show_lang: true,            /* true, false: show/hide language menu */
         show_sort: true,            /* true, false: show/hide sort menu */
         show_perpage: true,         /* true, false: show/hide perpage menu */
+        show_switch: true,          /* true, false: show/hide switch menu */
         lang_options: ["en", "de", "da"],
                                     /* display languages links for given languages, [] for all */
         facets: ["xtargets", "subject", "author"],
index 74a3234..55c56ec 100644 (file)
@@ -394,6 +394,9 @@ show_perpage              bool    true      Indicates whether or not to display
 
 show_sort                 bool    true      Indicates whether or not to display the sort menu.
 
+show_switch               bool    true      Indicates whether or not to display the switch menu, for switching between showing
+                                            retrieved records and target information.
+
 sort_default              string  relevance The label of the default sort criterion to use. Must be one of those in the `sort`
                                             array.
 
@@ -405,8 +408,8 @@ use_service_proxy         bool    true      If true, then a Service Proxy is use
                                             Pazpar2.
 ---
 
-Perhaps we should get rid of the `show_lang`, `show_perpage` and
-`show_sort` configuration items, and simply display the relevant menus
+Perhaps we should get rid of the `show_lang`, `show_perpage`,
+`show_sort` and `show_switch` configuration items, and simply display the relevant menus
 only when their containers are provided -- e.g. an `mkwsLang` element
 for the language menu. But for now we retain these, as an easier route
 to lightly customise the display than my changing providing a full HTML
index 3f87083..f93e2ab 100644 (file)
@@ -1,14 +1,10 @@
-<?xml version="1.0"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
+<html>
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-    <title>MKWS demo: Mike's playground</title>
-    <link rel="stylesheet" type="text/css" href="http://x.mkws.indexdata.com/mkws.css" />
-    <link rel="stylesheet" type="text/css" href="mkws-widget-reference.css" />
+    <title>MKWS demo: Reference Universe widget</title>
+    <link rel="stylesheet" type="text/css" href="mkws-widget-credo.css" />
     <script type="text/javascript">
-      var mkws_config = { service_proxy_auth: "//mkws.indexdata.com/service-proxy-testauth",
-                          responsive_design_width: 800 };
+      var mkws_config = { service_proxy_auth: "//mkws.indexdata.com/service-proxy-testauth" };
     </script>
     <script type="text/javascript" src="//code.jquery.com/jquery-1.10.0.min.js"></script>
     <script type="text/javascript" src="//x.mkws.indexdata.com/jquery.json-2.4.js"></script>
     <script type="text/javascript" src="src/mkws-widget-log.js"></script>
     <script type="text/javascript" src="src/mkws-widget-record.js"></script>
     <script type="text/javascript" src="src/mkws-widget-builder.js"></script>
-    <script type="text/javascript" src="src/mkws-jquery.js"></script>
-    <script type="text/javascript" src="mkws-widget-reference.js"></script>
-    <script type="text/javascript">$ = undefined;</script>
+    <script type="text/javascript" src="mkws-widget-credo.js"></script>
   </head>
-<!--
   <body>
-    <div class='mkwsReference' autosearch='!param!q'>result will appear here</div>
-  </body>
--->
-  <body>
-    <script type="text/javascript">$ = undefined;</script>
-    <div class="mkwsSwitch"></div>
-    <div class="mkwsLang"></div>
-    <div class="mkwsSearch-Container-wide"><div class="mkwsSearch"></div></div>
-    <div class="mkwsResults"></div>
-    <div class="mkwsTargets"></div>
-    <div class="mkwsStat"></div>
-    <div class="mkwsBuilder"></div>
-    <div class="mkwsSearch-Container-narrow"></div>
-    <script type="text/javascript">$ = undefined;</script>
+    <div class='mkwsCredo' autosearch='!param!q'>result will appear here</div>
+    <div class='mkwsConfig' perpage='10'></div>
   </body>
 </html>
diff --git a/examples/htdocs/mkws-widget-credo.css b/examples/htdocs/mkws-widget-credo.css
new file mode 100644 (file)
index 0000000..4cb10cb
--- /dev/null
@@ -0,0 +1,3 @@
+.mkwsCredo {
+    font-family: Gill Sans, "Gillius ADF", Gillius, GilliusADF, Verdana, Sans-Serif;
+}
diff --git a/examples/htdocs/mkws-widget-credo.js b/examples/htdocs/mkws-widget-credo.js
new file mode 100644 (file)
index 0000000..7ea0169
--- /dev/null
@@ -0,0 +1,51 @@
+mkws.registerWidgetType('Credo', function() {
+  s = []
+  s.push('<table>');
+
+  // Main panel: encylopaedia and images on the left, topics on the right
+  s.push('<tr>');
+
+  s.push('<td class="main">');
+
+  s.push('<div class="encyclopaedia">');
+  s.push('<div class="title">Topic Page: ### title</div>');
+  s.push(this.subwidget('Reference'));
+  s.push('</div>');
+
+  s.push('<div class="images">');
+  s.push('<div class="title">Images</div>');
+  s.push(this.subwidget('Images', { /* ### config */ } ));
+  s.push('</div>');
+
+  s.push('</td>');
+
+  s.push('<td class="side">');
+
+  s.push('<div class="mindmap">');
+  s.push('<div class="title">Create a Mind Map for ### title</div>');
+  // ### Is there a way to make a mind-map?
+  s.push('</div>');
+
+  s.push('<div class="topics">');
+  s.push('<div class="title">Related Topics</div>');
+  s.push(this.subwidget('Facet', { facet: 'subject' }));
+  s.push('</div>');
+
+  s.push('</td>');
+
+  s.push('</tr>');
+
+  s.push('<tr>');
+  s.push('</td>');
+  s.push('<div class="entries">');
+  s.push('<div class="title">Credo Entries</div>');
+  s.push(this.subwidget('Records', { /* ### config */ }));
+  s.push('</div>');
+  s.push('</td>');
+  s.push('</tr>');
+
+  // More TRs for Articles, Books, News, Suggested Resources
+  s.push('</table>');
+
+  this.node.html(s.join(''));
+});
diff --git a/examples/htdocs/mkws-widget-ru.css b/examples/htdocs/mkws-widget-ru.css
new file mode 100644 (file)
index 0000000..39765ff
--- /dev/null
@@ -0,0 +1,31 @@
+.mkwsReferenceUniverse {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  background: #FCFBFA;
+  padding: 0.5em 1em 0.25em;
+  box-shadow: 0 0 2px 0 #7F8F93;
+  border-radius: 0 0 1.5em;
+  -moz-border-radius: 0 0 1.5em;
+  -webkit-border-radius: 0 0 1.5em;
+  line-height: 1.4;
+  color: #86979B;
+  background: radial-gradient(ellipse at center,  #ffffff 0%,#f8f8f8 100%);
+}
+
+h2 {
+  font-size: 100%;
+  color: #4A5456;
+  padding-bottom: .5em;
+}
+
+.record, .mkwsSummary {
+  margin: .95em .25em;
+  padding-top: .75em;
+  border-top: 1px dotted #BEC8CC;
+  font-size: 90%;
+}
+
+a {
+  text-decoration: none;
+  font-weight:normal;
+  color: #2B77AF;
+}
diff --git a/examples/htdocs/mkws-widget-ru.html b/examples/htdocs/mkws-widget-ru.html
new file mode 100644 (file)
index 0000000..64ef386
--- /dev/null
@@ -0,0 +1,8 @@
+<html>
+  <div style="max-width: 18em; margin: 1.5em 1.5em">
+    <script src="//mkws.indexdata.com/mkws-complete.js"></script>
+    <script src="mkws-widget-ru.js"></script>
+    <link rel="stylesheet" type="text/css" href="mkws-widget-ru.css" />
+    <div class="mkwsReferenceUniverse" autosearch="!param!q"></div>
+  </div>
+</html>
diff --git a/examples/htdocs/mkws-widget-ru.js b/examples/htdocs/mkws-widget-ru.js
new file mode 100644 (file)
index 0000000..4b7054f
--- /dev/null
@@ -0,0 +1,7 @@
+mkws.registerWidgetType('ReferenceUniverse', function() {
+    //this.team.config.service_proxy_auth = "http://mkws.indexdata.com/service-proxy/?command=auth&action=login&username=paratext&password=paratext_mkc";
+    // this.team.config.perpage_default = 5;
+    // this.team.config.sort_default = "position";
+    this.node.html("<h2>Reference Universe results:</h2>\n" +
+                   this.subwidget('Records', { sort: 'position', perpage: 5 }));
+});
diff --git a/examples/htdocs/mkws-widget-ru.readme b/examples/htdocs/mkws-widget-ru.readme
new file mode 100644 (file)
index 0000000..c55272e
--- /dev/null
@@ -0,0 +1,34 @@
+# Embedding Reference Universe with MKWS
+
+## Quick start
+Simply paste this inline with the markup on any page: 
+
+    <script src="//mkws.indexdata.com/mkws-complete.js"></script>
+    <script src="//mkws.indexdata.com/mkws-widget-ru.js"></script>
+    <link rel="stylesheet" type="text/css" href="//mkws.indexdata.com/mkws-widget-ru.css" />
+    <div class="mkwsReferenceUniverse" autosearch="!param!q"></div>
+    
+## A bit more detail 
+
+The MasterKey Widget Set ([MKWS](http://mkws.indexdata.com/)) lets you easily embed search-enabled widgets which run in the client browser and display results from a web service. In this case, it searches Reference Universe.
+
+You need to include two scripts: one for MKWS and one for the Reference Universe widget. This can be inline as above or you can include them in the header or aggregate them with your application's scripts.
+
+    <script src="//mkws.indexdata.com/mkws-complete.js"></script>
+    <script src="//mkws.indexdata.com/mkws-widget-ru.js"></script>
+    
+The provided stylesheet is generic and you're encouraged to replace it entirely by styling the new elements to fit seamlessly with your content. 
+
+    <link rel="stylesheet" type="text/css" href="//mkws.indexdata.com/mkws-widget-ru.css" />
+    
+Any element you give the class `mkwsReferenceUniverse` will have is contents replaced by the top results from a search against the Reference Universe service for the current query.
+    
+    <div class="mkwsReferenceUniverse" autosearch="!param!q"></div>
+
+### Finding the query 
+
+The `autosearch` attribute of the widget container lets it know where to find the query. There are three places it might look to find that you're searching for *water*: 
+
+* `!param!foo` indicates a GET parameter and would match `http://site.tld/search?foo=water`
+* `!path!2` will take the 2nd path component from the end of the url and would find the query in `http://site.tld/apps/search/water/mobile`
+* `!var!foo` will look for the query in a JavaScript variable named `foo` in the `window` context (ie. a top level variable)
index 89f434e..0af84a9 100644 (file)
@@ -148,7 +148,8 @@ mkws.setMkwsConfig = function(overrides) {
     query_width: 50,
     show_lang: true,    /* show/hide language menu */
     show_sort: true,    /* show/hide sort menu */
-    show_perpage: true,         /* show/hide perpage menu */
+    show_perpage: true, /* show/hide perpage menu */
+    show_switch: true,  /* show/hide switch menu */
     lang_options: [],   /* display languages links for given languages, [] for all */
     facets: ["xtargets", "subject", "author"], /* display facets, in this order, [] for none */
     responsive_design_width: undefined, /* a page with less pixel width considered as narrow */
@@ -309,10 +310,9 @@ mkws.pagerNext = function(tname) {
 };
 
 
-// wrapper to call team() after page load
-(function(j) {
+// wrapper to provide local copy of the jQuery object.
+(function($) {
   var log = mkws.log;
-  var $ = j; // XXX
 
   function handleNodeWithTeam(node, callback) {
     // First branch for DOM objects; second branch for jQuery objects
@@ -364,11 +364,11 @@ mkws.pagerNext = function(tname) {
           var w1 = team.widget(t + "-Container-" + from);
           var w2 = team.widget(t + "-Container-" + to);
           if (w1) {
-            w1.jqnode.hide();
+            w1.node.hide();
           }
           if (w2) {
-            w2.jqnode.show();
-            w.jqnode.appendTo(w2.jqnode);
+            w2.node.show();
+            w.node.appendTo(w2.node);
           }
         });
         team.queue("resize-" + to).publish();
@@ -383,7 +383,7 @@ mkws.pagerNext = function(tname) {
    * for the site.
    */
   function authenticateSession(auth_url, auth_domain, pp2_url) {
-    log("Run service proxy auth URL: " + auth_url);
+    log("service proxy authentication on URL: " + auth_url);
 
     if (!auth_domain) {
       auth_domain = pp2_url.replace(/^(https?:)?\/\/(.*?)\/.*/, '$2');
@@ -406,7 +406,7 @@ mkws.pagerNext = function(tname) {
         return;
       }
 
-      log("Service proxy auth successfully done");
+      log("service proxy authentication successful");
       mkws.authenticated = true;
       var authName = $(data).find("displayName").text();
       // You'd think there would be a better way to do this:
@@ -430,7 +430,7 @@ mkws.pagerNext = function(tname) {
 
 
   function selectorForAllWidgets() {
-    if (mkws.config.scan_all_nodes) {
+    if (mkws.config && mkws.config.scan_all_nodes) {
       // This is the old version, which works by telling jQuery to
       // find every node that has a class beginning with "mkws". In
       // theory it should be slower than the class-based selector; but
@@ -462,12 +462,12 @@ mkws.pagerNext = function(tname) {
       handleNodeWithTeam(this, function(tname, type) {
         var myTeam = mkws.teams[tname];
         if (!myTeam) {
-          myTeam = mkws.teams[tname] = team(j, tname);
-          log("Made MKWS team '" + tname + "'");
+          myTeam = mkws.teams[tname] = team($, tname);
+          log("made MKWS team '" + tname + "'");
         }
 
         var oldHTML = this.innerHTML;
-        var myWidget = widget(j, myTeam, type, this);
+        var myWidget = widget($, myTeam, type, this);
         myTeam.addWidget(myWidget);
         var newHTML = this.innerHTML;
         if (newHTML !== oldHTML) {
@@ -479,7 +479,8 @@ mkws.pagerNext = function(tname) {
   }
 
 
-  $(document).ready(function() {
+  function init(rootsel) {
+    if (!rootsel) var rootsel = ':root';
     var saved_config;
     if (typeof mkws_config === 'undefined') {
       log("setting empty config");
@@ -496,7 +497,7 @@ mkws.pagerNext = function(tname) {
           var lang = key.replace(/^language_/, "");
           // Copy custom languages into list
           mkws.locale_lang[lang] = mkws.config[key];
-          log("Added locally configured language '" + lang + "'");
+          log("added locally configured language '" + lang + "'");
         }
       }
     }
@@ -511,14 +512,14 @@ mkws.pagerNext = function(tname) {
     log("using language: " + (mkws.config.lang ? mkws.config.lang : "none"));
 
     if (mkws.config.query_width < 5 || mkws.config.query_width > 150) {
-      log("Reset query width: " + mkws.config.query_width);
+      log("reset query width to " + mkws.config.query_width);
       mkws.config.query_width = 50;
     }
 
     // protocol independent link for pazpar2: "//mkws/sp" -> "https://mkws/sp"
     if (mkws.config.pazpar2_url.match(/^\/\//)) {
       mkws.config.pazpar2_url = document.location.protocol + mkws.config.pazpar2_url;
-      log("adjusted protocol independent link to: " + mkws.config.pazpar2_url);
+      log("adjusted protocol independent link to " + mkws.config.pazpar2_url);
     }
 
     if (mkws.config.responsive_design_width) {
@@ -544,15 +545,15 @@ mkws.pagerNext = function(tname) {
     }
 
     var then = $.now();
-    makeWidgetsWithin(1, $(':root'));
+    makeWidgetsWithin(1, $(rootsel));
     var now = $.now();
 
-    log("Walking MKWS nodes took " + (now-then) + " ms");
+    log("walking MKWS nodes took " + (now-then) + " ms");
 
     /*
       for (var tName in mkws.teams) {
       var myTeam = mkws.teams[tName]
-      log("TEAM '" + tName + "' = " + myTeam + " ...");
+      log("team '" + tName + "' = " + myTeam + " ...");
       myTeam.visitWidgets(function(t, w) {
       log("  has widget of type '" + t + "': " + w);
       });
@@ -567,5 +568,9 @@ mkws.pagerNext = function(tname) {
       // raw pp2
       runAutoSearches();
     }
+  };
+  $(document).ready(function() {
+    var widgetSelector = selectorForAllWidgets();
+    if (widgetSelector && $(widgetSelector).length !== 0) init();
   });
 })(jQuery);
index 4383ac9..22aeb20 100644 (file)
@@ -45,9 +45,9 @@ function filterSet(team) {
     for (var i in m_list) {
       var filter = m_list[i];
       if (matchFn(filter)) {
-        m_team.log("removeMatching() removing filter " + mkws.$.toJSON(filter));
+        m_team.log("removeMatching: removing filter " + mkws.$.toJSON(filter));
       } else {
-        m_team.log("removeMatching() keeping filter " + mkws.$.toJSON(filter));
+        m_team.log("removeMatching: keeping filter " + mkws.$.toJSON(filter));
         newList.push(filter);
       }
     }
index 90e43e4..73bd406 100644 (file)
@@ -11,7 +11,7 @@
  */
 function _mkws_jquery_plugin($) {
   function debug(string) {
-    mkws.log("jquery.pazpar2: " + string);
+    mkws.log("jQuery.pazpar2: " + string);
   }
 
   function init_popup(obj) {
index a1f664a..8523ec7 100644 (file)
@@ -83,12 +83,11 @@ function team($, teamName) {
   that.log = log;
 
 
-  log("start running MKWS");
+  log("making new widget team");
 
   m_sortOrder = m_config.sort_default;
   m_perpage = m_config.perpage_default;
 
-  log("Create main pz2 object");
   // create a parameters array and pass it to the pz2's constructor
   // then register the form submit event with the pz2.search function
   // autoInit is set to true on default
@@ -104,6 +103,7 @@ function team($, teamName) {
                     "showtime": 500,            //each timer (show, stat, term, bytarget) can be specified this way
                     "termlist": m_config.facets.join(',')
                   });
+  log("created main pz2 object");
 
   // pz2.js event handlers:
   function onInit() {
@@ -113,7 +113,7 @@ function team($, teamName) {
   }
 
   function onBytarget(data) {
-    log("target");
+    log("bytarget");
     queue("targets").publish(data);
   }
 
@@ -360,7 +360,7 @@ function team($, teamName) {
 
   function widgetNode(type) {
     var w = that.widget(type);
-    return w ? w.jqnode : undefined;
+    return w ? w.node : undefined;
   }
 
   function renderDetails(data, marker) {
index abca07e..b1e0b1f 100644 (file)
@@ -2,6 +2,6 @@ mkws.registerWidgetType('Authname', function() {
   var that = this;
 
   this.team.queue("authenticated").subscribe(function(authName) {
-    that.jqnode.html(authName);
+    that.node.html(authName);
   });
 });
index 2092a75..60ee37b 100644 (file)
@@ -6,7 +6,7 @@ mkws.registerWidgetType('Builder', function() {
     type: 'button',
     text: this.config.text || "Build!"
   });
-  this.jqnode.append(this.button);
+  this.node.append(this.button);
   this.button.click(function() {
     var   query = team.widget('Query').value();
     var    sort = team.widget('Sort').value();
@@ -24,6 +24,6 @@ mkws.registerWidgetType('Builder', function() {
 mkws.registerWidgetType('ConsoleBuilder', function() {
   mkws.promotionFunction('Builder').call(this);
   this.callback = function(s) {
-    console.log("Generated widget: " + s);
+    console.log("generated widget: " + s);
   }
 });
index bec99f5..a11e522 100644 (file)
@@ -29,7 +29,7 @@ mkws.registerWidgetType('Categories', function() {
         text.push("<option value='", id, "'>", name, "</option>");
       });
       text.push("</select>");
-      that.jqnode.html(text.join(''));
+      that.node.html(text.join(''));
     });
   });
 });
index 6f3947f..4ea6cd8 100644 (file)
@@ -2,6 +2,6 @@ mkws.registerWidgetType('Log', function() {
   var that = this;
 
   this.team.queue("log").subscribe(function(teamName, timestamp, message) {
-    that.jqnode.append(teamName + ": " + timestamp + message + "<br/>");
+    that.node.append(teamName + ": " + timestamp + message + "<br/>");
   });
 });
index a688eac..9271602 100644 (file)
@@ -4,11 +4,12 @@
 
 
 mkws.registerWidgetType('Targets', function() {
+  if (!this.config.show_switch) return;
   var that = this;
   var M = mkws.M;
 
-  this.jqnode.html('No information available yet.');
-  this.jqnode.css("display", "none");
+  this.node.html('No information available yet.');
+  this.node.css("display", "none");
 
   this.team.queue("targets").subscribe(function(data) {
     var table ='<table><thead><tr>' +
@@ -28,7 +29,7 @@ mkws.registerWidgetType('Targets', function() {
     }
 
     table += '</tbody></table>';
-    that.jqnode.html(table);
+    that.node.html(table);
   });
 });
 
@@ -38,7 +39,7 @@ mkws.registerWidgetType('Stat', function() {
   var M = mkws.M;
 
   this.team.queue("stat").subscribe(function(data) {
-    that.jqnode.html(' -- ' +
+    that.node.html(' -- ' +
                       '<span class="mkwsClientCount">' + M('Active clients') + ': ' + data.activeclients + '/' + data.clients + '</span>' +
                       ' -- ' +
                       M('Retrieved records') + ': ' + data.records + '/' + data.hits);
@@ -51,7 +52,7 @@ mkws.registerWidgetType('Pager', function() {
   var M = mkws.M;
 
   this.team.queue("pager").subscribe(function(data) {
-    that.jqnode.html(drawPager(data))
+    that.node.html(drawPager(data))
 
     function drawPager(data) {
       var teamName = that.team.name();
@@ -129,7 +130,7 @@ mkws.registerWidgetType('Records', function() {
           html.push(team.renderDetails(team.currentRecordData()));
       }
     }
-    that.jqnode.html(html.join(''));
+    that.node.html(html.join(''));
 
     function renderSummary(hit) {
       var template = team.loadTemplate(that.config.template || "Summary");
@@ -165,7 +166,7 @@ mkws.registerWidgetType('Navi', function() {
         ');return false;">' + value + '</a>';
     });
 
-    that.jqnode.html(text);
+    that.node.html(text);
   });
 });
 
@@ -176,8 +177,8 @@ mkws.registerWidgetType('Navi', function() {
 mkws.registerWidgetType('Sort', function() {
   var that = this;
 
-  this.jqnode.change(function() {
-    that.team.set_sortOrder(that.jqnode.val());
+  this.node.change(function() {
+    that.team.set_sortOrder(that.node.val());
     if (that.team.submitted()) {
       that.team.reShow();
     }
@@ -189,8 +190,8 @@ mkws.registerWidgetType('Sort', function() {
 mkws.registerWidgetType('Perpage', function() {
   var that = this;
 
-  this.jqnode.change(function() {
-    that.team.set_perpage(that.jqnode.val());
+  this.node.change(function() {
+    that.team.set_perpage(that.node.val());
     if (that.team.submitted()) {
       that.team.reShow();
     }
@@ -203,14 +204,15 @@ mkws.registerWidgetType('Done', function() {
   var that = this;
 
   this.team.queue("complete").subscribe(function(n) {
-    that.jqnode.html("Search complete: found " + n + " records");
+    that.node.html("Search complete: found " + n + " records");
   });
 });
 
 
 mkws.registerWidgetType('Switch', function() {
+  if (!this.config.show_switch) return;
   var tname = this.team.name();
-  this.jqnode.html('\
+  this.node.html('\
 <a href="#" onclick="mkws.switchView(\'' + tname + '\', \'records\')">Records</a><span> \
 | \
 </span><a href="#" onclick="mkws.switchView(\'' + tname + '\', \'targets\')">Targets</a>');
@@ -222,7 +224,7 @@ mkws.registerWidgetType('Search', function() {
   var tname = this.team.name();
   var M = mkws.M;
 
-  this.jqnode.html('\
+  this.node.html('\
 <form name="mkwsSearchForm" class="mkwsSearchForm mkwsTeam_' + tname + '" action="" >\
   <input class="mkwsQuery mkwsTeam_' + tname + '" type="text" size="' + this.config.query_width + '" />\
   <input class="mkwsButton mkwsTeam_' + tname + '" type="submit" value="' + M('Search') + '" />\
@@ -232,7 +234,7 @@ mkws.registerWidgetType('Search', function() {
 
 mkws.registerWidgetType('SearchForm', function() {
   var team = this.team;
-  this.jqnode.submit(function() {
+  this.node.submit(function() {
     var val = team.widget('Query').value();
     team.newSearch(val);
     return false;
@@ -243,7 +245,7 @@ mkws.registerWidgetType('SearchForm', function() {
 mkws.registerWidgetType('Results', function() {
   var tname = this.team.name();
 
-  this.jqnode.html('\
+  this.node.html('\
 <table width="100%" border="0" cellpadding="6" cellspacing="0">\
   <tr>\
     <td class="mkwsTermlists-Container-wide mkwsTeam_' + tname + '" width="250" valign="top">\
@@ -281,13 +283,13 @@ mkws.registerWidgetType('Ranking', function() {
   }
   s += '</form>';
 
-  this.jqnode.html(s);
+  this.node.html(s);
 
 
   function mkwsHtmlSort() {
     var order = that.team.sortOrder();
 
-    that.log("HTML sort, sortOrder = '" + order + "'");
+    that.log("making sort HTML, sortOrder = '" + order + "'");
     var sort_html = '<select class="mkwsSort mkwsTeam_' + tname + '">';
 
     for(var i = 0; i < that.config.sort_options.length; i++) {
@@ -309,7 +311,7 @@ mkws.registerWidgetType('Ranking', function() {
   function mkwsHtmlPerpage() {
     var perpage = that.team.perpage();
 
-    that.log("HTML perpage, perpage = " + perpage);
+    that.log("making perpage HTML, perpage = " + perpage);
     var perpage_html = '<select class="mkwsPerpage mkwsTeam_' + tname + '">';
 
     for(var i = 0; i < that.config.perpage_options.length; i++) {
@@ -353,7 +355,7 @@ mkws.registerWidgetType('Lang', function() {
   if (lang_options.length == 0 || toBeIncluded[lang_default])
     list.push(lang_default);
 
-  this.log("Language menu for: " + list.join(", "));
+  this.log("language menu: " + list.join(", "));
 
   /* the HTML part */
   var data = "";
@@ -369,7 +371,7 @@ mkws.registerWidgetType('Lang', function() {
     }
   }
 
-  this.jqnode.html(data);
+  this.node.html(data);
   widget.hideWhenNarrow(this);
 
 
@@ -398,7 +400,22 @@ mkws.registerWidgetType('MOTD', function() {
   var container = this.team.widget('MOTDContainer');
   if (container) {
     // Move the MOTD from the provided element down into the container
-    this.jqnode.appendTo(container.node); // #### can this be container.jqnode
+    this.node.appendTo(container.node);
+  }
+});
+
+
+// This widget has no functionality of its own, but its configuration
+// is copied up into its team, allowing it to affect other widgets in
+// the team.
+//
+mkws.registerWidgetType('Config', function() {
+  var c = this.config;
+  for (var name in c) {
+    if (c.hasOwnProperty(name)) {
+      this.team.config()[name] = c[name];
+      this.log(this + " copied property " + name + "='" + c[name] + "' up to team");
+    }
   }
 });
 
index 776ef5b..dc89504 100644 (file)
@@ -3,10 +3,10 @@ mkws.registerWidgetType('Termlists', function() {
 
   // Initially hide the termlists; display when we get results
   mkws.$(document).ready(function() {
-    that.jqnode.hide();
+    that.node.hide();
   });
   this.team.queue("termlists").subscribe(function(data) {
-    that.jqnode.show();
+    that.node.show();
   });
 
   var acc = [];
@@ -15,7 +15,7 @@ mkws.registerWidgetType('Termlists', function() {
   for (var i = 0; i < facets.length; i++) {
     acc.push('<div class="mkwsFacet mkwsTeam_', this.team.name(), '" data-mkws-facet="', facets[i], '">', '</div>');
   }
-  this.jqnode.html(acc.join(''));
+  this.node.html(acc.join(''));
 
   widget.autosearch(this);
 });
@@ -30,9 +30,9 @@ mkws.registerWidgetType('Facet', function() {
 
   var that = this;
   var name = that.config.facet;
-  var ref = facetConfig[name] || alert("no facet definition for '" + name + "'");
-  var caption = ref[0];
-  var max = ref[1];
+  var ref = facetConfig[name] || [ "Unknown", 10, true ];
+  var caption = this.config['facet_caption_' + name] || ref[0];
+  var max     = this.config['facet_max_' + name]     || ref[1];
   var pzIndex = ref[2] ? name : null;
 
   that.toString = function() {
@@ -63,6 +63,6 @@ mkws.registerWidgetType('Facet', function() {
       acc.push('</div>');
     }
 
-    that.jqnode.html(acc.join(''));
+    that.node.html(acc.join(''));
   });
 });
index a201424..25e6855 100644 (file)
@@ -9,8 +9,7 @@ function widget($, team, type, node) {
   var that = {
     team: team,
     type: type,
-    node: node,
-    jqnode: $(node),
+    node: $(node),
     config: mkws.objectInheritingFrom(team.config())
   };
 
@@ -25,7 +24,35 @@ function widget($, team, type, node) {
 
   that.value = function() {
     return node.value;
-  }
+  };
+
+  // Returns the HTML of a subwidget of the specified type. It gets
+  // the same attributes at the parent widget that invokes this
+  // function, except where overrides are passed in.
+  that.subwidget = function(type, overrides) {
+    var attrs = {};
+    
+    // Copy locally-set properties from the parent widget
+    for (var name in this.config) {
+      if (this.config.hasOwnProperty(name)) {
+        attrs[name] = this.config[name];
+        log(this + " copied property " + name + "='" + attrs[name] + "' to " + type + " subwidget");
+      }
+    }
+    
+    for (var name in overrides) {
+      attrs[name] = overrides[name];
+      log(this + " overrode property " + name + "='" + attrs[name] + "' for " + type + " subwidget");
+    }
+
+    var s = [];
+    s.push('<div class="mkws', type, ' ', team.name(), '"');
+    for (var name in attrs) {    
+      s.push(' ', name, '="', attrs[name], '"');
+    }
+    s.push('></div>');
+    return s.join('');
+  };
 
   for (var i = 0; i < node.attributes.length; i++) {
     var a = node.attributes[i];
@@ -45,10 +72,10 @@ function widget($, team, type, node) {
     } else if (a.name.match (/^data-mkws-/)) {
       var name = a.name.replace(/^data-mkws-/, '')
       that.config[name] = a.value;
-      log(node + ": set data-mkws attribute " + name + "='" + a.value + "'");
+      log(that + ": set data-mkws attribute " + name + "='" + a.value + "'");
     } else if (!ignoreAttrs[a.name]) {
       that.config[a.name] = a.value;
-      log(node + ": set regular attribute " + a.name + "='" + a.value + "'");
+      log(that + ": set regular attribute " + a.name + "='" + a.value + "'");
     }
   }
 
@@ -122,10 +149,10 @@ widget.autosearch = function(widget) {
 // Utility function for all widgets that want to hide in narrow windows
 widget.hideWhenNarrow = function(widget) {
   widget.team.queue("resize-narrow").subscribe(function(n) {
-    widget.jqnode.hide();
+    widget.node.hide();
   });
   widget.team.queue("resize-wide").subscribe(function(n) {
-    widget.jqnode.show();
+    widget.node.show();
   });
 };