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