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