Move actual widgets out of mkws-core.js into their own file mkws-widgets.js
[mkws-moved-to-github.git] / src / mkws-widgets.js
1 // Factory function for widget objects.
2 function widget($, team, type, node) {
3     var that = {
4         team: team,
5         type: type,
6         node: node
7     };
8
9     var M = mkws.M;
10
11     var type2fn = {
12         Targets: promoteTargets,
13         Stat: promoteStat,
14         Termlists: promoteTermlists,
15         Pager: promotePager,
16         Records: promoteRecords,
17         Navi: promoteNavi,
18         Sort: promoteSort,
19         Perpage: promotePerpage
20     };
21
22     var promote = type2fn[type];
23     if (promote) {
24         promote();
25         log("made " + type + " widget(node=" + node + ")");
26     } else {
27         log("made UNENCAPSULATED widget(type=" + type + ", node=" + node + ")");
28     }
29
30     return that;
31
32
33     function log(s) {
34         team.log(s);
35     }
36
37     // Functions follow for promoting the regular widget object into
38     // widgets of specific types. These could be moved outside of the
39     // widget object, or even into their own source files.
40
41     function promoteTargets() {
42         team.queue("targets").subscribe(function(data) {
43             var table ='<table><thead><tr>' +
44                 '<td>' + M('Target ID') + '</td>' +
45                 '<td>' + M('Hits') + '</td>' +
46                 '<td>' + M('Diags') + '</td>' +
47                 '<td>' + M('Records') + '</td>' +
48                 '<td>' + M('State') + '</td>' +
49                 '</tr></thead><tbody>';
50
51             for (var i = 0; i < data.length; i++) {
52                 table += "<tr><td>" + data[i].id +
53                     "</td><td>" + data[i].hits +
54                     "</td><td>" + data[i].diagnostic +
55                     "</td><td>" + data[i].records +
56                     "</td><td>" + data[i].state + "</td></tr>";
57             }
58             
59             table += '</tbody></table>';
60             var subnode = $(node).children('.mkwsBytarget');
61             subnode.html(table);
62         });
63     }
64
65
66     function promoteStat() {
67         team.queue("stat").subscribe(function(data) {
68             if (node.length === 0)  alert("huh?!");
69
70             $(node).html('<span class="head">' + M('Status info') + '</span>' +
71                 ' -- ' +
72                 '<span class="clients">' + M('Active clients') + ': ' + data.activeclients + '/' + data.clients + '</span>' +
73                 ' -- ' +
74                 '<span class="records">' + M('Retrieved records') + ': ' + data.records + '/' + data.hits + '</span>');
75         });
76     }
77
78
79     function promoteTermlists() {
80         team.queue("termlists").subscribe(function(data) {
81             if (!node) {
82                 alert("termlists event when there are no termlists");
83                 return;
84             }
85
86             // no facets: this should never happen
87             if (!mkws_config.facets || mkws_config.facets.length == 0) {
88                 alert("onTerm called even though we have no facets: " + $.toJSON(data));
89                 $(node).hide();
90                 return;
91             }
92
93             // display if we first got results
94             $(node).show();
95
96             var acc = [];
97             acc.push('<div class="title">' + M('Termlists') + '</div>');
98             var facets = mkws_config.facets;
99
100             for (var i = 0; i < facets.length; i++) {
101                 if (facets[i] == "xtargets") {
102                     addSingleFacet(acc, "Sources",  data.xtargets, 16, null);
103                 } else if (facets[i] == "subject") {
104                     addSingleFacet(acc, "Subjects", data.subject,  10, "subject");
105                 } else if (facets[i] == "author") {
106                     addSingleFacet(acc, "Authors",  data.author,   10, "author");
107                 } else {
108                     alert("bad facet configuration: '" + facets[i] + "'");
109                 }
110             }
111
112             $(node).html(acc.join(''));
113
114             function addSingleFacet(acc, caption, data, max, pzIndex) {
115                 acc.push('<div class="facet mkwsFacet' + caption + ' mkwsTeam_' + team.name() + '">');
116                 acc.push('<div class="termtitle">' + M(caption) + '</div>');
117                 for (var i = 0; i < data.length && i < max; i++) {
118                     acc.push('<div class="term">');
119                     acc.push('<a href="#" ');
120                     var action = '';
121                     if (!pzIndex) {
122                         // Special case: target selection
123                         acc.push('target_id='+data[i].id+' ');
124                         if (!team.targetFiltered(data[i].id)) {
125                             action = 'mkws.limitTarget(\'' + team.name() + '\', this.getAttribute(\'target_id\'),this.firstChild.nodeValue)';
126                         }
127                     } else {
128                         action = 'mkws.limitQuery(\'' + team.name() + '\', \'' + pzIndex + '\', this.firstChild.nodeValue)';
129                     }
130                     acc.push('onclick="' + action + ';return false;">' + data[i].name + '</a>'
131                              + ' <span>' + data[i].freq + '</span>');
132                     acc.push('</div>');
133                 }
134                 acc.push('</div>');
135             }
136         });
137     }
138
139
140     function promotePager() {
141         team.queue("pager").subscribe(function(data) {
142             $(node).html(drawPager(data))
143
144             function drawPager(data) {
145                 var s = '<div style="float: right">' + M('Displaying') + ': '
146                     + (data.start + 1) + ' ' + M('to') + ' ' + (data.start + data.num) +
147                     ' ' + M('of') + ' ' + data.merged + ' (' + M('found') + ': '
148                     + data.total + ')</div>';
149
150                 //client indexes pages from 1 but pz2 from 0
151                 var onsides = 6;
152                 var pages = Math.ceil(team.totalRecordCount() / team.perpage());
153                 var currentPage = team.currentPage();
154
155                 var firstClkbl = (currentPage - onsides > 0)
156                     ? currentPage - onsides
157                     : 1;
158
159                 var lastClkbl = firstClkbl + 2*onsides < pages
160                     ? firstClkbl + 2*onsides
161                     : pages;
162
163                 var prev = '<span class="mkwsPrev">&#60;&#60; ' + M('Prev') + '</span><b> | </b>';
164                 if (currentPage > 1)
165                     prev = '<a href="#" class="mkwsPrev" onclick="mkws.pagerPrev(\'' + team.name() + '\');">'
166                     +'&#60;&#60; ' + M('Prev') + '</a><b> | </b>';
167
168                 var middle = '';
169                 for(var i = firstClkbl; i <= lastClkbl; i++) {
170                     var numLabel = i;
171                     if(i == currentPage)
172                         numLabel = '<b>' + i + '</b>';
173
174                     middle += '<a href="#" onclick="mkws.showPage(\'' + team.name() + '\', ' + i + ')"> '
175                         + numLabel + ' </a>';
176                 }
177
178                 var next = '<b> | </b><span class="mkwsNext">' + M('Next') + ' &#62;&#62;</span>';
179                 if (pages - currentPage > 0)
180                     next = '<b> | </b><a href="#" class="mkwsNext" onclick="mkws.pagerNext(\'' + team.name() + '\')">'
181                     + M('Next') + ' &#62;&#62;</a>';
182
183                 var predots = '';
184                 if (firstClkbl > 1)
185                     predots = '...';
186
187                 var postdots = '';
188                 if (lastClkbl < pages)
189                     postdots = '...';
190
191                 s += '<div style="float: clear">'
192                     + prev + predots + middle + postdots + next + '</div>';
193
194                 return s;
195             }
196         });
197     }                        
198
199
200     function promoteRecords() {
201         team.queue("records").subscribe(function(data) {
202             var html = [];
203             for (var i = 0; i < data.hits.length; i++) {
204                 var hit = data.hits[i];
205                 var divId = team.recordElementId(hit.recid[0]);
206                 html.push('<div class="record mkwsTeam_' + team.name() + ' ' + divId + '">', renderSummary(hit), '</div>');
207                 // ### At some point, we may be able to move the
208                 // m_currentRecordId and m_currentRecordData members
209                 // from the team object into this widget.
210                 if (hit.recid == team.currentRecordId()) {
211                     if (team.currentRecordData())
212                         html.push(team.renderDetails(team.currentRecordData()));
213                 }
214             }
215             $(node).html(html.join(''));
216
217             function renderSummary(hit)
218             {
219                 var template = team.loadTemplate("Summary");
220                 hit._id = team.recordElementId(hit.recid[0]);
221                 hit._onclick = "mkws.showDetails('" + team.name() + "', '" + hit.recid[0] + "');return false;"
222                 return template(hit);
223             }
224         });
225     }
226
227
228     function promoteNavi() {
229         team.queue("navi").subscribe(function() {
230             var filters = team.filters();
231             var text = "";
232
233             for (var i in filters) {
234                 if (text) {
235                     text += " | ";
236                 }
237                 var filter = filters[i];
238                 if (filter.id) {
239                     text += M('source') + ': <a class="crossout" href="#" onclick="mkws.delimitTarget(\'' + team.name() +
240                         "', '" + filter.id + "'" + ');return false;">' + filter.name + '</a>';
241                 } else {
242                     text += M(filter.field) + ': <a class="crossout" href="#" onclick="mkws.delimitQuery(\'' + team.name() +
243                         "', '" + filter.field + "', '" + filter.value + "'" +
244                         ');return false;">' + filter.value + '</a>';
245                 }
246             }
247
248             $(node).html(text);
249         });
250     }
251
252
253     function promoteSort() {
254         // It seems this and the Perpage widget doen't need to
255         // subscribe to anything, since they produce events rather
256         // than consuming them.
257         $(node).change(function () {
258             team.set_sortOrder($(node).val());
259             if (team.submitted()) {
260                 team.resetPage();
261                 team.reShow();
262             }
263             return false;
264         });
265     }
266
267
268     function promotePerpage() {
269         $(node).change(function() {
270             team.set_perpage($(node).val());
271             if (team.submitted()) {
272                 team.resetPage();
273                 team.reShow();
274             }
275             return false;
276         });
277     }
278 }