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