tweak to default suggestion for low-hits search
[evergreen-equinox.git] / Open-ILS / web / opac / skin / default / js / result_common.js
1 dojo.require('openils.BibTemplate');
2 dojo.requireLocalization("openils.opac", "opac");
3 var opac_strings = dojo.i18n.getLocalization("openils.opac", "opac");
4
5 var recordsHandled = 0;
6 var recordsCache = [];
7 var lowHitCount = 4;
8 var isbnList = '';
9 var googleBooksLink = true;
10
11 var resultFetchAllRecords = false;
12 var resultCompiledSearch = null;
13
14 /* set up the event handlers */
15 if( findCurrentPage() == MRESULT || findCurrentPage() == RRESULT ) {
16         G.evt.result.hitCountReceived.push(resultSetHitInfo);
17         G.evt.result.recordReceived.push(resultDisplayRecord, resultAddCopyCounts);
18         G.evt.result.copyCountsReceived.push(resultDisplayCopyCounts);
19         G.evt.result.allRecordsReceived.push( function(){unHideMe($('result_info_2'))}, fetchGoogleBooksLink, fetchChiliFreshReviews);
20
21         attachEvt('result','lowHits',resultLowHits);
22         attachEvt('result','zeroHits',resultZeroHits);
23         attachEvt( "common", "locationUpdated", resultSBSubmit );
24         /* do this after we have ID's so the rank for mr pages will be correct */
25         attachEvt("result", "preCollectRecords", resultPaginate);
26 }
27
28 function resultSBSubmit(){searchBarSubmit();}
29
30 /* returns the last 'index' postion ocurring in this page */
31 function resultFinalPageIndex() {
32         if(getHitCount() < (getOffset() + getDisplayCount())) 
33                 return getHitCount() - 1;
34         return getOffset() + getDisplayCount() - 1;
35 }
36
37
38
39
40 /* generic search method */
41 function resultCollectSearchIds( type, method, handler ) {
42
43         var sort                = (getSort() == SORT_TYPE_REL) ? null : getSort(); 
44         var sortdir = (sort) ? ((getSortDir()) ? getSortDir() : SORT_DIR_ASC) : null;
45
46         var item_type;
47         var item_form;
48         var args = {};
49
50         if( type ) {
51                 var form = parseForm(getForm());
52                 item_type = form.item_type;
53                 item_form = form.item_form;
54
55         } else {
56                 item_type = (getItemType()) ? getItemType().split(/,/) : null;
57                 item_form = (getItemForm()) ? getItemForm().split(/,/) : null;
58         }
59
60         var limit = (resultFetchAllRecords) ? 1000 : getDisplayCount();
61
62         if( getOffset() > 0 ) {
63                 if( getHitCount() > 0 && (getOffset() + getDisplayCount()) > getHitCount() ) 
64                         limit = getHitCount() - getOffset();
65         }
66
67         var lasso = getLasso();
68
69         if (lasso) args.org_unit = -lasso;
70         else args.org_unit = getLocation();
71
72         args.depth    = getDepth();
73         args.limit    = limit;
74         args.offset   = getOffset();
75         args.visibility_limit = 3000;
76     args.default_class = getStype();
77
78         if(sort) args.sort = sort;
79         if(sortdir) args.sort_dir = sortdir;
80         if(item_type) args.item_type    = item_type;
81         if(item_form) args.item_form    = item_form;
82     if(getAvail()) args.available = 1;
83
84
85         if(getFacet()) args.facets  = getFacet();
86
87         if(getAudience()) args.audience  = getAudience().split(/,/);
88         if(getLitForm()) args.lit_form  = getLitForm().split(/,/);
89         if(getLanguage()) args.language = getLanguage().split(/,/);
90         if(getBibLevel()) args.bib_level        = getBibLevel().split(/,/);
91         if(getCopyLocs()) args.locations        = getCopyLocs().split(/,/);
92     if(getPubdBefore()) args.before = getPubdBefore();
93     else if(getPubdAfter()) args.after = getPubdAfter();
94     else if(getPubdBetween()) args.between = getPubdBetween().split(/,/);
95
96         _debug('Search args: ' + js2JSON(args));
97         _debug('Raw query: ' + getTerm());
98
99         var atomfeed = "/opac/extras/opensearch/1.1/" + findOrgUnit(args.org_unit).shortname() + "/atom-full/" + getStype() + '?searchTerms=' + getTerm();
100         if (args.facets) { atomfeed += ' ' + args.facets; }
101         if (sort) { atomfeed += '&searchSort=' + sort; }
102         if (sortdir) { atomfeed += '&searchSortDir=' + sortdir; }
103         dojo.create('link', {"rel":"alternate", "href":atomfeed, "type":"application/atom+xml"}, dojo.query('head')[0]);
104
105         var req = new Request(method, args, getTerm(), 1);
106         req.callback(handler);
107         req.send();
108 }
109
110
111
112
113
114 /* set the search result info, number of hits, which results we're 
115         displaying, links to the next/prev pages, etc. */
116 function resultSetHitInfo() { 
117
118         var lasso = getLasso();
119         if (!lasso) {
120                 /* tell the user where the results are coming from */
121                 var baseorg = findOrgUnit(getLocation());
122                 var depth = getDepth();
123                 var mydepth = findOrgDepth(baseorg);
124                 if( findOrgDepth(baseorg) != depth ) {
125                         var tmporg = baseorg;
126                         while( mydepth > depth ) {
127                                 mydepth--;
128                                 tmporg = findOrgUnit(tmporg.parent_ou());
129                         }
130                         unHideMe($('including_results_for'));
131                         $('including_results_location').appendChild(text(tmporg.name()));
132                 }
133         }
134
135
136         try{searchTimer.stop()}catch(e){}
137
138         //if( findCurrentPage() == MRESULT ) {
139         if( findCurrentPage() == MRESULT || 
140
141                 (findCurrentPage() == RRESULT &&
142                         (
143                                 getRtype() == RTYPE_TITLE ||
144                                 getRtype() == RTYPE_AUTHOR ||
145                                 getRtype() == RTYPE_SUBJECT ||
146                                 getRtype() == RTYPE_SERIES ||
147                                 getRtype() == RTYPE_KEYWORD 
148                         )
149
150                 ) ) {
151
152                 if(getHitCount() <= lowHitCount && getTerm())
153                         runEvt('result', 'lowHits');
154         }
155
156         if(getHitCount() == 0) {
157                 runEvt('result', 'zeroHits');
158                 return;
159         }
160
161
162         var pages = getHitCount() / getDisplayCount();
163         if(pages % 1) pages = parseInt(pages) + 1;
164
165         
166
167         var cpage = (getOffset()/getDisplayCount()) + 1;
168
169         G.ui.result.current_page.appendChild(text(cpage));
170         G.ui.result.num_pages.appendChild(text(pages + ")")); /* the ) is dumb */
171
172         $('current_page2').appendChild(text(cpage));
173         $('num_pages2').appendChild(text(pages + ")")); /* the ) is dumb */
174
175         /* set the offsets */
176         var offsetEnd = getDisplayCount() + getOffset();  
177         if( getDisplayCount() > (getHitCount() - getOffset()))  
178                 offsetEnd = getHitCount();
179
180         G.ui.result.offset_end.appendChild(text(offsetEnd));
181         G.ui.result.offset_start.appendChild(text(getOffset() + 1));
182
183         $('offset_end2').appendChild(text(offsetEnd));
184         $('offset_start2').appendChild(text(getOffset() + 1));
185
186         G.ui.result.result_count.appendChild(text(getHitCount()));
187         unHideMe(G.ui.result.info);
188
189         $('result_count2').appendChild(text(getHitCount()));
190         unHideMe($('result_info_div2'));
191 }
192
193 function resultLowHits() {
194         showCanvas();
195         unHideMe($('result_low_hits'));
196         if(getHitCount() > 0)
197                 unHideMe($('result_low_hits_msg'));
198
199     var words = [];
200     for(var key in resultCompiledSearch.searches) 
201         words.push(resultCompiledSearch.searches[key].term);
202
203         var sreq = new Request(CHECK_SPELL, words.join(' '));
204         sreq.callback(resultSuggestSpelling);
205         sreq.send();
206
207     for(var key in resultCompiledSearch.searches) {
208                 var areq = new Request(FETCH_CROSSREF, key, resultCompiledSearch.searches[key].term);
209                 areq.callback(resultLowHitXRef);
210                 areq.send();
211         }
212
213         if( !(getForm() == null || getForm() == 'all' || getForm() == "") ) {
214                 var a = {};
215                 a[PARAM_FORM] = "all";
216                 $('low_hits_remove_format_link').setAttribute('href',buildOPACLink(a));
217                 unHideMe($('low_hits_remove_format'));
218         }
219
220         resultSuggestSearchClass();
221
222         if(getTerm()) resultExpandSearch(); /* advanced search */
223 }
224
225 var lowHitsXRefSet = {};
226 var lowHitsXRefLink;
227 var lowHitsXRefLinkParent;
228 function resultLowHitXRef(r) {
229         if(!lowHitsXRefLink){
230                 lowHitsXRefLinkParent = $('low_hits_xref_link').parentNode;
231                 lowHitsXRefLink = lowHitsXRefLinkParent.removeChild($('low_hits_xref_link'));
232         }
233         var res = r.getResultObject();
234         var arr = res.from;
235         arr.concat(res.also);
236         if(arr && arr.length > 0) {
237                 unHideMe($('low_hits_cross_ref'));
238                 var word;
239                 var c = 0;
240                 while( word = arr.shift() ) {
241
242             if (lowHitsXRefSet[word] == 1) continue;
243             lowHitsXRefSet[word] = 1;
244
245                         if(c++ > 20) break;
246                         var a = {};
247                         a[PARAM_TERM] = word;
248                         var template = lowHitsXRefLink.cloneNode(true);
249                         template.setAttribute('href',buildOPACLink(a));
250                         template.appendChild(text(word));
251                         lowHitsXRefLinkParent.appendChild(template);
252                         lowHitsXRefLinkParent.appendChild(text(' '));
253                 }
254         }
255 }
256
257 function resultZeroHits() {
258         showCanvas();
259         unHideMe($('result_low_hits'));
260         unHideMe($('result_zero_hits_msg'));
261         //if(getTerm()) resultExpandSearch(); /* advanced search */
262 }
263
264 function resultExpandSearch() {
265         var top = findOrgDepth(globalOrgTree);
266         if(getDepth() == top) return;
267         unHideMe($('low_hits_expand_range'));
268         var par = $('low_hits_expand_link').parentNode;
269         var template = par.removeChild($('low_hits_expand_link'));
270
271         var bottom = getDepth();
272         while( top < bottom ) {
273                 var a = {};
274                 a[PARAM_DEPTH] = top;
275                 var temp = template.cloneNode(true);
276                 temp.appendChild(text(findOrgTypeFromDepth(top).opac_label()))
277                 temp.setAttribute('href',buildOPACLink(a));
278                 par.appendChild(temp);
279                 top++;
280         }
281 }
282
283 function resultSuggestSearchClass() {
284         var stype = getStype();
285         if(stype == STYPE_KEYWORD) return;
286         var a = {}; var ref;
287         unHideMe($('low_hits_search_type'));
288         if(stype != STYPE_TITLE) {
289                 ref = $('low_hits_title_search');
290                 unHideMe(ref);
291                 a[PARAM_STYPE] = STYPE_TITLE;
292                 ref.setAttribute('href',buildOPACLink(a));
293         }
294         if(stype != STYPE_AUTHOR) {
295                 ref = $('low_hits_author_search');
296                 unHideMe(ref);
297                 a[PARAM_STYPE] = STYPE_AUTHOR;
298                 ref.setAttribute('href',buildOPACLink(a));
299         }
300         if(stype != STYPE_SUBJECT) {
301                 ref = $('low_hits_subject_search');
302                 unHideMe(ref);
303                 a[PARAM_STYPE] = STYPE_SUBJECT;
304                 ref.setAttribute('href',buildOPACLink(a));
305         }
306         if(stype != STYPE_KEYWORD) {
307                 ref = $('low_hits_keyword_search');
308                 unHideMe(ref);
309                 a[PARAM_STYPE] = STYPE_KEYWORD;
310                 ref.setAttribute('href',buildOPACLink(a));
311         }
312         if(stype != STYPE_SERIES) {
313                 ref = $('low_hits_series_search');
314                 unHideMe(ref);
315                 a[PARAM_STYPE] = STYPE_SERIES;
316                 ref.setAttribute('href',buildOPACLink(a));
317         }
318 }
319
320 function resultSuggestSpelling(r) {
321         var res = r.getResultObject();
322         var phrase = getTerm();
323         var words = phrase.split(/ /);
324
325         var newterm = "";
326
327         for( var w = 0; w < words.length; w++ ) {
328                 var word = words[w];
329                 var blob = grep(res, function(i){return (i.word == word);});
330                 if( blob ) blob = blob[0];
331                 else continue;
332                 if( blob.word == word ) {
333                         if( !blob.found && blob.suggestions && blob.suggestions[0] ) {
334                                 newterm += " " + blob.suggestions[0];
335                                 unHideMe($('did_you_mean'));
336                         } else {
337                                 newterm += " " + word;
338                         }
339                 }
340         }
341
342         var arg = {};
343         arg[PARAM_TERM] = newterm;
344         $('spell_check_link').setAttribute('href', buildOPACLink(arg));
345         $('spell_check_link').appendChild(text(newterm));
346 }
347
348
349 function resultPaginate() {
350         var o = getOffset();
351
352         if( !(  ((o) + getDisplayCount()) >= getHitCount()) ) {
353
354                 var args = {};
355                 args[PARAM_OFFSET]      = o + getDisplayCount();
356                 args[PARAM_SORT]                = SORT;
357                 args[PARAM_SORT_DIR] = SORT_DIR;
358                 args[PARAM_RLIST]               = new CGI().param(PARAM_RLIST);
359
360                 G.ui.result.next_link.setAttribute("href", buildOPACLink(args)); 
361                 addCSSClass(G.ui.result.next_link, config.css.result.nav_active);
362
363                 $('next_link2').setAttribute("href", buildOPACLink(args)); 
364                 addCSSClass($('next_link2'), config.css.result.nav_active);
365
366                 args[PARAM_OFFSET] = getHitCount() - (getHitCount() % getDisplayCount());
367
368                 /* when hit count is divisible by display count, we have to adjust */
369                 if( getHitCount() % getDisplayCount() == 0 ) 
370                         args[PARAM_OFFSET] -= getDisplayCount();
371
372         /*
373                 G.ui.result.end_link.setAttribute("href", buildOPACLink(args)); 
374                 addCSSClass(G.ui.result.end_link, config.css.result.nav_active);
375
376                 $('end_link2').setAttribute("href", buildOPACLink(args)); 
377                 addCSSClass($('end_link2'), config.css.result.nav_active);
378         */
379         }
380
381         if( o > 0 ) {
382
383                 var args = {};
384                 args[PARAM_SORT]                = SORT;
385                 args[PARAM_SORT_DIR] = SORT_DIR;
386                 args[PARAM_RLIST]               = new CGI().param(PARAM_RLIST);
387
388                 args[PARAM_OFFSET] = o - getDisplayCount();
389                 G.ui.result.prev_link.setAttribute( "href", buildOPACLink(args)); 
390                 addCSSClass(G.ui.result.prev_link, config.css.result.nav_active);
391
392                 $('prev_link2').setAttribute( "href", buildOPACLink(args)); 
393                 addCSSClass($('prev_link2'), config.css.result.nav_active);
394
395                 args[PARAM_OFFSET] = 0;
396                 G.ui.result.home_link.setAttribute( "href", buildOPACLink(args)); 
397                 addCSSClass(G.ui.result.home_link, config.css.result.nav_active);
398
399                 $('search_home_link2').setAttribute( "href", buildOPACLink(args)); 
400                 addCSSClass($('search_home_link2'), config.css.result.nav_active);
401         }
402
403         if(getDisplayCount() < getHitCount()) {
404                 unHideMe($('start_end_links_span'));
405                 unHideMe($('start_end_links_span2'));
406    }
407
408         showCanvas();
409         try{searchTimer.stop()}catch(e){}
410 }
411
412 function buildunAPISpan (span, type, id) {
413         var cgi = new CGI();
414         var d = new Date();
415
416         addCSSClass(span,'unapi-id');
417
418         span.setAttribute(
419                 'title',
420                 'tag:' + cgi.server_name + ',' +
421                         d.getFullYear() +
422                         ':' + type + '/' + id
423         );
424 }
425
426 function unhideGoogleBooksLink (data) {
427     for ( var i in data ) {
428         //if (data[i].preview == 'noview') continue;
429
430         var gbspan = $n(document.documentElement, 'googleBooksLink-' + i);
431         var gba = $n(gbspan, "googleBooks-link");
432
433         gba.setAttribute(
434             'href',
435             data[i].info_url
436         );
437         removeCSSClass( gbspan, 'hide_me' );
438     }
439 }
440
441 /* display the record info in the record display table 'pos' is the 
442                 zero based position the record should have in the display table */
443 function resultDisplayRecord(rec, pos, is_mr) {
444
445     fieldmapper.IDL.load(['mvr']);
446         if(rec == null) rec = new mvr(); /* so the page won't die if there was an error */
447         recordsHandled++;
448         recordsCache.push(rec);
449
450         var r = table.rows[pos + 1];
451     var currentISBN = cleanISBN(rec.isbn());
452
453     if (googleBooksLink) {
454             var gbspan = $n(r, "googleBooksLink");
455         if (currentISBN) {
456             gbspan.setAttribute(
457                 'name',
458                 gbspan.getAttribute('name') + '-' + currentISBN
459             );
460
461             if (isbnList) isbnList += ', ';
462             isbnList += currentISBN;
463         }
464     }
465
466     if (currentISBN && chilifresh && chilifresh != '(none)') {
467         var cfrow = $n(r, "chilifreshReview");
468         if (cfrow) {
469             removeCSSClass( cfrow, 'hide_me' );
470         }
471         var cflink = $n(r, "chilifreshReviewLink");
472         if (cflink) {
473             cflink.setAttribute(
474                 'id',
475                 'isbn_' + currentISBN
476             );
477         }
478         var cfdiv = $n(r, "chilifreshReviewResult");
479         if (cfdiv) {
480             cfdiv.setAttribute(
481                 'id',
482                 'chili_review_' + currentISBN
483             )
484         }
485     }
486
487 /*
488         try {
489                 var rank = parseFloat(ranks[pos + getOffset()]);
490                 rank            = parseInt( rank * 100 );
491                 var relspan = $n(r, "relevancy_span");
492                 relspan.appendChild(text(rank));
493                 unHideMe(relspan.parentNode);
494         } catch(e){ }
495 */
496
497         var pic = $n(r, config.names.result.item_jacket);
498         pic.setAttribute("src", buildISBNSrc(currentISBN));
499
500         var title_link = $n(r, config.names.result.item_title);
501         var author_link = $n(r, config.names.result.item_author);
502
503         var onlyrec;
504         if( is_mr )  {
505                 onlyrec = onlyrecord[ getOffset() + pos ];
506                 if(onlyrec) {
507                         buildunAPISpan($n(r,'unapi'), 'biblio-record_entry', onlyrec);
508
509                         var args = {};
510                         args.page = RDETAIL;
511                         args[PARAM_OFFSET] = 0;
512                         args[PARAM_RID] = onlyrec;
513                         args[PARAM_MRID] = rec.doc_id();
514                         pic.parentNode.setAttribute("href", buildOPACLink(args));
515                         title_link.setAttribute("href", buildOPACLink(args));
516                         title_link.appendChild(text(normalize(truncate(rec.title(), 65))));
517
518                 } else {
519                         buildunAPISpan($n(r,'unapi'), 'metabib-metarecord', rec.doc_id());
520
521                         buildTitleLink(rec, title_link); 
522                         var args = {};
523                         args.page = RRESULT;
524                         args[PARAM_OFFSET] = 0;
525                         args[PARAM_MRID] = rec.doc_id();
526                         pic.parentNode.setAttribute("href", buildOPACLink(args));
527                 }
528
529                 unHideMe($n(r,'place_hold_span'));
530                 $n(r,'place_hold_link').onclick = function() { resultDrawHoldsWindow(rec.doc_id(), 'M'); }
531             
532
533         } else {
534                 onlyrec = rec.doc_id();
535                 buildunAPISpan($n(r,'unapi'), 'biblio-record_entry', rec.doc_id());
536
537                 buildTitleDetailLink(rec, title_link); 
538                 var args = {};
539                 args.page = RDETAIL;
540                 args[PARAM_OFFSET] = 0;
541                 args[PARAM_RID] = rec.doc_id();
542                 pic.parentNode.setAttribute("href", buildOPACLink(args));
543
544                 unHideMe($n(r,'place_hold_span'));
545                 $n(r,'place_hold_link').onclick = function() { resultDrawHoldsWindow(rec.doc_id(), 'T'); }
546         }
547
548         buildSearchLink(STYPE_AUTHOR, rec.author(), author_link);
549
550         if(! is_mr ) {
551         
552                 if(!isNull(rec.edition()))      {
553                         unHideMe( $n(r, "result_table_extra_span"));
554                         $n(r, "result_table_edition_span").appendChild( text( rec.edition()) );
555                 }
556                 if(!isNull(rec.pubdate())) {
557                         unHideMe( $n(r, "result_table_extra_span"));
558                         unHideMe($n(r, "result_table_pub_span"));
559                         $n(r, "result_table_pub_span").appendChild( text( rec.pubdate() ));
560                 }
561                 if(!isNull(rec.publisher()) ) {
562                         unHideMe( $n(r, "result_table_extra_span"));
563                         unHideMe($n(r, "result_table_pub_span"));
564                         $n(r, "result_table_pub_span").appendChild( text( " " + rec.publisher() ));
565                 }
566
567                 if(!isNull(rec.physical_description()) ) {
568                         unHideMe( $n(r, "result_table_extra_span"));
569                         var t = " " + rec.physical_description();
570                         //$n(r, "result_table_phys_span").appendChild( text(t.replace(/:.*/g,'')));
571                         $n(r, "result_table_phys_span").appendChild( text(t));
572                 }
573
574         }
575
576         resultBuildFormatIcons( r, rec, is_mr );
577
578         var bt_params = {
579                 sync                    : false,
580                 root                    : r,
581                 subObjectLimit  : 10,
582                 org_unit                : findOrgUnit(getLocation()).shortname(),
583                 depth                   : getDepth()
584         };
585
586         if (!is_mr) {
587                 bt_params = dojo.mixin( bt_params, { record : onlyrec } );
588         } else {
589                 bt_params = dojo.mixin( bt_params, { metarecord : onlyrec } );
590         }
591
592         if (findOrgType(findOrgUnit(getLocation()).ou_type()).can_have_vols())
593                 unHideMe($n(r,'local_callnumber_list'));
594
595         new openils.BibTemplate( bt_params ).render();
596
597         unHideMe(r);
598         
599         runEvt("result", "recordDrawn", rec.doc_id(), title_link);
600
601         /*
602         if(resultPageIsDone())  {
603                 runEvt('result', 'allRecordsReceived', recordsCache);
604         }
605         */
606 }
607
608 function resultDrawHoldsWindow(hold_target, hold_type) {
609     var src = location.href;
610
611     if(forceLoginSSL && src.match(/^http:/)) {
612
613         src = src.replace(/^http:/, 'https:');
614
615         if(src.match(/&hold_target=/)) {
616             src.replace(/&hold_target=(\d+)/, hold_target);
617
618         } else {
619             src += '&hold_target=' + hold_target;
620         }
621
622         location.href = src;
623
624     } else {
625         holdsDrawEditor({record:hold_target, type:hold_type});
626     }
627 }
628
629
630
631 function _resultFindRec(id) {
632         for( var i = 0; i != recordsCache.length; i++ ) {
633                 var rec = recordsCache[i];
634                 if( rec && rec.doc_id() == id )
635                         return rec;
636         }
637         return null;
638 }
639
640
641 function resultBuildFormatIcons( row, rec, is_mr ) {
642
643         var ress = rec.types_of_resource();
644
645         for( var i in ress ) {
646
647                 var res = ress[i];
648                 if(!res) continue;
649
650                 var link = $n(row, res + "_link");
651                 link.title = res;
652                 var img = link.getElementsByTagName("img")[0];
653                 removeCSSClass( img, config.css.dim );
654
655                 var f = getForm();
656                 if( f != "all" ) {
657                         if( f == modsFormatToMARC(res) ) 
658                                 addCSSClass( img, "dim2_border");
659                 }
660
661                 var args = {};
662                 args[PARAM_OFFSET] = 0;
663
664                 if(is_mr) {
665                         args.page = RRESULT;
666                         args[PARAM_TFORM] = modsFormatToMARC(res);
667                         args[PARAM_MRID] = rec.doc_id();
668
669                 } else {
670                         args.page = RDETAIL
671                         args[PARAM_RID] = rec.doc_id();
672                 }
673
674                 link.setAttribute("href", buildOPACLink(args));
675
676         }
677 }
678
679 function fetchGoogleBooksLink () {
680     if (isbnList && googleBooksLink) {
681         var scriptElement = document.createElement("script");
682         scriptElement.setAttribute("id", "jsonScript");
683         scriptElement.setAttribute("src",
684             "http://books.google.com/books?bibkeys=" + 
685             escape(isbnList) + "&jscmd=viewapi&callback=unhideGoogleBooksLink");
686         scriptElement.setAttribute("type", "text/javascript");
687         // make the request to Google Book Search
688         document.documentElement.firstChild.appendChild(scriptElement);
689     }
690 }
691
692 function fetchChiliFreshReviews() {
693     if (chilifresh && chilifresh != '(none)') {
694         try { chili_init(); } catch(E) { console.log(E + '\n'); }
695     }
696 }
697
698 function resultPageIsDone(pos) {
699
700         return (recordsHandled == getDisplayCount() 
701                 || recordsHandled + getOffset() == getHitCount());
702 }
703
704 var resultCCHeaderApplied = false;
705
706 /* -------------------------------------------------------------------- */
707 /* dynamically add the copy count rows based on the org type 'countsrow' 
708         is the row into which we will add TD's to hold the copy counts 
709         This code generates copy count cells with an id of
710         'copy_count_cell_<depth>_<pagePosition>'  */
711 function resultAddCopyCounts(rec, pagePosition) {
712
713         var r = table.rows[pagePosition + 1];
714         var countsrow = $n(r, config.names.result.counts_row );
715         var ccell = $n(countsrow, config.names.result.count_cell);
716
717         var nodes = orgNodeTrail(findOrgUnit(getLocation()));
718         var start_here = 0;
719         var orgHiding = checkOrgHiding();
720         if (orgHiding) {
721                 for (var i = 0; i < nodes.length; i++) {
722                         if (orgHiding.depth == findOrgDepth(nodes[i])) {
723                                 start_here = i;
724                         }
725                 }
726         }
727
728         var node = nodes[start_here];
729         var type = findOrgType(node.ou_type());
730         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
731         ccell.title = type.opac_label();
732         //addCSSClass(ccell, config.css.result.cc_cell_even);
733
734         var lastcell = ccell;
735         var lastheadcell = null;
736
737         var cchead = null;
738         var ccheadcell = null;
739         if(!resultCCHeaderApplied && !getLasso()) {
740                 ccrow = $('result_thead_row');
741                 ccheadcell =  ccrow.removeChild($n(ccrow, "result_thead_ccell"));
742                 var t = ccheadcell.cloneNode(true);
743                 lastheadcell = t;
744                 t.appendChild(text(type.opac_label()));
745                 ccrow.appendChild(t);
746                 resultCCHeaderApplied = true;
747         }
748
749         if(nodes[start_here+1]) {
750
751                 var x = start_here+1;
752                 var d = findOrgDepth(nodes[start_here+1]);
753                 var d2 = findOrgDepth(nodes[nodes.length -1]);
754
755                 for( var i = d; i <= d2 ; i++ ) {
756         
757                         ccell = ccell.cloneNode(true);
758
759                         //if((i % 2)) removeCSSClass(ccell, "copy_count_cell_even");
760                         //else addCSSClass(ccell, "copy_count_cell_even");
761
762                         var node = nodes[x++];
763                         var type = findOrgType(node.ou_type());
764         
765                         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
766                         ccell.title = type.opac_label();
767                         countsrow.insertBefore(ccell, lastcell);
768                         lastcell = ccell;
769
770                         if(ccheadcell) {
771                                 var t = ccheadcell.cloneNode(true);
772                                 t.appendChild(text(type.opac_label()));
773                                 ccrow.insertBefore(t, lastheadcell);
774                                 lastheadcell = t;
775                         }
776                 }
777         }
778
779         unHideMe($("search_info_table"));
780 }
781
782 /* collect copy counts for a record using method 'methodName' */
783 function resultCollectCopyCounts(rec, pagePosition, methodName) {
784         if(rec == null || rec.doc_id() == null) return;
785
786         var loc = getLasso();
787         if (loc) loc = -loc;
788         else loc= getLocation();
789
790         var req = new Request(methodName, loc, rec.doc_id(), getForm() );
791         req.request.userdata = [ rec, pagePosition ];
792         req.callback(resultHandleCopyCounts);
793         req.send();
794 }
795
796 function resultHandleCopyCounts(r) {
797         runEvt('result', 'copyCountsReceived', r.userdata[0], r.userdata[1], r.getResultObject()); 
798 }
799
800
801 /* XXX Needs to understand Lasso copy counts... */
802 /* display the collected copy counts */
803 function resultDisplayCopyCounts(rec, pagePosition, copy_counts) {
804         if(copy_counts == null || rec == null) return;
805
806         if (getLasso()) {
807                 var copy_counts_lasso = {
808                         transcendant : null,
809                         count : 0,
810                         unshadow : 0,
811                         available : 0,
812                         depth : -1,
813                         org_unit : getLasso()
814                 };
815
816                 for (var i in copy_counts) {
817                         copy_counts_lasso.transcendant = copy_counts[i].transcendant;
818                         copy_counts_lasso.count += parseInt(copy_counts[i].count);
819                         copy_counts_lasso.unshadow += parseInt(copy_counts[i].unshadow);
820                         copy_counts_lasso.available += parseInt(copy_counts[i].available);
821                 }
822
823                 copy_counts = [ copy_counts_lasso ];
824         }
825
826         var i = 0;
827         while(copy_counts[i] != null) {
828                 var cell = $("copy_count_cell_" + i +"_" + pagePosition);
829                 if (cell) {
830                         var cts = copy_counts[i];
831                         cell.appendChild(text(cts.available + " / " + cts.count));
832
833                         if(isXUL()) {
834                                 /* here we style opac-invisible records for xul */
835
836                                 if( cts.depth == 0 ) {
837                                         if(cts.transcendant == null && cts.unshadow == 0) {
838                                                 _debug("found an opac-shadowed record: " + rec.doc_id());
839                                                 var row = cell.parentNode.parentNode.parentNode.parentNode.parentNode; 
840                                                 if( cts.count == 0 ) 
841                                                         addCSSClass( row, 'no_copies' );
842                                                 else 
843                                                         addCSSClass( row, 'shadowed' );
844                                         }
845                                 }
846                         }
847                 }
848                 i++;
849         }
850 }
851
852