]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/opac/skin/default/js/result_common.js
made search term escaping actuall escape all instances - also escapging \ chars now
[Evergreen.git] / Open-ILS / web / opac / skin / default / js / result_common.js
1
2 var recordsHandled = 0;
3 var recordsCache = [];
4 var lowHitCount = 4;
5
6 var resultFetchAllRecords = false;
7
8 /* set up the event handlers */
9 if( findCurrentPage() == MRESULT || findCurrentPage() == RRESULT ) {
10         G.evt.result.hitCountReceived.push(resultSetHitInfo);
11         G.evt.result.recordReceived.push(resultDisplayRecord, resultAddCopyCounts);
12         G.evt.result.copyCountsReceived.push(resultDisplayCopyCounts);
13         G.evt.result.allRecordsReceived.push(resultBuildCaches, resultDrawSubjects, resultDrawAuthors, resultDrawSeries);
14         attachEvt('result','lowHits',resultLowHits);
15         attachEvt('result','zeroHits',resultZeroHits);
16         attachEvt( "common", "locationUpdated", resultSBSubmit );
17         /* do this after we have ID's so the rank for mr pages will be correct */
18         attachEvt("result", "preCollectRecords", resultPaginate);
19 }
20
21 function resultSBSubmit(){searchBarSubmit();}
22
23 /* returns the last 'index' postion ocurring in this page */
24 function resultFinalPageIndex() {
25         if(getHitCount() < (getOffset() + getDisplayCount())) 
26                 return getHitCount() - 1;
27         return getOffset() + getDisplayCount() - 1;
28 }
29
30
31
32
33 /* generic search method */
34 function resultCollectSearchIds( type, method, handler ) {
35
36         var sort                = (getSort() == SORT_TYPE_REL) ? null : getSort(); 
37         var sortdir = (sort) ? ((getSortDir()) ? getSortDir() : SORT_DIR_ASC) : null;
38
39         var item_type;
40         var item_form;
41         var args = {};
42
43         if( type ) {
44                 args.searches = {};
45                 args.searches[getStype()] = {};
46                 var term = getTerm();
47                 if( term ) {
48                         term = term.replace(/'/g,' ');
49                         term = term.replace(/\\/g,' ');
50                         args.searches[getStype()].term = term;
51                 }
52
53                 var form = parseForm(getForm());
54                 item_type = form.item_type;
55                 item_form = form.item_form;
56
57         } else {
58                 args.searches = JSON2js(getSearches());
59                 item_type = (getItemType()) ? getItemType().split(/,/) : null;
60                 item_form = (getItemForm()) ? getItemForm().split(/,/) : null;
61         }
62
63         var limit = (resultFetchAllRecords) ? 1000 : getDisplayCount();
64
65         if( getOffset() > 0 ) {
66                 if( getHitCount() > 0 && (getOffset() + getDisplayCount()) > getHitCount() ) 
67                         limit = getHitCount() - getOffset();
68         }
69
70         args.org_unit = getLocation();
71         args.depth    = getDepth();
72         args.limit    = limit;
73         args.offset   = getOffset();
74         args.visiblity_limit = 3000;
75
76         if(sort) args.sort = sort;
77         if(sortdir) args.sort_dir = sortdir;
78         if(item_type) args.item_type    = item_type;
79         if(item_form) args.item_form    = item_form;
80
81
82         if(getAudience()) args.audience  = getAudience().split(/,/);
83         if(getLitForm()) args.lit_form  = getLitForm().split(/,/);
84         if(getLanguage()) args.language = getLanguage().split(/,/);
85
86         //alert(js2JSON(args));
87
88         _debug('SEARCH: \n' + js2JSON(args) + '\n\n');
89         var req = new Request(method, args, 1);
90         req.callback(handler);
91         req.send();
92 }
93
94
95
96
97
98 /* set the search result info, number of hits, which results we're 
99         displaying, links to the next/prev pages, etc. */
100 function resultSetHitInfo() { 
101
102
103         /* tell the user where the results are coming from */
104         var baseorg = findOrgUnit(getLocation());
105         var depth = getDepth();
106         var mydepth = findOrgDepth(baseorg);
107         if( findOrgDepth(baseorg) != depth ) {
108                 var tmporg = baseorg;
109                 while( mydepth > depth ) {
110                         mydepth--;
111                         tmporg = findOrgUnit(tmporg.parent_ou());
112                 }
113                 unHideMe($('including_results_for'));
114                 $('including_results_location').appendChild(text(tmporg.name()));
115         }
116
117
118         try{searchTimer.stop()}catch(e){}
119
120         //if( findCurrentPage() == MRESULT ) {
121         if( findCurrentPage() == MRESULT || 
122
123                 (findCurrentPage() == RRESULT &&
124                         (
125                                 getRtype() == RTYPE_TITLE ||
126                                 getRtype() == RTYPE_AUTHOR ||
127                                 getRtype() == RTYPE_SUBJECT ||
128                                 getRtype() == RTYPE_SERIES ||
129                                 getRtype() == RTYPE_KEYWORD 
130                         )
131
132                 ) ) {
133
134                 if(getHitCount() <= lowHitCount && getTerm())
135                         runEvt('result', 'lowHits');
136         }
137
138         if(getHitCount() == 0) {
139                 runEvt('result', 'zeroHits');
140                 return;
141         }
142
143
144         var pages = getHitCount() / getDisplayCount();
145         if(pages % 1) pages = parseInt(pages) + 1;
146
147         
148
149         var cpage = (getOffset()/getDisplayCount()) + 1;
150
151         G.ui.result.current_page.appendChild(text(cpage));
152         G.ui.result.num_pages.appendChild(text(pages + ")")); /* the ) is dumb */
153
154         /* set the offsets */
155         var offsetEnd = getDisplayCount() + getOffset();  
156         if( getDisplayCount() > (getHitCount() - getOffset()))  
157                 offsetEnd = getHitCount();
158
159         G.ui.result.offset_end.appendChild(text(offsetEnd));
160         G.ui.result.offset_start.appendChild(text(getOffset() + 1));
161
162         G.ui.result.result_count.appendChild(text(getHitCount()));
163         unHideMe(G.ui.result.info);
164 }
165
166 function resultLowHits() {
167         showCanvas();
168         unHideMe($('result_low_hits'));
169         if(getHitCount() > 0)
170                 unHideMe($('result_low_hits_msg'));
171
172         var sreq = new Request(CHECK_SPELL, getTerm());
173         sreq.callback(resultSuggestSpelling);
174         sreq.send();
175
176         var words = getTerm().split(' ');
177         var word;
178         while( word = words.shift() ) {
179                 var areq = new Request(FETCH_CROSSREF, getStype(), getTerm() );
180                 areq.callback(resultLowHitXRef);
181                 areq.send();
182         }
183
184         if( !(getForm() == null || getForm() == 'all' || getForm() == "") ) {
185                 var a = {};
186                 a[PARAM_FORM] = "all";
187                 $('low_hits_remove_format_link').setAttribute('href',buildOPACLink(a));
188                 unHideMe($('low_hits_remove_format'));
189         }
190
191         resultSuggestSearchClass();
192
193         if(getTerm()) resultExpandSearch(); /* advanced search */
194 }
195
196 var lowHitsXRefLink;
197 var lowHitsXRefLinkParent;
198 function resultLowHitXRef(r) {
199         if(!lowHitsXRefLink){
200                 lowHitsXRefLinkParent = $('low_hits_xref_link').parentNode;
201                 lowHitsXRefLink = lowHitsXRefLinkParent.removeChild($('low_hits_xref_link'));
202         }
203         var res = r.getResultObject();
204         var arr = res.from;
205         arr.concat(res.also);
206         if(arr && arr.length > 0) {
207                 unHideMe($('low_hits_cross_ref'));
208                 var word;
209                 var c = 0;
210                 while( word = arr.shift() ) {
211                         if(c++ > 20) break;
212                         var a = {};
213                         a[PARAM_TERM] = word;
214                         var template = lowHitsXRefLink.cloneNode(true);
215                         template.setAttribute('href',buildOPACLink(a));
216                         template.appendChild(text(word));
217                         lowHitsXRefLinkParent.appendChild(template);
218                         lowHitsXRefLinkParent.appendChild(text(' '));
219                 }
220         }
221 }
222
223 function resultZeroHits() {
224         showCanvas();
225         unHideMe($('result_low_hits'));
226         unHideMe($('result_zero_hits_msg'));
227         //if(getTerm()) resultExpandSearch(); /* advanced search */
228 }
229
230 function resultExpandSearch() {
231         var top = findOrgDepth(globalOrgTree);
232         if(getDepth() == top) return;
233         unHideMe($('low_hits_expand_range'));
234         var par = $('low_hits_expand_link').parentNode;
235         var template = par.removeChild($('low_hits_expand_link'));
236
237         var bottom = getDepth();
238         while( top < bottom ) {
239                 var a = {};
240                 a[PARAM_DEPTH] = top;
241                 var temp = template.cloneNode(true);
242                 temp.appendChild(text(findOrgTypeFromDepth(top).opac_label()))
243                 temp.setAttribute('href',buildOPACLink(a));
244                 par.appendChild(temp);
245                 top++;
246         }
247 }
248
249 function resultSuggestSearchClass() {
250         var stype = getStype();
251         if(stype == STYPE_KEYWORD) return;
252         var a = {}; var ref;
253         unHideMe($('low_hits_search_type'));
254         if(stype != STYPE_TITLE) {
255                 ref = $('low_hits_title_search');
256                 unHideMe(ref);
257                 a[PARAM_STYPE] = STYPE_TITLE;
258                 ref.setAttribute('href',buildOPACLink(a));
259         }
260         if(stype != STYPE_AUTHOR) {
261                 ref = $('low_hits_author_search');
262                 unHideMe(ref);
263                 a[PARAM_STYPE] = STYPE_AUTHOR;
264                 ref.setAttribute('href',buildOPACLink(a));
265         }
266         if(stype != STYPE_SUBJECT) {
267                 ref = $('low_hits_subject_search');
268                 unHideMe(ref);
269                 a[PARAM_STYPE] = STYPE_SUBJECT;
270                 ref.setAttribute('href',buildOPACLink(a));
271         }
272         if(stype != STYPE_KEYWORD) {
273                 ref = $('low_hits_keyword_search');
274                 unHideMe(ref);
275                 a[PARAM_STYPE] = STYPE_KEYWORD;
276                 ref.setAttribute('href',buildOPACLink(a));
277         }
278         if(stype != STYPE_SERIES) {
279                 ref = $('low_hits_series_search');
280                 unHideMe(ref);
281                 a[PARAM_STYPE] = STYPE_SERIES;
282                 ref.setAttribute('href',buildOPACLink(a));
283         }
284 }
285
286 function resultSuggestSpelling(r) {
287         var res = r.getResultObject();
288         var phrase = getTerm();
289         var words = phrase.split(/ /);
290
291         var newterm = "";
292
293         for( var w = 0; w < words.length; w++ ) {
294                 var word = words[w];
295                 var blob = grep(res, function(i){return (i.word == word);});
296                 if( blob ) blob = blob[0];
297                 else continue;
298                 if( blob.word == word ) {
299                         if( blob.suggestions && blob.suggestions[0] ) {
300                                 newterm += " " + blob.suggestions[0];
301                                 unHideMe($('did_you_mean'));
302                         } else {
303                                 newterm += " " + word;
304                         }
305                 }
306         }
307
308         var arg = {};
309         arg[PARAM_TERM] = newterm;
310         $('spell_check_link').setAttribute('href', buildOPACLink(arg));
311         $('spell_check_link').appendChild(text(newterm));
312 }
313
314
315 function resultPaginate() {
316         var o = getOffset();
317
318         if( !(  ((o) + getDisplayCount()) >= getHitCount()) ) {
319
320                 var args = {};
321                 args[PARAM_OFFSET]      = o + getDisplayCount();
322                 args[PARAM_SORT]                = SORT;
323                 args[PARAM_SORT_DIR] = SORT_DIR;
324                 args[PARAM_RLIST]               = new CGI().param(PARAM_RLIST);
325
326                 G.ui.result.next_link.setAttribute("href", buildOPACLink(args)); 
327                 addCSSClass(G.ui.result.next_link, config.css.result.nav_active);
328
329                 args[PARAM_OFFSET] = getHitCount() - (getHitCount() % getDisplayCount());
330
331                 /* when hit count is divisible by display count, we have to adjust */
332                 if( getHitCount() % getDisplayCount() == 0 ) 
333                         args[PARAM_OFFSET] -= getDisplayCount();
334
335                 G.ui.result.end_link.setAttribute("href", buildOPACLink(args)); 
336                 addCSSClass(G.ui.result.end_link, config.css.result.nav_active);
337         }
338
339         if( o > 0 ) {
340
341                 var args = {};
342                 args[PARAM_SORT]                = SORT;
343                 args[PARAM_SORT_DIR] = SORT_DIR;
344                 args[PARAM_RLIST]               = new CGI().param(PARAM_RLIST);
345
346                 args[PARAM_OFFSET] = o - getDisplayCount();
347                 G.ui.result.prev_link.setAttribute( "href", buildOPACLink(args)); 
348                 addCSSClass(G.ui.result.prev_link, config.css.result.nav_active);
349
350                 args[PARAM_OFFSET] = 0;
351                 G.ui.result.home_link.setAttribute( "href", buildOPACLink(args)); 
352                 addCSSClass(G.ui.result.home_link, config.css.result.nav_active);
353         }
354
355         if(getDisplayCount() < getHitCount())
356                 unHideMe($('start_end_links_span'));
357
358         showCanvas();
359         try{searchTimer.stop()}catch(e){}
360 }
361
362 function buildunAPISpan (span, type, id) {
363         var cgi = new CGI();
364         var d = new Date();
365
366         addCSSClass(span,'unapi-id');
367
368         span.setAttribute(
369                 'title',
370                 'tag:' + cgi.server_name + ',' +
371                         d.getFullYear() +
372                         ':' + type + '/' + id
373         );
374 }
375
376 /* display the record info in the record display table 'pos' is the 
377                 zero based position the record should have in the display table */
378 function resultDisplayRecord(rec, pos, is_mr) {
379
380         if(rec == null) rec = new mvr(); /* so the page won't die if there was an error */
381         recordsHandled++;
382         recordsCache.push(rec);
383
384         var r = table.rows[pos + 1];
385
386         
387         try {
388                 var rank = parseFloat(ranks[pos + getOffset()]);
389                 rank            = parseInt( rank * 100 );
390                 var relspan = $n(r, "relevancy_span");
391                 relspan.appendChild(text(rank));
392                 unHideMe(relspan.parentNode);
393         } catch(e){ }
394
395         var pic = $n(r, config.names.result.item_jacket);
396         pic.setAttribute("src", buildISBNSrc(cleanISBN(rec.isbn())));
397
398         var title_link = $n(r, config.names.result.item_title);
399         var author_link = $n(r, config.names.result.item_author);
400
401         if( is_mr )  {
402                 var onlyrec = onlyrecord[ getOffset() + pos ];
403                 if(onlyrec) {
404                         buildunAPISpan($n(r,'unapi'), 'biblio-record_entry', onlyrec);
405
406                         var args = {};
407                         args.page = RDETAIL;
408                         args[PARAM_OFFSET] = 0;
409                         args[PARAM_RID] = onlyrec;
410                         args[PARAM_MRID] = rec.doc_id();
411                         pic.parentNode.setAttribute("href", buildOPACLink(args));
412                         title_link.setAttribute("href", buildOPACLink(args));
413                         title_link.appendChild(text(normalize(truncate(rec.title(), 65))));
414                         
415                 } else {
416                         buildunAPISpan($n(r,'unapi'), 'metabib-metarecord', rec.doc_id());
417
418                         buildTitleLink(rec, title_link); 
419                         var args = {};
420                         args.page = RRESULT;
421                         args[PARAM_OFFSET] = 0;
422                         args[PARAM_MRID] = rec.doc_id();
423                         pic.parentNode.setAttribute("href", buildOPACLink(args));
424                 }
425
426         } else {
427                 buildunAPISpan($n(r,'unapi'), 'biblio-record_entry', rec.doc_id());
428
429                 buildTitleDetailLink(rec, title_link); 
430                 var args = {};
431                 args.page = RDETAIL;
432                 args[PARAM_OFFSET] = 0;
433                 args[PARAM_RID] = rec.doc_id();
434                 pic.parentNode.setAttribute("href", buildOPACLink(args));
435
436                 unHideMe($n(r,'place_hold_span'));
437                 $n(r,'place_hold_link').setAttribute(
438                         'href','javascript:holdsDrawEditor({record:"'+rec.doc_id()+'",type:"T"});');
439         }
440
441         buildSearchLink(STYPE_AUTHOR, rec.author(), author_link);
442
443         if(! is_mr ) {
444         
445                 if(!isNull(rec.edition()))      {
446                         unHideMe( $n(r, "result_table_extra_span"));
447                         $n(r, "result_table_edition_span").appendChild( text( rec.edition()) );
448                 }
449                 if(!isNull(rec.pubdate())) {
450                         unHideMe( $n(r, "result_table_extra_span"));
451                         unHideMe($n(r, "result_table_pub_span"));
452                         $n(r, "result_table_pub_span").appendChild( text( rec.pubdate() ));
453                 }
454                 if(!isNull(rec.publisher()) ) {
455                         unHideMe( $n(r, "result_table_extra_span"));
456                         unHideMe($n(r, "result_table_pub_span"));
457                         $n(r, "result_table_pub_span").appendChild( text( " " + rec.publisher() ));
458                 }
459
460                 if(!isNull(rec.physical_description()) ) {
461                         unHideMe( $n(r, "result_table_extra_span"));
462                         var t = " " + rec.physical_description();
463                         //$n(r, "result_table_phys_span").appendChild( text(t.replace(/:.*/g,'')));
464                         $n(r, "result_table_phys_span").appendChild( text(t));
465                 }
466
467         }
468
469         resultBuildFormatIcons( r, rec, is_mr );
470
471         unHideMe(r);
472         
473         runEvt("result", "recordDrawn", rec.doc_id(), title_link);
474
475         /*
476         if(resultPageIsDone())  {
477                 runEvt('result', 'allRecordsReceived', recordsCache);
478         }
479         */
480 }
481
482 function _resultFindRec(id) {
483         for( var i = 0; i != recordsCache.length; i++ ) {
484                 var rec = recordsCache[i];
485                 if( rec && rec.doc_id() == id )
486                         return rec;
487         }
488         return null;
489 }
490
491
492 function resultBuildFormatIcons( row, rec, is_mr ) {
493
494         var ress = rec.types_of_resource();
495
496         for( var i in ress ) {
497
498                 var res = ress[i];
499                 if(!res) continue;
500
501                 var link = $n(row, res + "_link");
502                 link.title = res;
503                 var img = link.getElementsByTagName("img")[0];
504                 removeCSSClass( img, config.css.dim );
505
506                 var f = getForm();
507                 if( f != "all" ) {
508                         if( f == modsFormatToMARC(res) ) 
509                                 addCSSClass( img, "dim2_border");
510                 }
511
512                 var args = {};
513                 args[PARAM_OFFSET] = 0;
514
515                 if(is_mr) {
516                         args.page = RRESULT;
517                         args[PARAM_TFORM] = modsFormatToMARC(res);
518                         args[PARAM_MRID] = rec.doc_id();
519
520                 } else {
521                         args.page = RDETAIL
522                         args[PARAM_RID] = rec.doc_id();
523                 }
524
525                 link.setAttribute("href", buildOPACLink(args));
526
527         }
528 }
529
530
531 function resultPageIsDone(pos) {
532         return (recordsHandled == getDisplayCount() 
533                 || recordsHandled + getOffset() == getHitCount());
534 }
535
536 var resultCCHeaderApplied = false;
537
538 /* -------------------------------------------------------------------- */
539 /* dynamically add the copy count rows based on the org type 'countsrow' 
540         is the row into which we will add TD's to hold the copy counts 
541         This code generates copy count cells with an id of
542         'copy_count_cell_<depth>_<pagePosition>'  */
543 function resultAddCopyCounts(rec, pagePosition) {
544
545         var r = table.rows[pagePosition + 1];
546         var countsrow = $n(r, config.names.result.counts_row );
547         var ccell = $n(countsrow, config.names.result.count_cell);
548
549         var nodes = orgNodeTrail(findOrgUnit(getLocation()));
550         var node = nodes[0];
551         var type = findOrgType(node.ou_type());
552         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
553         ccell.title = type.opac_label();
554         //addCSSClass(ccell, config.css.result.cc_cell_even);
555
556         var lastcell = ccell;
557         var lastheadcell = null;
558
559         var cchead = null;
560         var ccheadcell = null;
561         if(!resultCCHeaderApplied) {
562                 ccrow = $('result_thead_row');
563                 ccheadcell =  ccrow.removeChild($n(ccrow, "result_thead_ccell"));
564                 var t = ccheadcell.cloneNode(true);
565                 lastheadcell = t;
566                 t.appendChild(text(type.opac_label()));
567                 ccrow.appendChild(t);
568                 resultCCHeaderApplied = true;
569         }
570
571         if(nodes[1]) {
572
573                 var x = 1;
574                 var d = findOrgDepth(nodes[1]);
575                 var d2 = findOrgDepth(nodes[nodes.length -1]);
576
577                 for( var i = d; i <= d2 ; i++ ) {
578         
579                         ccell = ccell.cloneNode(true);
580
581                         //if((i % 2)) removeCSSClass(ccell, "copy_count_cell_even");
582                         //else addCSSClass(ccell, "copy_count_cell_even");
583
584                         var node = nodes[x++];
585                         var type = findOrgType(node.ou_type());
586         
587                         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
588                         ccell.title = type.opac_label();
589                         countsrow.insertBefore(ccell, lastcell);
590                         lastcell = ccell;
591
592                         if(ccheadcell) {
593                                 var t = ccheadcell.cloneNode(true);
594                                 t.appendChild(text(type.opac_label()));
595                                 ccrow.insertBefore(t, lastheadcell);
596                                 lastheadcell = t;
597                         }
598                 }
599         }
600
601         unHideMe($("search_info_table"));
602 }
603
604 /* collect copy counts for a record using method 'methodName' */
605 function resultCollectCopyCounts(rec, pagePosition, methodName) {
606         if(rec == null || rec.doc_id() == null) return;
607         var req = new Request(methodName, getLocation(), rec.doc_id(), getForm() );
608         req.request.userdata = [ rec, pagePosition ];
609         req.callback(resultHandleCopyCounts);
610         req.send();
611 }
612
613 function resultHandleCopyCounts(r) {
614         runEvt('result', 'copyCountsReceived', r.userdata[0], r.userdata[1], r.getResultObject()); 
615 }
616
617
618 /* display the collected copy counts */
619 function resultDisplayCopyCounts(rec, pagePosition, copy_counts) {
620         if(copy_counts == null || rec == null) return;
621         var i = 0;
622         while(copy_counts[i] != null) {
623                 var cell = $("copy_count_cell_" + i +"_" + pagePosition);
624                 var cts = copy_counts[i];
625                 cell.appendChild(text(cts.available + " / " + cts.count));
626
627                 if(isXUL()) {
628                         /* here we style opac-invisible records for xul */
629
630                         if( cts.depth == 0 ) {
631                                 if(!cts.transcendant && !cts.unshadow) {
632                                         _debug("found an opac-shadowed record: " + rec.doc_id());
633                                         var row = cell.parentNode.parentNode.parentNode.parentNode.parentNode; 
634                                         if( cts.count == 0 ) 
635                                                 addCSSClass( row, 'no_copies' );
636                                         else 
637                                                 addCSSClass( row, 'shadowed' );
638                                 }
639                         }
640                 }
641                 i++;
642         }
643 }
644
645