]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/extras/opensearchportal.html
adding sources and a reasonable timeout
[Evergreen.git] / Open-ILS / src / extras / opensearchportal.html
1 <html>
2         <head>
3                 <title>mikers experimental opensearch portal</title>
4                 <style>
5
6 * {
7         font-family: verdana,arial,helvetica,sans-serif;
8 }
9
10 #result_sources a {
11         font-size: 8px;
12         color: grey;
13         text-decoration: none;
14 }
15
16 td {
17         vertical-align: top;
18 }
19
20 .source_input {
21         border: dotted blue 1px;
22 }
23
24 caption {
25         border: solid lightblue 1px;
26 }
27
28 a {
29         color: blue;
30         text-decoration: none;
31 }
32
33 a:hover {
34         color: blue;
35         text-decoration: underline;
36 }
37
38 a:active {
39         color: red;
40         text-decoration: underline;
41 }
42
43 a:visited {
44         color: blue;
45         text-decoration: none;
46 }
47
48 .title_link {
49         font-size: medium;
50         font-weight: bold;
51 }
52
53 .desc_text {
54         font-size: small;
55 }
56
57 .hide {
58         color: lightgray;
59 }
60
61 .col_tab {
62         border-collapse: collapse;
63         border: solid gray 1px;
64 }
65
66 .res_table {
67         border-collapse: collapse;
68         /*width: 100%;*/
69         max-width: 400px;
70         min-width: 300px;
71 }
72
73 .res_tr {
74         border-bottom: 1px dashed darkgrey;
75 }
76
77 .noshow {
78         display: none;
79         visibility: hidden;
80 }
81
82                 </style>
83                 <script>
84
85 var isIE = false;
86
87 function create_requestor () {
88         var req;
89         try { 
90                 req = new ActiveXObject("Msxml2.XMLHTTP");
91                 isIE = true;
92         } catch (e) {
93                 try { 
94                         req = new ActiveXObject("Microsoft.XMLHTTP");
95                         isIE = true;
96                 } catch (E) {
97                         req = false;
98                 }
99         }
100
101         if (!req && typeof XMLHttpRequest!='undefined') {
102                 req = new XMLHttpRequest();
103         }
104         
105         if(!req) {
106                 alert("NEEDS NEWER JAVASCRIPT for XMLHTTPRequest()");
107                 return null;
108         }
109
110         return req;
111 }
112
113 var proxy = 'http://gapines.org/opensearch/?fetch=';
114
115 var images = [];
116 var search_templates = [];
117 var search_urls = {};
118 var rel_scales = {};
119
120 var current_startPage = 1;
121 var current_startIndex = 1;
122 var current_count = 5;
123
124 function opensearch ( term, reset ) {
125
126         if (reset) {
127                 current_startPage = 1;
128                 rel_scales = {};
129         }
130
131         document.getElementById('next_button').className = 'hide';
132
133         if (current_startPage == 1)
134                 document.getElementById('prev_button').className = 'hide';
135         else 
136                 document.getElementById('prev_button').className = '';
137
138         var tot = document.getElementById('total');
139         while (tot.lastChild)
140                         tot.removeChild(tot.lastChild);
141
142         var src = document.getElementById('result_sources');
143         while (src.lastChild)
144                         src.removeChild(src.lastChild);
145
146         document.getElementById('int_res_hide').className = 'noshow';
147         document.getElementById('col_res_hide').className = 'noshow';
148
149         var tab = document.getElementById('int_res');
150         while (tab.lastChild)
151                         tab.removeChild(tab.lastChild);
152
153         tab = document.getElementById('col_res');
154         while (tab.lastChild)
155                         tab.removeChild(tab.lastChild);
156
157         search_count = 0;
158
159         var sources = new Array();
160         var selector = document.getElementsByName('source');
161         for (var i = 0; i < selector.length; i++) {
162                 if (selector[i].checked) {
163                         sources.push(selector[i].value);
164                 }
165         }
166
167         search_templates = [];
168         for (var i in sources) {
169                 create_search( sources[i] );
170         }
171
172         current_startIndex = (current_count * (current_startPage - 1)) + 1; 
173
174         search_urls = [];
175         for (var i in search_templates) {
176                 if (!search_templates[i])
177                         continue;
178
179                 if (!rel_scales[i])
180                         rel_scales[i] = 0;
181
182                 var url = search_templates[i].replace(/\{searchTerms\}/,encodeURIComponent(term));
183                 url = url.replace(/\{startPage\}/,current_startPage);
184                 url = url.replace(/\{startIndex\}/,current_startIndex);
185                 url = url.replace(/\{count\}/,current_count);
186                 url = url.replace(/\{relevanceScale}/,rel_scales[i]);
187                 search_urls[i] = proxy + encodeURIComponent(url);
188
189                 src.innerHTML += '<a href="' + url + '">' + url + '</a><br>';
190         }
191
192         for (var i in search_urls) {
193                 if (!search_templates[i])
194                         continue;
195
196                 perform_search(i);
197         }
198
199         document.getElementById('page_label').innerHTML = current_startPage;
200 }
201
202 function perform_search ( source ) {
203         var req = create_requestor();
204
205         req.onreadystatechange = function () {
206                 if (req.readyState != 4)
207                         return;
208
209                 var xml = req.responseXML;
210
211                 var desc  = getElementTextNS('','description',xml,0);
212                 var xml_link  = getElementTextNS('','link',xml,0);
213
214                 var total  = getElementFloatNS('openSearch','totalResults',xml,0);
215                 var integratible = (getElementNS('openIll','relevance',xml,0) != null);
216                 var scale = getElementFloatNS('openIll','relevanceScale',xml,0);
217
218                 rel_scales[source]  = scale;
219                 
220                 var current_tot = getElementFloatNS('','span',document.getElementById('total').parentNode,0);
221                 var tot = document.getElementById('total');
222
223                 if (!current_tot)
224                         current_tot = 0;
225
226                 if (total > (current_startPage * current_count))
227                         document.getElementById('next_button').className = '';
228
229                 current_tot += total
230                 tot.innerHTML = current_tot;
231
232                 var list = xml.getElementsByTagName('item');
233                 for (var i = 0; i < list.length; i++) {
234
235                         if ( typeof list[i] != 'object')
236                                         continue;
237
238                         var tab;
239                         if (!integratible) {
240                                 tab = document.getElementById('col_res');
241                                 document.getElementById('col_res_hide').className = '';
242                                 var col = document.getElementById(source);
243                                 if (!col) {
244                                         var row = tab.rows[0];
245                                         if (!row)
246                                                 row = tab.insertRow(0);
247
248                                         col = document.createElement('td');
249                                         col.setAttribute('id',source);
250                                         row.appendChild(col);
251
252                                         tab = document.createElement('table');
253                                         tab.setAttribute('valign','top');
254                                         tab.setAttribute('class','col_tab');
255
256                                         var cap = document.createElement('caption');
257                                         tab.appendChild(cap);
258                                         cap.innerHTML = desc + ' -- <a href="' + xml_link + '">XML</a>';
259
260                                         col.appendChild(tab);
261
262                                         var per = parseInt(100 / search_urls.length);
263                                         col.setAttribute('valign','top');
264                                         col.setAttribute('width', + per + '%');
265
266                                 } else {
267                                         tab = col.firstChild;
268                                 }
269                         } else {
270                                 tab = document.getElementById('int_res');
271                                 document.getElementById('int_res_hide').className = '';
272                         }
273
274                         if (!tab.rows.length) {
275                                 add_result_row(tab, 0, list[i], source);
276                         } else {
277                                 for (var j = 0; j < tab.rows.length; j++) {
278                                         if ( typeof tab.rows[j] != 'object')
279                                                 continue;
280
281                                         var rank;
282                                         try {
283                                                 rank = getElementFloatNS('openIll','relevance',list[i],0);
284                                         } catch (e) {
285                                                 alert("error getting float relevance: " + e);
286                                                 rank = 0;
287                                         }
288
289                                         if ( rank < parseFloat(tab.rows[j].firstChild.firstChild.textContent) ) {
290                                                 if ( (j + 1) == tab.rows.length) {
291                                                         add_result_row(tab, tab.rows.length, list[i], source);
292                                                         break
293                                                 }
294                                                 continue;
295                                         }
296                                         add_result_row(tab, j, list[i], source);
297                                         break;
298                                 }
299                         }
300                 }
301         };
302
303         req.open('GET', proxy + encodeURIComponent(search_urls[source]), true);
304         req.send(null);
305 }
306
307
308 // retrieve float of an XML document element, including
309 // elements using namespaces
310 function getElementFloatNS(prefix, local, parentElem, index) {
311     var result = getElementNS(prefix, local, parentElem, index);
312     if (result) {
313         // get text, accounting for possible
314         // whitespace (carriage return) text nodes 
315         if (result.childNodes.length > 1) {
316             return parseFloat(result.childNodes[1].nodeValue);
317         } else {
318             return parseFloat(result.textContent);              
319         }
320     } else {
321         return 0;
322     }
323 }
324
325 function getElementNS(prefix, local, parentElem, index) {
326     var result = "";
327     if (prefix && isIE) {
328         // IE/Windows way of handling namespaces
329         return parentElem.getElementsByTagName(prefix + ":" + local)[index];
330     } else {
331         // the namespace versions of this method 
332         // (getElementsByTagNameNS()) operate
333         // differently in Safari and Mozilla, but both
334         // return value with just local name, provided 
335         // there aren't conflicts with non-namespace element
336         // names
337         return parentElem.getElementsByTagName(local)[index];
338     }
339 }
340
341 // retrieve text of an XML document element, including
342 // elements using namespaces
343 function getElementTextNS(prefix, local, parentElem, index) {
344     var result = getElementNS(prefix, local, parentElem, index);
345     if (result) {
346         // get text, accounting for possible
347         // whitespace (carriage return) text nodes 
348         if (result.childNodes.length > 1) {
349             return result.childNodes[1].nodeValue;
350         } else {
351             return result.firstChild.nodeValue;                 
352         }
353     } else {
354         return '';
355     }
356 }
357
358 function add_result_row (tab, index, xml, source) {
359         var img = images[source];
360         var rank,title,tlink,desc;
361
362         try {
363                 rank = getElementFloatNS('openIll','relevance',xml,0);
364         } catch (e) {
365                 alert("error getting relevance: " + e);
366                 rank = '0';
367         }
368         
369         try {
370                 title = getElementTextNS('','title',xml,0);
371         } catch (e) {
372                 title = '';
373         }
374         
375         try {
376                 tlink = getElementTextNS('','link',xml,0);
377         } catch (e) {
378                 tlink = '';
379         }
380
381         try {
382                 description = getElementTextNS('','description',xml,0);
383         } catch (e) {
384                 description = '';
385         }
386
387         var row = tab.insertRow(index);
388         row.className = 'res_tr';
389         row.innerHTML = '<td style="padding: 4px"><div style="display: none; visibility: hidden;">' + rank +
390                                                  '</div><span class="title_link"><a href="' + tlink + '">' + title +
391                                                  '</a></span><br/><span class="desc_text">' + description + '</span></td>' +
392                                                  '<td><img title="' + parseInt(rank) + '% Relevant" width="32" height="32" src="' + img + '"></td>';
393 }
394
395 function create_search ( s ) {
396         var req = create_requestor();
397
398         req.open('GET',proxy +  encodeURIComponent(s),false);
399         req.send(null);
400
401         try {
402                 var xml = req.responseXML;
403                 search_templates[s] = xml.getElementsByTagName('Url')[0].textContent;
404                 var i =  xml.getElementsByTagName('Image');
405                 if (i.length)
406                         images[s] = i[0].textContent;
407         } catch (e) {
408                 alert('BAD XML!\n\n' + e + '\n\n' + req.responseText);
409                 search_templates[s] = null;
410                 images[s] = null;
411         }
412
413 }
414
415                 </script>
416         </head>
417         <body>
418                 <br/>
419                 <form onsubmit="opensearch(document.getElementById('term').value, true); return false;">
420                 <table>
421                         <tr valign="top">
422                                 <td align="left">Keyword Search: 
423                                         <input type="text" id="term" value="javascript"/>
424                                         <input type="submit" value="Go!"/>
425                                 </td>
426                                 <td align="right">Hits per Source: 
427                                         <select onchange="current_count=this.options[this.selectedIndex].value;">
428                                                 <option value="5" selected>5</option>
429                                                 <option value="10">10</option>
430                                                 <option value="25">25</option>
431                                         </select>
432                                 </td>
433                         </tr>
434                         <tr valign="top">
435                                 <td colspan=2>Sources:  
436                                         <label class="source_input"><input name="source" type="checkbox" value="http://gapines.org/opensearch.xml" checked>GPLS Pines</label>
437                                         <label class="source_input"><input name="source" type="checkbox" value="http://rsinger.library.gatech.edu/opensearch/osdd-gil.xml" checked>GIL Universal Catalog</label>
438                                         <label class="source_input"><input name="source" type="checkbox" value="http://search.athenscounty.lib.oh.us/cgi-bin/koha/opensearchdescription">NPL/Koha</label>
439                                         <label class="source_input"><input name="source" type="checkbox" value="http://www.koders.com/search/KodersSourceCodeSearchDescription.xml">Koders Source Code</label>
440                                         <label class="source_input"><input name="source" type="checkbox" value="http://cnx.rice.edu/content/opensearchdescription">rice.edu Connexions</label>
441                                         <label class="source_input"><input name="source" type="checkbox" value="http://redlightgreen.com/ucwprod/web/opensearchDescription.xml">RedLightGreen</label>
442                                         <label class="source_input"><input name="source" type="checkbox" value="http://www.itpapers.com/itpaperssearchdescription.xml">ITPapers</label>
443                                         <!-- <input name="source" type="checkbox" value="http://www.webdevref.com/blog/opensearchdescription.xml">WebDefRef -->
444                                 </td>
445                         </tr>
446                 </table>
447                 </form>
448
449                 <div>Total results: <span id="total"/></div>
450                 <div>Current page: <span id="page_label"></span> -- 
451                         <button class='hide' id='prev_button' onclick="if (this.className != 'hide') {current_startPage -= 1; opensearch(document.getElementById('term').value);}">Previous Page</button>
452                         ...
453                         <button class='hide' id='next_button' onclick="if (this.className != 'hide') {current_startPage += 1; opensearch(document.getElementById('term').value);}">Next Page</button>
454                 </div>
455                 <hr/>
456                 <br/>
457                 <table id="results">
458                         <tr>
459                                 <td id="int_res_hide" class="noshow">
460                                         <table>
461                                                 <caption>Merged search results</caption>
462                                                 <tr>
463                                                         <td>
464                                                                 <table id='int_res' class="res_table"></table>
465                                                         </td>
466                                                 </tr>
467                                         </table>
468                                 </td>
469                                 <td id='col_res_hide' class="noshow">
470                                         <table>
471                                                 <caption>Unranked search results</caption>
472                                                 <tr>
473                                                         <td>
474                                                                 <table id='col_res' class="res_table"></table>
475                                                         </td>
476                                                 </tr>
477                                         </table>
478                                 </td>
479                         </tr>
480                 </table>
481                 <div id="result_sources"></div>
482                 <br/>
483         </body>
484 </html>