Improved pager.
[pazpar2-moved-to-github.git] / www / demo / search.js
1 /* $Id: search.js,v 1.11 2007-01-10 09:50:57 sondberg Exp $
2  * ---------------------------------------------------
3  * Javascript container
4  */
5
6 var xmlHttp
7 var xinitSession;
8 var xloadTargets;
9 var xsearch;
10 var xshow;
11 var xstat;
12 var xtermlist;
13 var session = false;
14 var targetsloaded = false;
15 var shown;
16 var searchtimer;
17 var showtimer;
18 var termtimer;
19 var stattimer;
20 var session_cells = Array('query', 'startrec', 'action_type');
21 var old_session = session_read();
22 var url_surveillence;
23 var recstoshow = 15;
24 var page_window = 5;  // Number of pages prior to and after the current page
25 var facet_list;
26 var cur_facet = 0;
27
28 function initialize ()
29 {
30     facet_list = get_available_facets();
31     start_session();
32     session_check();
33 }
34
35
36 function GetXmlHttpObject()
37
38     var objXMLHttp=null
39     if (window.XMLHttpRequest)
40       {
41       objXMLHttp=new XMLHttpRequest()
42       }
43     else if (window.ActiveXObject)
44       {
45       objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP")
46       }
47     return objXMLHttp
48
49
50 function SendXmlHttpObject(obj, url, handler)
51 {
52     obj.onreadystatechange=handler;
53     obj.open("GET", url);
54     obj.send(null);
55 }
56
57 function session_started()
58 {
59     if (xinitSession.readyState != 4)
60         return;
61     var xml = xinitSession.responseXML;
62     var sesid = xml.getElementsByTagName("session")[0].childNodes[0].nodeValue;
63     document.getElementById("status").innerHTML = "Live";
64     session = sesid;
65     setTimeout(ping_session, 50000);
66 }
67
68 function start_session()
69 {
70     xinitSession = GetXmlHttpObject();
71     var url="search.pz2?";
72     url += "command=init";
73     xinitSession.onreadystatechange=session_started;
74     xinitSession.open("GET", url);
75     xinitSession.send(null);
76 }
77
78 function ping_session()
79 {
80     if (!session)
81         return;
82     var url = "search.pz2?command=ping&session=" + session;
83     SendXmlHttpObject(xpingSession = GetXmlHttpObject(), url, session_pinged);
84 }
85
86 function session_pinged()
87 {
88     if (xpingSession.readyState != 4)
89         return;
90     var xml = xpingSession.responseXML;
91     var error = xml.getElementsByTagName("error");
92     if (error[0])
93     {
94         var msg = error[0].childNodes[0].nodeValue;
95         alert(msg);
96         location = "?";
97         return;
98     }
99     setTimeout(ping_session, 50000);
100 }
101
102 function targets_loaded()
103 {
104     if (xloadTargets.readyState != 4)
105         return;
106     var xml = xloadTargets.responseXML;
107     var error = xml.getElementsByTagName("error");
108     if (error[0])
109     {
110         var msg = error[0].childNodes[0].nodeValue;
111         alert(msg);
112         return;
113     }
114     document.getElementById("targetstatus").innerHTML = "Targets loaded";
115 }
116
117 function load_targets()
118 {
119     var fn = document.getElementById("targetfilename").value;
120     clearTimeout(termtimer);
121     clearTimeout(searchtimer);
122     clearTimeout(stattimer);
123     clearTimeout(showtimer);
124     document.getElementById("stat").innerHTML = "";
125     if (!fn)
126     {
127         alert("Please enter a target definition file name");
128         return;
129     }
130     var url="search.pz2?" +
131         "command=load" +
132         "&session=" + session +
133         "&name=" + fn;
134     document.getElementById("targetstatus").innerHTML = "Loading targets...";
135     xloadTargets = GetXmlHttpObject();
136     xloadTargets.onreadystatechange=targets_loaded;
137     xloadTargets.open("GET", url);
138     xloadTargets.send(null);
139 }
140
141
142 function update_action (new_action) {
143     document.search.action_type.value = new_action;
144 }
145
146
147 function make_pager (hits, offset, max) {
148     var html = '';
149     var off;
150     var start_offset = offset - page_window * max;
151
152     if (start_offset < 0) {
153         start_offset = 0;
154     }
155
156     for (off = start_offset;
157          off < hits && off < (start_offset + 2 * page_window * max); 
158          off += max) {
159
160         var class = '';
161         
162         if (off < 0)
163             off = 0; 
164             
165         var p = off / max + 1;
166
167         if ((offset >= off) && (offset < (off + max)))
168             class = ' class="select"';
169
170         html += '<a href="#" ' + class +
171                 'onclick="update_offset(' + off + ')">' + p + '</a>\n';
172     }
173
174     return html;
175 }
176
177
178 function update_offset (offset) {
179     document.search.startrec.value = offset;
180     update_action('page');
181     check_search();
182     update_history();
183     return false;
184 }
185
186
187 function show_records()
188 {
189     if (xshow.readyState != 4)
190         return;
191     var i;
192     var xml = xshow.responseXML;
193     var body = document.getElementById("body");
194     var hits = xml.getElementsByTagName("hit");
195     if (!hits[0]) // We should never get here with blocking operations
196     {
197         body.innerHTML = "No records yet";
198         searchtimer = setTimeout(check_search, 250);
199     }
200     else
201     {
202
203         var total = Number(xml.getElementsByTagName('total')[0].childNodes[0].nodeValue);
204         var merged = Number(xml.getElementsByTagName('merged')[0].childNodes[0].nodeValue);
205         var start = Number(xml.getElementsByTagName('start')[0].childNodes[0].nodeValue);
206         var num = Number(xml.getElementsByTagName('num')[0].childNodes[0].nodeValue);
207         var clients = Number(xml.getElementsByTagName("activeclients")[0].childNodes[0].nodeValue);
208         body.innerHTML = '<div class="pages">' +
209                          make_pager(merged, start, recstoshow) +
210                          '</div>';
211                          
212         body.innerHTML += '<div class="results">Records : ' + (start + 1) +
213                           ' to ' + (start + num) + ' of ' + merged +
214                           ' (total hits: ' + total + ')</div><br/><br/>';
215
216 /*
217         if (start + num < merged)
218             body.innerHTML += ' <a href="" ' +
219                 'onclick="document.search.startrec.value=' + (start + recstoshow) +
220                 ";update_action('page')" +
221                 ';check_search(); update_history(); return false;">Next</a>';
222
223         if (start > 0)
224             body.innerHTML += ' <a href="" ' +
225                 'onclick="document.search.startrec.value=' + (start - recstoshow) +
226                 ";update_action('page')" +
227                 ';check_search(); update_history();return false;">Previous</a>';
228
229         body.innerHTML += '<br/>';
230 */
231         body.innerHTML += '<div class="records">';
232
233         for (i = 0; i < hits.length; i++)
234         {
235             var mk = hits[i].getElementsByTagName("md-title");
236             var html = '<a href="#" class="record">';
237             var field = '';
238
239             if (mk[0]) {
240                 field = mk[0].childNodes[0].nodeValue;
241             }
242
243             html += field + '</a>';
244             body.innerHTML += html;
245         }
246
247         body.innerHTML += '</div>';
248         shown++;
249         if (clients > 0)
250         {
251             if (shown < 5)
252                 searchtimer = setTimeout(check_search, 1000);
253             else
254                 searchtimer = setTimeout(check_search, 2000);
255         }
256     }
257     if (!termtimer)
258         termtimer = setTimeout(check_termlist, 500);
259 }
260
261 function check_search()
262 {
263     clearTimeout(searchtimer);
264     var url = "search.pz2?" +
265         "command=show" +
266         "&start=" + document.search.startrec.value +
267         "&num=" + recstoshow +
268         "&session=" + session +
269         "&block=1";
270     xshow = GetXmlHttpObject();
271     xshow.onreadystatechange=show_records;
272     xshow.open("GET", url);
273     xshow.send(null);
274 }
275
276
277 function refine_query (obj) {
278     var query_cell = document.getElementById('query');
279     var term = obj.innerHTML;
280     
281     term = term.replace(/[\(\)]/g, '');
282     if (cur_termlist == 'subject')
283         query_cell.value += ' and su=(' + term + ')';
284     else if (cur_termlist == 'author')
285         query_cell.value += ' and au=(' + term + ')';
286     start_search();
287 }
288
289
290
291 function show_termlist()
292 {
293     if (xtermlist.readyState != 4)
294         return;
295
296     var i;
297     var xml = xtermlist.responseXML;
298     var body = facet_list[cur_facet][1];
299     var hits = xml.getElementsByTagName("term");
300     var clients =
301         Number(xml.getElementsByTagName("activeclients")[0].childNodes[0].nodeValue);
302
303     cur_facet++;
304
305     if (cur_facet >= facet_list.length)
306         cur_facet = 0;
307
308     if (!hits[0])
309     {
310         termtimer = setTimeout(check_termlist, 500);
311     }
312     else
313     {
314         body.innerHTML = '';
315         
316         for (i = 0; i < hits.length; i++)
317         {
318             var namen = hits[i].getElementsByTagName("name");
319             if (namen[0])
320                 body.innerHTML += '<a href="#" onclick="refine_query(this)">' +
321                                   namen[0].childNodes[0].nodeValue +
322                                   '</a>';
323         }
324
325         if (clients > 0)
326             termtimer = setTimeout(check_termlist, 1000);
327     }
328 }
329
330 function check_termlist()
331 {
332     var facet_name = facet_list[cur_facet][0];
333     var url = "search.pz2?" +
334         "command=termlist" +
335         "&session=" + session +
336         "&name=" + facet_name;
337     xtermlist = GetXmlHttpObject();
338     xtermlist.onreadystatechange=show_termlist;
339     xtermlist.open("GET", url);
340     xtermlist.send(null);
341 }
342
343 function show_stat()
344 {
345     if (xstat.readyState != 4)
346         return;
347     var i;
348     var xml = xstat.responseXML;
349     var body = document.getElementById("stat");
350     var nodes = xml.childNodes[0].childNodes;
351     var clients =
352         Number(xml.getElementsByTagName("activeclients")[0].childNodes[0].nodeValue);
353     if (!nodes[0])
354     {
355         stattimer  = setTimeout(check_stat, 500);
356     }
357     else
358     {
359         body.innerHTML = "(";
360         for (i = 0; i < nodes.length; i++)
361         {
362             if (nodes[i].nodeType != 1)
363                 continue;
364             var value = nodes[i].childNodes[0].nodeValue;
365             if (value == 0)
366                 continue;
367             var name = nodes[i].nodeName;
368             body.innerHTML += ' ' + name + '=' + value;
369         }
370         body.innerHTML += ')';
371         if (clients > 0)
372             stattimer = setTimeout(check_stat, 2000);
373     }
374 }
375
376 function check_stat()
377 {
378     var url = "search.pz2?" +
379         "command=stat" +
380         "&session=" + session;
381     xstat = GetXmlHttpObject();
382     xstat.onreadystatechange=show_stat;
383     xstat.open("GET", url);
384     xstat.send(null);
385 }
386
387 function search_started()
388 {
389     if (xsearch.readyState != 4)
390         return;
391     var xml = xsearch.responseXML;
392     var error = xml.getElementsByTagName("error");
393     if (error[0])
394     {
395         var msg = error[0].childNodes[0].nodeValue;
396         alert(msg);
397         return;
398     }
399     check_search();
400     stattimer = setTimeout(check_stat, 1000);
401 }
402
403 function start_search()
404 {
405     clearTimeout(termtimer);
406     termtimer = 0;
407     clearTimeout(searchtimer);
408     searchtimer = 0;
409     clearTimeout(stattimer);
410     stattimer = 0;
411     clearTimeout(showtimer);
412     showtimer = 0;
413     if (!targets_loaded)
414     {
415         alert("Please load targets first");
416         return;
417     }
418     var query = escape(document.getElementById('query').value);
419     var url = "search.pz2?" +
420         "command=search" +
421         "&session=" + session +
422         "&query=" + query;
423     xsearch = GetXmlHttpObject();
424     xsearch.onreadystatechange=search_started;
425     xsearch.open("GET", url);
426     xsearch.send(null);
427 //    document.getElementById("termlist").innerHTML = '';
428     document.getElementById("body").innerHTML = '';
429     update_history();
430     shown = 0;
431     document.search.startrec.value = 0;
432 }
433
434
435 function session_encode ()
436 {
437     var i;
438     var session = '';
439
440     for (i = 0; i < session_cells.length; i++)
441     {
442         var name = session_cells[i];
443         var value = escape(document.getElementById(name).value);
444         session += '&' + name + '=' + value;
445     }
446
447     return session;
448 }
449
450
451 function session_restore (session)
452 {
453     var fields = session.split(/&/);
454     var i;
455
456     for (i = 1; i < fields.length; i++)
457     {
458         var pair = fields[i].split(/=/);
459         var key = pair.shift();
460         var value = pair.join('=');
461         var cell = document.getElementById(key);
462
463         cell.value = value;
464     }
465     
466 }
467
468
469 function session_read ()
470 {
471     var ses = window.location.hash.replace(/^#/, '');
472     return ses;
473 }
474
475
476 function session_store (new_value)
477 {
478     window.location.hash = '#' + new_value;
479 }
480
481
482 function update_history ()
483 {
484     var session = session_encode();
485     session_store(session);
486     old_session = session;
487 }
488
489
490 function session_check ()
491 {
492     var session = session_read();
493     var action = document.search.action_type.value;
494
495     clearInterval(url_surveillence);
496
497     if ( session != unescape(old_session) )
498     {
499         session_restore(session);
500
501         if (action == 'search') {
502             start_search();
503         } else if (action == 'page') {
504             check_search();
505         } else {
506             alert('Unregocnized action_type: ' + action);
507             return;
508         }
509     }
510     
511     url_surveillence = setInterval(session_check, 200);
512 }
513
514
515 function get_available_facets () {
516     var facet_container = document.getElementById('termlists');
517     var facet_cells = facet_container.childNodes;
518     var facets = Array();
519     var i;
520
521     for (i = 0; i < facet_cells.length; i++) {
522         var cell = facet_cells.item(i);
523
524         if (cell.className == 'facet') {
525             var facet_name = cell.id.replace(/^facet_([^_]+)_terms$/, "$1");
526             facets.push(Array(facet_name, cell));
527         }
528     }
529
530     return facets;
531 }
532
533
534 function get_facet_container (obj) {
535     return document.getElementById(obj.id + '_terms');
536 }
537
538
539 function toggle_facet (obj) {
540     var container = get_facet_container(obj);
541
542     if (obj.className == 'selected') {
543         obj.className = 'unselected';
544         container.style.display = 'inline';
545     } else {
546         obj.className = 'selected';
547         container.style.display = 'none';
548     }
549 }