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