pandoc --standalone --toc -c mkws-doc.css $< | ./tweak-html > $@
chmod ugo-w $@
-# ### In order to compile the manual, which has tables, to PDF,
-# you will need to install the Debian package
-# texlive-latex-recommended
../tools/htdocs/%.pdf: %.markdown
rm -f $@
$(MARKDOWN2PDF) $< -o $@
[uses a local authentication regime](//example.indexdata.com/localauth.html)
and the corresponding
[Apache2 configuration stanza](//example.indexdata.com/apache-config.txt).
-* [A version that uses a jQuery popup](//example.indexdata.com/popup.html).
+* [A version that uses a jQuery popup](//example.indexdata.com/popup.html?q=sushi).
### Non-standard interfaces
MKWS makes requests to Service Proxy or Pazpar2 that perform the actual
searching. Depending on how these are configured and what is available from the
targets you are searching there may be more data available than what is
-presented by the default templates. In this case, you can redefine the
-`Record` template to include more fields in the full-record popup.
+presented by the default templates.
Handlebars offers a convenient log helper that will output the contents of a
variable for you to inspect. This lets you look at exactly what is being
search is made.
-Responsive design
------------------
-
-Metasearching applications may need to appear differently on
-small-screened mobile devices, or change their appearance when
-screen-width changes (as when a small device is rotated). To achieve
-this, MKWS supports responsive design which will move the termlists to
-the bottom on narrow screens and to the sidebar on wide screens.
-
-To turn on this behaviour, set the `responsive_design_width` to the desired
-threshhold width in pixels. For example:
-
- <script type="text/javascript">
- var mkws_config = {
- responsive_design_width: 990
- };
- </script>
-
-If individual result-related widgets are in use in place of the
-all-in-one mkwsResults, then the redesigned application needs to
-specify the locations where the termlists should appear in both
-cases. In this case, wrap the wide-screen `mkwsTermlists` element in a
-`mkwsTermlists-Container-wide` element; and provide an
-`mkwsTermlists-Container-narrow` element in the place where the narrow-screen
-termlists should appear.
-
-
Popup results with jQuery UI
----------------------------
sp_auth_credentials: "mkwstest/mkwstest"
}
</script>
- <link rel="stylesheet" type="text/css" href="//mkws.indexdata.com/mkws.css" />
+ <link rel="stylesheet" type="text/css" href="tools/htdocs/mkws.css" />
<script type="text/javascript" src="tools/htdocs/jquery-1.10.0.min.js"></script>
<script type="text/javascript" src="tools/htdocs/jquery.json-2.4.js"></script>
<script type="text/javascript" src="tools/htdocs/handlebars-v2.0.0.js"></script>
<title>MKWS demo</title>
<script type="text/javascript">
var mkws_config = {
-// pp2_hostname: "x.sp-mkws.indexdata.com",
- };
+ sp_auth_credentials: "mkwstest/mkwstest"
+ }
</script>
<link rel="stylesheet" type="text/css" href="tools/htdocs/mkws.css" />
<script type="text/javascript" src="tools/htdocs/jquery-1.10.0.min.js"></script>
<script type="text/javascript" src="src/mkws-widget-record.js"></script>
<script type="text/javascript" src="src/mkws-widget-reference.js"></script>
<script type="text/javascript" src="src/mkws-widget-builder.js"></script>
- <script type="text/javascript" src="mkws-widget-sru.js"></script>
+ <script type="text/javascript" src="src/mkws-templates.js"></script>
</head>
<body>
- <h1>SRU example: dinosaurs at LoC</h1>
- <div class="mkwsSRU" autosearch="dinosaur" maximumRecords="3" recordSchema="dc">Stand by ...</div>
- <!- Use:
-http://z3950.loc.gov:7090/voyager?version=1.1&operation=searchRetrieve&query=dinosaur&maximumRecords=3&recordSchema=dc
- -->
+ <div class="mkws-auth-name"></div>
+ <div class="mkws-switch"></div>
+ <div class="mkws-lang"></div>
+ <div class="mkws-progress"></div>
+ <div class="mkws-search"></div>
+ <div class="mkws-results"></div>
+ <div class="mkws-targets"></div>
+ <div class="mkws-stat"></div>
+ <div class="mkws-builder"></div>
</body>
</html>
// wrapper to provide local copy of the jQuery object.
(function($) {
var log = mkws.log;
+ var _old2new = { // Maps old-style widget names to new-style
+ 'Authname': 'auth-name',
+ 'ConsoleBuilder': 'console-builder',
+ 'Coverart': 'cover-art',
+ 'GoogleImage': 'google-image',
+ 'MOTD': 'motd',
+ 'MOTDContainer': 'motd-container',
+ 'Perpage': 'per-page',
+ 'SearchForm': 'search-form',
+ };
+ // Annoyingly, there is no built-in way to invert a hash
+ var _new2old = {};
+ for (var key in _old2new) {
+ if(_old2new.hasOwnProperty(key)) {
+ _new2old[_old2new[key]] = key;
+ }
+ }
function handleNodeWithTeam(node, callback) {
// First branch for DOM objects; second branch for jQuery objects
for (var i = 0; i < list.length; i++) {
var cname = list[i];
- if (cname.match(/^mkwsTeam_/)) {
+ if (cname.match(/^mkws-team-/)) {
+ // New-style teamnames of the form mkws-team-xyz
+ teamName = cname.replace(/^mkws-team-/, '');
+ } else if (cname.match(/^mkwsTeam_/)) {
+ // Old-style teamnames of the form mkwsTeam_xyz
teamName = cname.replace(/^mkwsTeam_/, '');
+ } else if (cname.match(/^mkws-/)) {
+ // New-style names of the from mkws-foo-bar
+ type = cname.replace(/^mkws-/, '');
} else if (cname.match(/^mkws/)) {
- type = cname.replace(/^mkws/, '');
+ // Old-style names of the form mkwsFooBar
+ var tmp = cname.replace(/^mkws/, '');
+ type = _old2new[tmp] || tmp.toLowerCase();
}
}
for (var tname in mkws.teams) {
var team = mkws.teams[tname];
team.visitWidgets(function(t, w) {
- var w1 = team.widget(t + "-Container-" + from);
- var w2 = team.widget(t + "-Container-" + to);
+ var w1 = team.widget(t + "-container-" + from);
+ var w2 = team.widget(t + "-container-" + to);
if (w1) {
w1.node.hide();
}
var s = "";
for (var type in mkws.widgetType2function) {
if (s) s += ',';
- s += '.mkws' + type;
- s += ',.mkws' + type + "-Container-wide";
- s += ',.mkws' + type + "-Container-narrow";
+ s += '.mkws-' + type;
+ s += ',.mkws-' + type + "-container-wide";
+ s += ',.mkws-' + type + "-container-narrow";
+ // Annoyingly, we also need to recognise old-style names
+ var oldtype = _new2old[type] || type.charAt(0).toUpperCase() + type.slice(1);
+ s += ',.mkws' + oldtype;
+ s += ',.mkws' + oldtype + "-Container-wide";
+ s += ',.mkws' + oldtype + "-Container-narrow";
}
return s;
}
//"use strict";
// $(document).ready(function () {
-mkws.registerWidgetType('Popup', function() {
+mkws.registerWidgetType('popup', function() {
var $ = mkws.$;
var debug = mkws.log;
debug("init popup window");
- var popup_window = $(this.node); // mkws.registerWidgetType('Popup',....)
+ var popup_window = $(this.node);
// var popup_window = $(".mkwsPopup"); // $(document).ready()
if (!popup_window) {
debug("no popup found, skip...");
// switching view between targets and records
function switchView(view) {
- var targets = widgetNode('Targets');
- var results = widgetNode('Results') || widgetNode('Records');
- var blanket = widgetNode('Blanket');
- var motd = widgetNode('MOTD');
+ var targets = widgetNode('targets');
+ var results = widgetNode('results') || widgetNode('records');
+ var blanket = widgetNode('blanket');
+ var motd = widgetNode('motd');
switch(view) {
case 'targets':
-mkws.registerWidgetType('Authname', function() {
+mkws.registerWidgetType('auth-name', function() {
var that = this;
this.team.queue("authenticated").subscribe(function(authName) {
-mkws.registerWidgetType('Builder', function() {
+mkws.registerWidgetType('builder', function() {
var that = this;
var team = this.team;
});
this.node.append(button);
button.click(function() {
- var query = team.widget('Query').value();
- var sort = team.widget('Sort').value();
- var perpage = team.widget('Perpage').value();
+ var query = team.widget('query').value();
+ var sort = team.widget('sort').value();
+ var perpage = team.widget('per-page').value();
var html = ('<div class="mkwsRecords" ' +
'autosearch="' + query + '" ' +
});
});
-mkws.registerWidgetType('ConsoleBuilder', function() {
- mkws.promotionFunction('Builder').call(this);
+mkws.registerWidgetType('console-builder', function() {
+ mkws.promotionFunction('builder').call(this);
this.callback = function(s) {
console.log("generated widget: " + s);
}
-mkws.registerWidgetType('Categories', function() {
+mkws.registerWidgetType('categories', function() {
var that = this;
if (!mkws.authenticated) {
-mkws.registerWidgetType('Log', function() {
+mkws.registerWidgetType('log', function() {
var that = this;
this.team.queue("log").subscribe(function(teamName, timestamp, message) {
// source files.
-mkws.registerWidgetType('Targets', function() {
+mkws.registerWidgetType('targets', function() {
if (!this.config.show_switch) return;
var that = this;
});
-mkws.registerWidgetType('Stat', function() {
+mkws.registerWidgetType('stat', function() {
var that = this;
this.team.queue("stat").subscribe(function(data) {
var template = that.team.loadTemplate(that.config.template || "Stat");
});
-mkws.registerWidgetType('Pager', function() {
+mkws.registerWidgetType('pager', function() {
var that = this;
var M = mkws.M;
});
});
-mkws.registerWidgetType('Details', function() {
+mkws.registerWidgetType('details', function() {
var that = this;
var recid = that.node.attr("data-mkws-recid");
if (this.team.gotRecords()) {
that.autosearch();
});
-mkws.registerWidgetType('Records', function() {
+mkws.registerWidgetType('records', function() {
var that = this;
var team = this.team;
});
-mkws.registerWidgetType('Navi', function() {
+mkws.registerWidgetType('navi', function() {
var that = this;
var teamName = this.team.name();
// It seems this and the Perpage widget doen't need to subscribe to
// anything, since they produce events rather than consuming them.
//
-mkws.registerWidgetType('Sort', function() {
+mkws.registerWidgetType('sort', function() {
var that = this;
this.node.change(function() {
});
-mkws.registerWidgetType('Perpage', function() {
+mkws.registerWidgetType('per-page', function() {
var that = this;
this.node.change(function() {
});
-mkws.registerWidgetType('Done', function() {
+mkws.registerWidgetType('done', function() {
var that = this;
this.team.queue("complete").subscribe(function(n) {
var template = that.team.loadTemplate(that.config.template || "Done");
});
-mkws.registerWidgetType('Switch', function() {
+mkws.registerWidgetType('switch', function() {
if (!this.config.show_switch) return;
var tname = this.team.name();
var output = {};
});
-mkws.registerWidgetType('Search', function() {
+mkws.registerWidgetType('search', function() {
var output = {};
output.team = this.team.name();
output.queryWidth = this.config.query_width;
});
-mkws.registerWidgetType('SearchForm', function() {
+mkws.registerWidgetType('search-form', function() {
var team = this.team;
this.node.submit(function() {
- var val = team.widget('Query').value();
+ var val = team.widget('query').value();
team.newSearch(val);
return false;
});
});
-mkws.registerWidgetType('Results', function() {
+mkws.registerWidgetType('results', function() {
var template = this.team.loadTemplate(this.config.template || "Results");
this.node.html(template({team: this.team.name()}));
this.autosearch();
});
-mkws.registerWidgetType('Ranking', function() {
+mkws.registerWidgetType('ranking', function() {
var output = {};
output.perPage = [];
output.sort = [];
});
-mkws.registerWidgetType('Lang', function() {
+mkws.registerWidgetType('lang', function() {
// dynamic URL or static page? /path/foo?query=test
/* create locale language menu */
if (!this.config.show_lang) return;
});
-mkws.registerWidgetType('MOTD', function() {
- var container = this.team.widget('MOTDContainer');
+mkws.registerWidgetType('motd', function() {
+ var container = this.team.widget('motd-container');
if (container) {
// Move the MOTD from the provided element down into the container
this.node.appendTo(container.node);
// is copied up into its team, allowing it to affect other widgets in
// the team.
//
-mkws.registerWidgetType('Config', function() {
+mkws.registerWidgetType('config', function() {
var c = this.config;
for (var name in c) {
if (c.hasOwnProperty(name)) {
});
-mkws.registerWidgetType('Progress', function() {
+mkws.registerWidgetType('progress', function() {
var that = this;
this.node.hide();
this.team.queue("stat").subscribe(function(data) {
// no actual functionality. We register these to prevent ignorable
// warnings when they occur.
-mkws.registerWidgetType('Query', function() {});
-mkws.registerWidgetType('MOTDContainer', function() {});
-mkws.registerWidgetType('Button', function() {});
+mkws.registerWidgetType('query', function() {});
+mkws.registerWidgetType('motd-container', function() {});
+mkws.registerWidgetType('button', function() {});
})(mkws.$); // jQuery wrapper
// A widget for one record
-mkws.registerWidgetType('Record', function() {
+mkws.registerWidgetType('record', function() {
if (!this.config.maxrecs) this.config.maxrecs = 1;
var that = this;
var team = this.team;
that.autosearch();
});
-mkws.registerWidgetType('Image', function() {
- mkws.promotionFunction('Records').call(this);
+mkws.registerWidgetType('image', function() {
+ mkws.promotionFunction('records').call(this);
if (!this.config.template) this.config.template = 'Image';
});
-mkws.registerWidgetType('GoogleImage', function() {
- mkws.promotionFunction('Image').call(this);
+mkws.registerWidgetType('google-image', function() {
+ mkws.promotionFunction('image').call(this);
if (!this.config.target) this.config.target = 'Google_Images';
});
-mkws.registerWidgetType('Lolcat', function() {
- mkws.promotionFunction('GoogleImage').call(this);
+mkws.registerWidgetType('lolcat', function() {
+ mkws.promotionFunction('google-image').call(this);
if (!this.config.autosearch) this.config.autosearch = 'kitteh';
});
-mkws.registerWidgetType('Coverart', function() {
- mkws.promotionFunction('Image').call(this);
+mkws.registerWidgetType('cover-art', function() {
+ mkws.promotionFunction('image').call(this);
if (!this.config.target) this.config.target = 'AmazonBooks';
});
-mkws.registerWidgetType('Reference', function() {
- mkws.promotionFunction('Record').call(this);
+mkws.registerWidgetType('reference', function() {
+ mkws.promotionFunction('record').call(this);
if (!this.config.target) this.config.target = 'wikimedia_wikipedia_single_result';
if (!this.config.template) this.config.template = 'Reference';
this.config.template_vars.paragraphs = this.config.paragraphs || 0;
-mkws.registerWidgetType('Termlists', function() {
+mkws.registerWidgetType('termlists', function() {
// Initially hide the termlists; display when we get results
var that = this;
var team = this.team;
});
-mkws.registerWidgetType('Facet', function() {
+mkws.registerWidgetType('facet', function() {
var facetConfig = {
xtargets: [ "Sources", 16, false ],
subject: [ "Subjects", 10, true ],
term - term name
count - count of items matching in the current search for this team
linkdata - attributes to add to the term element including an onclick handler
+ field - for the xtargets facet ONLY, the opaque identifier of the target
}}
<div class="mkwsFacetTitle">{{caption}}</div>
{{!
Records presented as images.
+The non-metadata keys enable an optional link to display an AJAX popup that
+fetches additional record detail.
+
hits:
- containerClass - class attribute for same
+ containerClass - partial class attribute for element containing a record
detailLinkId - id for the element triggering detail display
detailClick - a click event handler for details
renderedDetails - active record details rendered from the Record template
done - number of targets complete
waiting - number of targets waiting
}}
-<span class="mkwsDone">{{#mkws-repeat done}}█{{/mkws-repeat}}</span>
+<span class="mkws-done mkwsDone">{{#mkws-repeat done}}█{{/mkws-repeat}}</span>
{{~#if waiting~}}
-<span class="mkwsWaiting">{{#mkws-repeat waiting}}█{{/mkws-repeat}}</span>
+<span class="mkws-waiting mkwsWaiting">{{#mkws-repeat waiting}}█{{/mkws-repeat}}</span>
{{~/if~}}
Ranking -- widget to select sort ordering and number of records to display
team - team for this widget
-showSort
-showPerPage
+showSort - set if sort control is to be displayed
+showPerPage - set if per-page control is to be displayed
sort
key - machine readable value for this sort option
label - text to display for this sort option
{{!
Full record display.
+
+Top level object is metadata from Service Proxy / Pazpar2
}}
<table>
<tr>
{{!
Records from a search.
+The non-metadata keys enable an optional link to display an AJAX popup that
+fetches additional record detail.
+
hits:
- containerClass - class attribute for same
+ containerClass - partial class attribute for element containing a record
detailLinkId - id for the element triggering detail display
detailClick - a click event handler for details
renderedDetails - active record details rendered from the Record template
team - MKWS team
queryWidth - configured width for search box
}}
-<form name="mkwsSearchForm" class="mkwsSearchForm mkwsTeam_{{team}}" action="">
- <input class="mkwsQuery mkwsTeam_{{team}}" type="text" size="{{queryWidth}}">
- <input class="mkwsButton mkwsTeam_{{team}}" type="submit" value="{{{mkws-translate "Search"}}}">
+<form name="mkws-search-form" class="mkws-search-form mkws-team-{{team}}" action="">
+ <input class="mkws-query mkwsQuery mkws-team-{{team}}" type="text" size="{{queryWidth}}">
+ <input class="mkws-button mkwsButton mkws-team-{{team}}" type="submit" value="{{{mkws-translate "Search"}}}">
</form>
Target detail
data:
- id - target id
- hits - number of hits for this target
- diagnostic -
- records -
- state - target state
+ id - target id, an opaque identifier
+ hits - number of hits for this target, or "Error" if an error has occurred
+ diagnostic - diagnostic code returned by target, if any. May be numeric or human-readable
+ records - number of record retrieved from target
+ state - target state (Client_Idle, Client_Working, Client_Disconnected or Client_Error)
}}
<table>
<thead>
<td>{{hits}}</td>
<td>{{diagnostic}}</td>
<td>{{records}}</td>
- <td>{{hits}}</td>
+ <td>{{state}}</td>
</tr>
{{/each}}
</tbody>
Installation
-------------------------------------
1. install node.js, see http://nodejs.org/
+(and apache2 if you have not already)
# debian7
$ sudo apt-get install npm
+$ sudo apt-get install apache2
# centos6
$ sudo yum install npm
+$ sudo yum install httpd
The nodejs modules are configured in ./package.json
-.mkwsLang,
-.mkwsSwitch,
-.mkwsSearch,
-.mkwsTermlists,
-.mkwsFacet,
-.mkwsRanking,
-.mkwsPager,
-.mkwsNavi,
-.mkwsRecords,
-.mkwsRecord,
-.mkwsTargets,
-.mkwsStat,
-.mkwsMOTD {
+.mkwsLang, .mkws-lang,
+.mkwsSwitch, .mkws-switch,
+.mkwsSearch, .mkws-search,
+.mkwsTermlists, .mkws-termlists,
+.mkwsFacet, .mkws-facet,
+.mkwsRanking, .mkws-ranking,
+.mkwsPager, .mkws-pager,
+.mkwsNavi, .mkws-navi,
+.mkwsRecords, .mkws-records,
+.mkwsRecord, .mkws-record,
+.mkwsTargets, .mkws-targets,
+.mkwsStat, .mkws-stat,
+.mkwsMOTD, .mkws-motd {
font-family: Gill Sans, "Gillius ADF", Gillius, GilliusADF, Verdana, Sans-Serif;
}
-.mkwsLang {
+.mkwsLang, .mkws-lang {
float: left;
padding-left: 1em;
padding-top: 0.4em;
}
-.mkwsLang a {
+.mkwsLang a, .mkws-lang a {
background: #d0e0ff;
padding: 1px 4px;
}
-.mkwsLang span {
+.mkwsLang span, .mkws-lang span {
border: solid 1px #d0e0ff;
padding: 0px 3px;
}
-.mkwsSearch {
+.mkwsSearch, .mkws-search {
float: right;
}
-.mkwsSwitch {
+.mkwsSwitch, .mkws-switch {
float: right;
padding-left: 1em;
padding-top: 0.4em;
}
-.mkwsTargets {
+.mkwsTargets, .mkws-targets {
background-color: #fafafa;
}
-.mkwsStat {
+.mkwsStat, .mkws-stat {
margin-top: 10px;
border-top: 1px solid #156a16;
padding-top: 5px;
font-size: small;
}
-.mkwsStat:before {
+.mkwsStat:before, .mkws-stat:before {
content: "Status info";
font-weight: bold;
}
-.mkwsSwitch a,
-.mkwsLang a,
-.mkwsFacet a,
-.mkwsRanking a,
-.mkwsPager a,
-.mkwsNavi a,
-.mkwsRecords a,
-.mkwsRecord a {
+.mkwsSwitch a, .mkws-switch a,
+.mkwsLang a, .mkws-lang a,
+.mkwsFacet a, .mkws-facet a,
+.mkwsRanking a, .mkws-ranking a,
+.mkwsPager a, .mkws-pager a,
+.mkwsNavi a, .mkws-navi a,
+.mkwsRecords a, .mkws-records a,
+.mkwsRecord a, .mkws-record a {
color: #005701;
text-decoration: none;
}
-.mkwsSwitch a:hover,
-.mkwsLang a:hover,
-.mkwsFacet a:hover,
-.mkwsPager a:hover,
-.mkwsRecords a:hover,
-.mkwsRecord a:hover {
+.mkwsSwitch a:hover, .mkws-switch a:hover,
+.mkwsLang a:hover, .mkws-lang a:hover,
+.mkwsFacet a:hover, .mkws-facet a:hover,
+.mkwsPager a:hover, .mkws-pager a:hover,
+.mkwsRecords a:hover, .mkws-records a:hover,
+.mkwsRecord a:hover, .mkws-record a:hover {
text-decoration: underline;
}
-.mkwsNavi a.mkwsRemovable:hover {
+.mkwsNavi a.mkwsRemovable:hover, .mkws-navi a.mkws-removable:hover {
text-decoration: line-through;
}
-.mkwsSearch input.mkwsButton {
+.mkwsSearch input.mkwsButton, .mkws-search input.mkws-button {
border: 3px outset #132194;
background-color: #132194;
padding: 2px;
cursor: pointer;
}
-.mkwsSearch input.mkwsQuery {
+.mkwsSearch input.mkwsQuery, .mkws-search input.mkws-query {
border: 2px inset #e0f0ff;
padding: 3px;
font-size: 12px;
background: #f0f8ff;
}
-.mkwsTermlistsTitle {
+.mkwsTermlistsTitle, .mkws-termlists-title {
font-size: large;
font-weight: bold;
text-transform: uppercase;
}
-.mkwsTermlists {
+.mkwsTermlists, .mkws-termlists {
background: #d0e0ff;
padding: 0.7em;
font-size: small;
-webkit-border-top-right-radius: 10px;
}
-.mkwsTermlists.active {
+.mkwsTermlists.active, .mkws-termlists.active {
display: block;
}
-.mkwsFacet {
+.mkwsFacet, .mkws-facet {
background: #e0f0ff;
padding: 0.7em;
margin-top: 0.7em;
-webkit-border-top-right-radius: 10px;
}
-.mkwsTerm {
+.mkwsTerm, .mkws-term {
clear: both;
}
-.mkwsTerm span {
+.mkwsTerm span, .mkws-term span {
float: right;
}
-.mkwsFacetTitle {
+.mkwsFacetTitle, .mkws-facet-title {
font-weight: bold;
}
-.mkwsSummary {
+.mkwsSummary, .mkws-summary {
padding: 5px;
}
-.mkwsDetails {
+.mkwsDetails, .mkws-details {
border: 1px solid #404040;
background: #e8e8e8;
color: black;
-webkit-border-top-right-radius: 10px;
}
-.mkwsDetails th {
+.mkwsDetails th, .mkws-details th {
text-align: right;
vertical-align: top;
padding-right: 0.6em;
}
-.mkwsDetails th:after {
+.mkwsDetails th:after, .mkws-details th:after {
content: ":";
}
-.mkwsPager {
+.mkwsPager, .mkws-pager {
background: #e0e0e0;
padding: 0.3em;
}
-.mkwsTargets table thead tr td {
+.mkwsTargets table thead tr td, .mkws-targets table thead tr td {
background-color: #132194;
color: white;
font-weight: bold;
padding: 0.2em 0.5em;
}
-.mkwsTargets table tbody tr:nth-child(odd) {
+.mkwsTargets table tbody tr:nth-child(odd), .mkws-targets table tbody tr:nth-child(odd) {
background-color: #e0f0ff;
}
-.mkwsTargets table tbody tr:nth-child(even) {
+.mkwsTargets table tbody tr:nth-child(even), .mkws-targets table tbody tr:nth-child(even) {
background-color: #d0e0ff;
}
-.mkwsTargets table tbody tr td {
+.mkwsTargets table tbody tr td, .mkws-targets table tbody tr td {
padding: 0.2em 0.5em;
}
-.mkwsCurrentPage {
+.mkwsCurrentPage, .mkws-current-page {
padding: 0.1em 0.5em;
background: #508751;
color: white;
}
-.mkwsProgress {
+.mkwsProgress, .mkws-progress {
border: 1px solid #c0c0c0;
float: left;
margin-left: 2em;
padding: 0 0.3em;
}
-.mkwsProgress .mkwsDone { color: #005701 }
-.mkwsProgress .mkwsWaiting { color: #c0c0c0 }
+.mkwsProgress .mkwsDone, .mkws-progress .mkws-done { color: #005701 }
+.mkwsProgress .mkwsWaiting, .mkws-progress .mkws-waiting { color: #c0c0c0 }
-.mkwsResults table {
+.mkwsResults table, .mkws-results table {
display: inline-table /* only for Firefox! */
}