Use new MKWS-specific class mkwsRemovable instead of old generic crossout.
[mkws-moved-to-github.git] / src / mkws-widget-main.js
1 // Functions follow for promoting the regular widget object into
2 // widgets of specific types. These could be moved into their own
3 // source files.
4
5
6 mkws.registerWidgetType('Targets', function() {
7   var that = this;
8   var M = mkws.M;
9
10   $(this.node).html('No information available yet.');
11   $(this.node).css("display", "none");
12
13   this.team.queue("targets").subscribe(function(data) {
14     var table ='<table><thead><tr>' +
15       '<td>' + M('Target ID') + '</td>' +
16       '<td>' + M('Hits') + '</td>' +
17       '<td>' + M('Diags') + '</td>' +
18       '<td>' + M('Records') + '</td>' +
19       '<td>' + M('State') + '</td>' +
20       '</tr></thead><tbody>';
21
22     for (var i = 0; i < data.length; i++) {
23       table += "<tr><td>" + data[i].id +
24         "</td><td>" + data[i].hits +
25         "</td><td>" + data[i].diagnostic +
26         "</td><td>" + data[i].records +
27         "</td><td>" + data[i].state + "</td></tr>";
28     }
29
30     table += '</tbody></table>';
31     $(that.node).html(table);
32   });
33 });
34
35
36 mkws.registerWidgetType('Stat', function() {
37   var that = this;
38   var M = mkws.M;
39
40   this.team.queue("stat").subscribe(function(data) {
41     if (that.node.length === 0)  alert("huh?!");
42
43     $(that.node).html('<span class="head">' + M('Status info') + '</span>' +
44                       ' -- ' +
45                       '<span class="clients">' + M('Active clients') + ': ' + data.activeclients + '/' + data.clients + '</span>' +
46                       ' -- ' +
47                       '<span class="records">' + M('Retrieved records') + ': ' + data.records + '/' + data.hits + '</span>');
48   });
49 });
50
51
52 mkws.registerWidgetType('Pager', function() {
53   var that = this;
54   var M = mkws.M;
55
56   this.team.queue("pager").subscribe(function(data) {
57     $(that.node).html(drawPager(data))
58
59     function drawPager(data) {
60       var teamName = that.team.name();
61       var s = '<div style="float: right">' + M('Displaying') + ': '
62         + (data.start + 1) + ' ' + M('to') + ' ' + (data.start + data.num) +
63         ' ' + M('of') + ' ' + data.merged + ' (' + M('found') + ': '
64         + data.total + ')</div>';
65
66       //client indexes pages from 1 but pz2 from 0
67       var onsides = 6;
68       var pages = Math.ceil(that.team.totalRecordCount() / that.team.perpage());
69       var currentPage = that.team.currentPage();
70
71       var firstClkbl = (currentPage - onsides > 0)
72         ? currentPage - onsides
73         : 1;
74
75       var lastClkbl = firstClkbl + 2*onsides < pages
76         ? firstClkbl + 2*onsides
77         : pages;
78
79       var prev = '<span class="mkwsPrev">&#60;&#60; ' + M('Prev') + '</span> | ';
80       if (currentPage > 1)
81         prev = '<a href="#" class="mkwsPrev" onclick="mkws.pagerPrev(\'' + teamName + '\');">'
82         +'&#60;&#60; ' + M('Prev') + '</a> | ';
83
84       var middle = '';
85       for(var i = firstClkbl; i <= lastClkbl; i++) {
86         var numLabel = i;
87         if(i == currentPage)
88           numLabel = '<span class="mkwsCurrentPage">' + i + '</span>';
89
90         middle += '<a href="#" onclick="mkws.showPage(\'' + teamName + '\', ' + i + ')"> '
91           + numLabel + ' </a>';
92       }
93
94       var next = ' | <span class="mkwsNext">' + M('Next') + ' &#62;&#62;</span>';
95       if (pages - currentPage > 0)
96         next = ' | <a href="#" class="mkwsNext" onclick="mkws.pagerNext(\'' + teamName + '\')">'
97         + M('Next') + ' &#62;&#62;</a>';
98
99       var predots = '';
100       if (firstClkbl > 1)
101         predots = '...';
102
103       var postdots = '';
104       if (lastClkbl < pages)
105         postdots = '...';
106
107       s += '<div style="float: clear">'
108         + prev + predots + middle + postdots + next + '</div>';
109
110       return s;
111     }
112   });
113 });
114
115
116 mkws.registerWidgetType('Records', function() {
117   var that = this;
118   var team = this.team;
119
120   this.team.queue("records").subscribe(function(data) {
121     var html = [];
122     for (var i = 0; i < data.hits.length; i++) {
123       var hit = data.hits[i];
124       that.team.queue("record").publish(hit);
125       var divId = team.recordElementId(hit.recid[0]);
126       html.push('<div class="record mkwsTeam_' + team.name() + ' ' + divId + '">', renderSummary(hit), '</div>');
127       // ### At some point, we may be able to move the
128       // m_currentRecordId and m_currentRecordData members
129       // from the team object into this widget.
130       if (hit.recid == team.currentRecordId()) {
131         if (team.currentRecordData())
132           html.push(team.renderDetails(team.currentRecordData()));
133       }
134     }
135     $(that.node).html(html.join(''));
136
137     function renderSummary(hit) {
138       var template = team.loadTemplate(that.config.template || "Summary");
139       hit._id = team.recordElementId(hit.recid[0]);
140       hit._onclick = "mkws.showDetails('" + team.name() + "', '" + hit.recid[0] + "');return false;"
141       return template(hit);
142     }
143   });
144
145   widget.autosearch(that);
146 });
147
148
149 mkws.registerWidgetType('Navi', function() {
150   var that = this;
151   var teamName = this.team.name();
152   var M = mkws.M;
153
154   this.team.queue("navi").subscribe(function() {
155     var filters = that.team.filters();
156     var text = "";
157
158     filters.visitTargets(function(id, name) {
159       if (text) text += " | ";
160       text += M('source') + ': <a class="mkwsRemovable" href="#" onclick="mkws.delimitTarget(\'' + teamName +
161         "', '" + id + "'" + ');return false;">' + name + '</a>';
162     });
163
164     filters.visitFields(function(field, value) {
165       if (text) text += " | ";
166       text += M(field) + ': <a class="mkwsRemovable" href="#" onclick="mkws.delimitQuery(\'' + teamName +
167         "', '" + field + "', '" + value + "'" +
168         ');return false;">' + value + '</a>';
169     });
170
171     $(that.node).html(text);
172   });
173 });
174
175
176 // It seems this and the Perpage widget doen't need to subscribe to
177 // anything, since they produce events rather than consuming them.
178 //
179 mkws.registerWidgetType('Sort', function() {
180   var that = this;
181
182   $(this.node).change(function() {
183     that.team.set_sortOrder($(that.node).val());
184     if (that.team.submitted()) {
185       that.team.reShow();
186     }
187     return false;
188   });
189 });
190
191
192 mkws.registerWidgetType('Perpage', function() {
193   var that = this;
194
195   $(this.node).change(function() {
196     that.team.set_perpage($(that.node).val());
197     if (that.team.submitted()) {
198       that.team.reShow();
199     }
200     return false;
201   });
202 });
203
204
205 mkws.registerWidgetType('Done', function() {
206   var that = this;
207
208   this.team.queue("complete").subscribe(function(n) {
209     $(that.node).html("Search complete: found " + n + " records");
210   });
211 });
212
213
214 mkws.registerWidgetType('Switch', function() {
215   var tname = this.team.name();
216   $(this.node).html('\
217 <a href="#" onclick="mkws.switchView(\'' + tname + '\', \'records\')">Records</a><span> \
218 | \
219 </span><a href="#" onclick="mkws.switchView(\'' + tname + '\', \'targets\')">Targets</a>');
220   widget.hideWhenNarrow(this);
221 });
222
223
224 mkws.registerWidgetType('Search', function() {
225   var tname = this.team.name();
226   var M = mkws.M;
227
228   $(this.node).html('\
229 <form name="mkwsSearchForm" class="mkwsSearchForm mkwsTeam_' + tname + '" action="" >\
230   <input class="mkwsQuery mkwsTeam_' + tname + '" type="text" size="' + this.config.query_width + '" />\
231   <input class="mkwsButton mkwsTeam_' + tname + '" type="submit" value="' + M('Search') + '" />\
232 </form>');
233 });
234
235
236 mkws.registerWidgetType('SearchForm', function() {
237   var team = this.team;
238   $(this.node).submit(function() {
239     var val = team.widget('Query').value();
240     team.newSearch(val);
241     return false;
242   });
243 });
244
245
246 mkws.registerWidgetType('Results', function() {
247   var tname = this.team.name();
248
249   $(this.node).html('\
250 <table width="100%" border="0" cellpadding="6" cellspacing="0">\
251   <tr>\
252     <td class="mkwsTermlists-Container-wide mkwsTeam_' + tname + '" width="250" valign="top">\
253       <div class="mkwsTermlists mkwsTeam_' + tname + '"></div>\
254     </td>\
255     <td class="mkwsMOTDContainer mkwsTeam_' + tname + '" valign="top">\
256       <div class="mkwsRanking mkwsTeam_' + tname + '"></div>\
257       <div class="mkwsPager mkwsTeam_' + tname + '"></div>\
258       <div class="mkwsNavi mkwsTeam_' + tname + '"></div>\
259       <div class="mkwsRecords mkwsTeam_' + tname + '"></div>\
260     </td>\
261   </tr>\
262   <tr>\
263     <td colspan="2">\
264       <div class="mkwsTermlists-Container-narrow mkwsTeam_' + tname + '"></div>\
265     </td>\
266   </tr>\
267 </table>');
268
269   widget.autosearch(this);
270 });
271
272
273 mkws.registerWidgetType('Ranking', function() {
274   var tname = this.team.name();
275   var that = this;
276   var M = mkws.M;
277
278   var s = '<form>';
279   if (this.config.show_sort) {
280     s +=  M('Sort by') + ' ' + mkwsHtmlSort() + ' ';
281   }
282   if (this.config.show_perpage) {
283     s += M('and show') + ' ' + mkwsHtmlPerpage() + ' ' + M('per page') + '.';
284   }
285   s += '</form>';
286
287   $(this.node).html(s);
288
289
290   function mkwsHtmlSort() {
291     var order = that.team.sortOrder();
292
293     that.log("HTML sort, sortOrder = '" + order + "'");
294     var sort_html = '<select class="mkwsSort mkwsTeam_' + tname + '">';
295
296     for(var i = 0; i < that.config.sort_options.length; i++) {
297       var opt = that.config.sort_options[i];
298       var key = opt[0];
299       var val = opt.length == 1 ? opt[0] : opt[1];
300
301       sort_html += '<option value="' + key + '"';
302       if (order == key || order == val) {
303         sort_html += ' selected="selected"';
304       }
305       sort_html += '>' + M(val) + '</option>';
306     }
307     sort_html += '</select>';
308
309     return sort_html;
310   }
311
312   function mkwsHtmlPerpage() {
313     var perpage = that.team.perpage();
314
315     that.log("HTML perpage, perpage = " + perpage);
316     var perpage_html = '<select class="mkwsPerpage mkwsTeam_' + tname + '">';
317
318     for(var i = 0; i < that.config.perpage_options.length; i++) {
319       var key = that.config.perpage_options[i];
320
321       perpage_html += '<option value="' + key + '"';
322       if (key == perpage) {
323         perpage_html += ' selected="selected"';
324       }
325       perpage_html += '>' + key + '</option>';
326     }
327     perpage_html += '</select>';
328
329     return perpage_html;
330   }
331 });
332
333
334 mkws.registerWidgetType('Lang', function() {
335   // dynamic URL or static page? /path/foo?query=test
336   /* create locale language menu */
337   if (!this.config.show_lang) return;
338
339   var lang_default = "en";
340   var lang = this.config.lang || lang_default;
341   var list = [];
342
343   /* display a list of configured languages, or all */
344   var lang_options = this.config.lang_options || [];
345   var toBeIncluded = {};
346   for (var i = 0; i < lang_options.length; i++) {
347     toBeIncluded[lang_options[i]] = true;
348   }
349
350   for (var k in mkws.locale_lang) {
351     if (toBeIncluded[k] || lang_options.length == 0)
352       list.push(k);
353   }
354
355   // add english link
356   if (lang_options.length == 0 || toBeIncluded[lang_default])
357     list.push(lang_default);
358
359   this.log("Language menu for: " + list.join(", "));
360
361   /* the HTML part */
362   var data = "";
363   for (var i = 0; i < list.length; i++) {
364     var l = list[i];
365     if (data)
366       data += ' | ';
367
368     if (lang == l) {
369       data += ' <span>' + l + '</span> ';
370     } else {
371       data += ' <a href="' + lang_url(l) + '">' + l + '</a> '
372     }
373   }
374
375   $(this.node).html(data);
376   widget.hideWhenNarrow(this);
377
378
379   // set or re-set "lang" URL parameter
380   function lang_url(lang) {
381     var query = location.search;
382     // no query parameters? done
383     if (!query) {
384       return "?lang=" + lang;
385     }
386
387     // parameter does not exist
388     if (!query.match(/[\?&]lang=/)) {
389       return query + "&lang=" + lang;
390     }
391
392     // replace existing parameter
393     query = query.replace(/\?lang=([^&#;]*)/, "?lang=" + lang);
394     query = query.replace(/\&lang=([^&#;]*)/, "&lang=" + lang);
395     return query;
396   }
397 });
398
399
400 mkws.registerWidgetType('MOTD', function() {
401   var container = this.team.widget('MOTDContainer');
402   if (container) {
403     // Move the MOTD from the provided element down into the container
404     $(this.node).appendTo(container.node);
405   }
406 });
407
408
409 // Some elements have mkws* classes that makes them appear as widgets
410 // -- for example, because we want to style them using CSS -- but have
411 // no actual functionality. We register these to prevent ignorable
412 // warnings when they occur.
413
414 mkws.registerWidgetType('Query', function() {});
415 mkws.registerWidgetType('MOTDContainer', function() {});
416 mkws.registerWidgetType('Button', function() {});
417 mkws.registerWidgetType('Popup', function() {});
418
419