Template Ranking widget.
[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   if (!this.config.show_switch) return;
8   var that = this;
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     // There is a bug in pz2.js wherein it makes each data object an array but
15     // simply assigns properties to it.
16     // TODO: remove this when PAZ-946 is addressed.
17     var cleandata = [];
18     for (var i = 0; i < data.length; i++) {
19       var cur = {};
20       cur.id = data[i].id;
21       cur.hits = data[i].hits;
22       cur.diagnostic = data[i].diagnostic;
23       cur.records = data[i].records;
24       cur.state = data[i].state;
25       cleandata.push(cur);
26     }
27
28     var template = that.team.loadTemplate(that.config.template || "Targets");
29     that.node.html(template({data: cleandata}));
30   });
31 });
32
33
34 mkws.registerWidgetType('Stat', function() {
35   var that = this;
36   this.team.queue("stat").subscribe(function(data) {
37     var template = that.team.loadTemplate(that.config.template || "Stat");
38     that.node.html(template(data));
39   });
40 });
41
42
43 mkws.registerWidgetType('Pager', function() {
44   var that = this;
45   var M = mkws.M;
46
47   this.team.queue("pager").subscribe(function(data) {
48     var teamName = that.team.name();
49     var output = {};
50     output.first = data.start + 1;
51     output.last = data.start + data.num;
52     output.count = data.merged;
53     output.found = data.total;
54
55     //client indexes pages from 1 but pz2 from 0
56     var onsides = 6;
57     var pages = Math.ceil(that.team.totalRecordCount() / that.team.perpage());
58     var currentPage = that.team.currentPage();
59
60     var firstClkbl = (currentPage - onsides > 0)
61       ? currentPage - onsides
62       : 1;
63     var lastClkbl = firstClkbl + 2*onsides < pages
64       ? firstClkbl + 2*onsides
65       : pages;
66
67     if (firstClkbl > 1) output.morePrev = true;
68     if (lastClkbl < pages) output.moreNext = true;
69
70     if (currentPage > 1) output.prevClick = "mkws.pagerPrev(\'" + teamName + "\');";
71
72     output.pages = [];
73     for(var i = firstClkbl; i <= lastClkbl; i++) {
74       var o = {};
75       o.number = i;
76       if (i !== currentPage) {
77         o.click = "mkws.showPage(\'" + teamName + "\', " + i + ");";
78       }
79       output.pages.push(o);
80     }
81
82     if (pages - currentPage > 0) output.nextClick = "mkws.pagerNext(\'" + teamName + "\')";
83
84     var template = that.team.loadTemplate(that.config.template || "Pager");
85     that.node.html(template(output));
86   });
87 });
88
89
90 mkws.registerWidgetType('Records', function() {
91   var that = this;
92   var team = this.team;
93
94   this.team.queue("records").subscribe(function(data) {
95     for (var i = 0; i < data.hits.length; i++) {
96       var hit = data.hits[i];
97       that.team.queue("record").publish(hit);
98       hit.detailLinkId = team.recordElementId(hit.recid[0]);
99       hit.detailClick = "mkws.showDetails('" + team.name() + "', '" + hit.recid[0] + "');return false;"
100       hit.containerClass = "mkwsSummary mkwsTeam_" + team.name();
101       hit.containerClass += " " + hit.detailLinkId;
102       // ### At some point, we may be able to move the
103       // m_currentRecordId and m_currentRecordData members
104       // from the team object into this widget.
105       if (hit.recid == team.currentRecordId()) {
106         if (team.currentRecordData()) {
107           hit.renderedDetails = team.renderDetails(team.currentRecordData());
108           console.log(hit.renderedDetails); 
109         } 
110       }
111     }
112     var template = team.loadTemplate(that.config.template || "Records");
113     var targs = $.extend({}, {"hits": data.hits}, that.config.template_vars);
114     that.node.html(template(targs));
115   });
116
117   that.autosearch();
118 });
119
120
121 mkws.registerWidgetType('Navi', function() {
122   var that = this;
123   var teamName = this.team.name();
124   var M = mkws.M;
125
126   this.team.queue("navi").subscribe(function() {
127     var filters = that.team.filters();
128     var text = "";
129
130     filters.visitTargets(function(id, name) {
131       if (text) text += " | ";
132       text += M('source') + ': <a class="mkwsRemovable" href="#" onclick="mkws.delimitTarget(\'' + teamName +
133         "', '" + id + "'" + ');return false;">' + name + '</a>';
134     });
135
136     filters.visitFields(function(field, value) {
137       if (text) text += " | ";
138       text += M(field) + ': <a class="mkwsRemovable" href="#" onclick="mkws.delimitQuery(\'' + teamName +
139         "', '" + field + "', '" + value + "'" +
140         ');return false;">' + value + '</a>';
141     });
142
143     that.node.html(text);
144   });
145 });
146
147
148 // It seems this and the Perpage widget doen't need to subscribe to
149 // anything, since they produce events rather than consuming them.
150 //
151 mkws.registerWidgetType('Sort', function() {
152   var that = this;
153
154   this.node.change(function() {
155     that.team.set_sortOrder(that.node.val());
156     if (that.team.submitted()) {
157       that.team.reShow();
158     }
159     return false;
160   });
161 });
162
163
164 mkws.registerWidgetType('Perpage', function() {
165   var that = this;
166
167   this.node.change(function() {
168     that.team.set_perpage(that.node.val());
169     if (that.team.submitted()) {
170       that.team.reShow();
171     }
172     return false;
173   });
174 });
175
176
177 mkws.registerWidgetType('Done', function() {
178   var that = this;
179   this.team.queue("complete").subscribe(function(n) {
180     var template = that.team.loadTemplate(that.config.template || "Done");
181     that.node.html(template({count: n}));
182   });
183 });
184
185
186 mkws.registerWidgetType('Switch', function() {
187   if (!this.config.show_switch) return;
188   var tname = this.team.name();
189   var output = {};
190   output.recordClick = "mkws.switchView(\'" + tname + "\', \'records\')";
191   output.targetClick = "mkws.switchView(\'" + tname + "\', \'targets\')";
192   var template = this.team.loadTemplate(this.config.template || "Switch");
193   this.node.html(template(output));
194   this.hideWhenNarrow();
195 });
196
197
198 mkws.registerWidgetType('Search', function() {
199   var output = {};
200   output.team = this.team.name();
201   output.queryWidth = this.config.query_width;
202   var template = this.team.loadTemplate(this.config.template || "Search");
203   this.node.html(template(output));
204 });
205
206
207 mkws.registerWidgetType('SearchForm', function() {
208   var team = this.team;
209   this.node.submit(function() {
210     var val = team.widget('Query').value();
211     team.newSearch(val);
212     return false;
213   });
214 });
215
216
217 mkws.registerWidgetType('Results', function() {
218   var template = this.team.loadTemplate(this.config.template || "Results");
219   this.node.html(template({team: this.team.name()}));
220   this.autosearch();
221 });
222
223
224 mkws.registerWidgetType('Ranking', function() {
225   var output = {};
226   output.perPage = [];
227   output.sort = [];
228   output.team = this.team.name();
229   output.showSort = this.config.show_sort;
230   output.showPerPage = this.config.show_perpage;
231
232   var order = this.team.sortOrder();
233   this.log("making sort, sortOrder = '" + order + "'");
234   for (var i = 0; i < this.config.sort_options.length; i++) {
235     var cur = {};
236     var opt = this.config.sort_options[i];
237     cur.key = opt[0];
238     cur.label = opt.length == 1 ? opt[0] : opt[1];
239     if (order == cur.key || order == cur.label) cur.selected = true;
240     output.sort.push(cur);
241   }
242
243   var perpage = this.team.perpage();
244   this.log("making perpage, perpage = " + perpage);
245   for(var i = 0; i < this.config.perpage_options.length; i++) {
246     var cur = {};
247     cur.perPage = this.config.perpage_options[i];
248     if (cur.perPage == perpage) cur.selected = true;
249     output.perPage.push(cur);
250   }
251
252   var template = this.team.loadTemplate(this.config.template || "Ranking");
253   console.log(output);
254   this.node.html(template(output));
255 });
256
257
258 mkws.registerWidgetType('Lang', function() {
259   // dynamic URL or static page? /path/foo?query=test
260   /* create locale language menu */
261   if (!this.config.show_lang) return;
262
263   var lang_default = "en";
264   var lang = this.config.lang || lang_default;
265   var list = [];
266
267   /* display a list of configured languages, or all */
268   var lang_options = this.config.lang_options || [];
269   var toBeIncluded = {};
270   for (var i = 0; i < lang_options.length; i++) {
271     toBeIncluded[lang_options[i]] = true;
272   }
273
274   for (var k in mkws.locale_lang) {
275     if (toBeIncluded[k] || lang_options.length == 0)
276       list.push(k);
277   }
278
279   // add english link
280   if (lang_options.length == 0 || toBeIncluded[lang_default])
281     list.push(lang_default);
282
283   this.log("language menu: " + list.join(", "));
284
285   /* the HTML part */
286   var data = "";
287   for (var i = 0; i < list.length; i++) {
288     var l = list[i];
289     if (data)
290       data += ' | ';
291
292     if (lang == l) {
293       data += ' <span>' + l + '</span> ';
294     } else {
295       data += ' <a href="' + lang_url(l) + '">' + l + '</a> '
296     }
297   }
298
299   this.node.html(data);
300   this.hideWhenNarrow();
301
302
303   // set or re-set "lang" URL parameter
304   function lang_url(lang) {
305     var query = location.search;
306     // no query parameters? done
307     if (!query) {
308       return "?lang=" + lang;
309     }
310
311     // parameter does not exist
312     if (!query.match(/[\?&]lang=/)) {
313       return query + "&lang=" + lang;
314     }
315
316     // replace existing parameter
317     query = query.replace(/\?lang=([^&#;]*)/, "?lang=" + lang);
318     query = query.replace(/\&lang=([^&#;]*)/, "&lang=" + lang);
319     return query;
320   }
321 });
322
323
324 mkws.registerWidgetType('MOTD', function() {
325   var container = this.team.widget('MOTDContainer');
326   if (container) {
327     // Move the MOTD from the provided element down into the container
328     this.node.appendTo(container.node);
329   }
330 });
331
332
333 // This widget has no functionality of its own, but its configuration
334 // is copied up into its team, allowing it to affect other widgets in
335 // the team.
336 //
337 mkws.registerWidgetType('Config', function() {
338   var c = this.config;
339   for (var name in c) {
340     if (c.hasOwnProperty(name)) {
341       this.team.config[name] = c[name];
342       this.log(this + " copied property " + name + "='" + c[name] + "' up to team");
343     }
344   }
345 });
346
347
348 mkws.registerWidgetType('Progress', function() {
349   var that = this;
350
351   this.node.hide();
352   this.team.queue("stat").subscribe(function(data) {
353     var s = '<span class="mkwsDone">';
354     for (var i = 0; i < data.clients; i++) {
355       if (i == data.clients - data.activeclients) {
356         s += '</span>';
357         s += '<span class="mkwsWaiting">';
358       }
359       s += '&#x2588;';
360     }
361     s += '</span>';
362     that.node.html(s);
363     that.node.show();
364   });
365 });
366
367
368 // Some elements have mkws* classes that makes them appear as widgets
369 // -- for example, because we want to style them using CSS -- but have
370 // no actual functionality. We register these to prevent ignorable
371 // warnings when they occur.
372
373 mkws.registerWidgetType('Query', function() {});
374 mkws.registerWidgetType('MOTDContainer', function() {});
375 mkws.registerWidgetType('Button', function() {});
376
377