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"],
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.
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
-<?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>
--- /dev/null
+.mkwsCredo {
+ font-family: Gill Sans, "Gillius ADF", Gillius, GilliusADF, Verdana, Sans-Serif;
+}
--- /dev/null
+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(''));
+});
--- /dev/null
+.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;
+}
--- /dev/null
+<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>
--- /dev/null
+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 }));
+});
--- /dev/null
+# 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)
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 */
};
-// 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
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();
* 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');
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:
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
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) {
}
- $(document).ready(function() {
+ function init(rootsel) {
+ if (!rootsel) var rootsel = ':root';
var saved_config;
if (typeof mkws_config === 'undefined') {
log("setting empty config");
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 + "'");
}
}
}
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) {
}
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);
});
// raw pp2
runAutoSearches();
}
+ };
+ $(document).ready(function() {
+ var widgetSelector = selectorForAllWidgets();
+ if (widgetSelector && $(widgetSelector).length !== 0) init();
});
})(jQuery);
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);
}
}
*/
function _mkws_jquery_plugin($) {
function debug(string) {
- mkws.log("jquery.pazpar2: " + string);
+ mkws.log("jQuery.pazpar2: " + string);
}
function init_popup(obj) {
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
"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() {
}
function onBytarget(data) {
- log("target");
+ log("bytarget");
queue("targets").publish(data);
}
function widgetNode(type) {
var w = that.widget(type);
- return w ? w.jqnode : undefined;
+ return w ? w.node : undefined;
}
function renderDetails(data, marker) {
var that = this;
this.team.queue("authenticated").subscribe(function(authName) {
- that.jqnode.html(authName);
+ that.node.html(authName);
});
});
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();
mkws.registerWidgetType('ConsoleBuilder', function() {
mkws.promotionFunction('Builder').call(this);
this.callback = function(s) {
- console.log("Generated widget: " + s);
+ console.log("generated widget: " + s);
}
});
text.push("<option value='", id, "'>", name, "</option>");
});
text.push("</select>");
- that.jqnode.html(text.join(''));
+ that.node.html(text.join(''));
});
});
});
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/>");
});
});
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>' +
}
table += '</tbody></table>';
- that.jqnode.html(table);
+ that.node.html(table);
});
});
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);
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();
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");
');return false;">' + value + '</a>';
});
- that.jqnode.html(text);
+ that.node.html(text);
});
});
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();
}
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();
}
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>');
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') + '" />\
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;
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">\
}
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++) {
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++) {
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 = "";
}
}
- this.jqnode.html(data);
+ this.node.html(data);
widget.hideWhenNarrow(this);
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");
+ }
}
});
// 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 = [];
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);
});
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() {
acc.push('</div>');
}
- that.jqnode.html(acc.join(''));
+ that.node.html(acc.join(''));
});
});
var that = {
team: team,
type: type,
- node: node,
- jqnode: $(node),
+ node: $(node),
config: mkws.objectInheritingFrom(team.config())
};
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];
} 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 + "'");
}
}
// 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();
});
};