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