]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/opac/skin/default/js/result_common.js
removed debugging alert
[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         args.org_unit = getLocation();
67         args.depth    = getDepth();
68         args.limit    = limit;
69         args.offset   = getOffset();
70         args.visibility_limit = 3000;
71     args.default_class = getStype();
72
73         if(sort) args.sort = sort;
74         if(sortdir) args.sort_dir = sortdir;
75         if(item_type) args.item_type    = item_type;
76         if(item_form) args.item_form    = item_form;
77     if(getAvail()) args.available = 1;
78
79
80         if(getAudience()) args.audience  = getAudience().split(/,/);
81         if(getLitForm()) args.lit_form  = getLitForm().split(/,/);
82         if(getLanguage()) args.language = getLanguage().split(/,/);
83
84         _debug('Search args: ' + js2JSON(args));
85         _debug('Raw query: ' + getTerm());
86
87         var req = new Request(method, args, getTerm(), 1);
88         req.callback(handler);
89         req.send();
90 }
91
92
93
94
95
96 /* set the search result info, number of hits, which results we're 
97         displaying, links to the next/prev pages, etc. */
98 function resultSetHitInfo() { 
99
100
101         /* tell the user where the results are coming from */
102         var baseorg = findOrgUnit(getLocation());
103         var depth = getDepth();
104         var mydepth = findOrgDepth(baseorg);
105         if( findOrgDepth(baseorg) != depth ) {
106                 var tmporg = baseorg;
107                 while( mydepth > depth ) {
108                         mydepth--;
109                         tmporg = findOrgUnit(tmporg.parent_ou());
110                 }
111                 unHideMe($('including_results_for'));
112                 $('including_results_location').appendChild(text(tmporg.name()));
113         }
114
115
116         try{searchTimer.stop()}catch(e){}
117
118         //if( findCurrentPage() == MRESULT ) {
119         if( findCurrentPage() == MRESULT || 
120
121                 (findCurrentPage() == RRESULT &&
122                         (
123                                 getRtype() == RTYPE_TITLE ||
124                                 getRtype() == RTYPE_AUTHOR ||
125                                 getRtype() == RTYPE_SUBJECT ||
126                                 getRtype() == RTYPE_SERIES ||
127                                 getRtype() == RTYPE_KEYWORD 
128                         )
129
130                 ) ) {
131
132                 if(getHitCount() <= lowHitCount && getTerm())
133                         runEvt('result', 'lowHits');
134         }
135
136         if(getHitCount() == 0) {
137                 runEvt('result', 'zeroHits');
138                 return;
139         }
140
141
142         var pages = getHitCount() / getDisplayCount();
143         if(pages % 1) pages = parseInt(pages) + 1;
144
145         
146
147         var cpage = (getOffset()/getDisplayCount()) + 1;
148
149         G.ui.result.current_page.appendChild(text(cpage));
150         G.ui.result.num_pages.appendChild(text(pages + ")")); /* the ) is dumb */
151
152         $('current_page2').appendChild(text(cpage));
153         $('num_pages2').appendChild(text(pages + ")")); /* the ) is dumb */
154
155         /* set the offsets */
156         var offsetEnd = getDisplayCount() + getOffset();  
157         if( getDisplayCount() > (getHitCount() - getOffset()))  
158                 offsetEnd = getHitCount();
159
160         G.ui.result.offset_end.appendChild(text(offsetEnd));
161         G.ui.result.offset_start.appendChild(text(getOffset() + 1));
162
163         $('offset_end2').appendChild(text(offsetEnd));
164         $('offset_start2').appendChild(text(getOffset() + 1));
165
166         G.ui.result.result_count.appendChild(text(getHitCount()));
167         unHideMe(G.ui.result.info);
168
169         $('result_count2').appendChild(text(getHitCount()));
170         unHideMe($('result_info_div2'));
171 }
172
173 function resultLowHits() {
174         showCanvas();
175         unHideMe($('result_low_hits'));
176         if(getHitCount() > 0)
177                 unHideMe($('result_low_hits_msg'));
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 function fetchGoogleBooks () {
582     if (isbnList && googleBooks) {
583         var scriptElement = document.createElement("script");
584         scriptElement.setAttribute("id", "jsonScript");
585         scriptElement.setAttribute("src",
586             "http://books.google.com/books?bibkeys=" + 
587             escape(isbnList) + "&jscmd=viewapi&callback=unhideGoogleBooks");
588         scriptElement.setAttribute("type", "text/javascript");
589         // make the request to Google Book Search
590         document.documentElement.firstChild.appendChild(scriptElement);
591     }
592 }
593
594 function resultPageIsDone(pos) {
595
596         return (recordsHandled == getDisplayCount() 
597                 || recordsHandled + getOffset() == getHitCount());
598 }
599
600 var resultCCHeaderApplied = false;
601
602 /* -------------------------------------------------------------------- */
603 /* dynamically add the copy count rows based on the org type 'countsrow' 
604         is the row into which we will add TD's to hold the copy counts 
605         This code generates copy count cells with an id of
606         'copy_count_cell_<depth>_<pagePosition>'  */
607 function resultAddCopyCounts(rec, pagePosition) {
608
609         var r = table.rows[pagePosition + 1];
610         var countsrow = $n(r, config.names.result.counts_row );
611         var ccell = $n(countsrow, config.names.result.count_cell);
612
613         var nodes = orgNodeTrail(findOrgUnit(getLocation()));
614         var node = nodes[0];
615         var type = findOrgType(node.ou_type());
616         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
617         ccell.title = type.opac_label();
618         //addCSSClass(ccell, config.css.result.cc_cell_even);
619
620         var lastcell = ccell;
621         var lastheadcell = null;
622
623         var cchead = null;
624         var ccheadcell = null;
625         if(!resultCCHeaderApplied) {
626                 ccrow = $('result_thead_row');
627                 ccheadcell =  ccrow.removeChild($n(ccrow, "result_thead_ccell"));
628                 var t = ccheadcell.cloneNode(true);
629                 lastheadcell = t;
630                 t.appendChild(text(type.opac_label()));
631                 ccrow.appendChild(t);
632                 resultCCHeaderApplied = true;
633         }
634
635         if(nodes[1]) {
636
637                 var x = 1;
638                 var d = findOrgDepth(nodes[1]);
639                 var d2 = findOrgDepth(nodes[nodes.length -1]);
640
641                 for( var i = d; i <= d2 ; i++ ) {
642         
643                         ccell = ccell.cloneNode(true);
644
645                         //if((i % 2)) removeCSSClass(ccell, "copy_count_cell_even");
646                         //else addCSSClass(ccell, "copy_count_cell_even");
647
648                         var node = nodes[x++];
649                         var type = findOrgType(node.ou_type());
650         
651                         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
652                         ccell.title = type.opac_label();
653                         countsrow.insertBefore(ccell, lastcell);
654                         lastcell = ccell;
655
656                         if(ccheadcell) {
657                                 var t = ccheadcell.cloneNode(true);
658                                 t.appendChild(text(type.opac_label()));
659                                 ccrow.insertBefore(t, lastheadcell);
660                                 lastheadcell = t;
661                         }
662                 }
663         }
664
665         unHideMe($("search_info_table"));
666 }
667
668 /* collect copy counts for a record using method 'methodName' */
669 function resultCollectCopyCounts(rec, pagePosition, methodName) {
670         if(rec == null || rec.doc_id() == null) return;
671         var req = new Request(methodName, getLocation(), rec.doc_id(), getForm() );
672         req.request.userdata = [ rec, pagePosition ];
673         req.callback(resultHandleCopyCounts);
674         req.send();
675 }
676
677 function resultHandleCopyCounts(r) {
678         runEvt('result', 'copyCountsReceived', r.userdata[0], r.userdata[1], r.getResultObject()); 
679 }
680
681
682 /* display the collected copy counts */
683 function resultDisplayCopyCounts(rec, pagePosition, copy_counts) {
684         if(copy_counts == null || rec == null) return;
685         var i = 0;
686         while(copy_counts[i] != null) {
687                 var cell = $("copy_count_cell_" + i +"_" + pagePosition);
688                 var cts = copy_counts[i];
689                 cell.appendChild(text(cts.available + " / " + cts.count));
690
691                 if(isXUL()) {
692                         /* here we style opac-invisible records for xul */
693
694                         if( cts.depth == 0 ) {
695                                 if(!cts.transcendant && !cts.unshadow) {
696                                         _debug("found an opac-shadowed record: " + rec.doc_id());
697                                         var row = cell.parentNode.parentNode.parentNode.parentNode.parentNode; 
698                                         if( cts.count == 0 ) 
699                                                 addCSSClass( row, 'no_copies' );
700                                         else 
701                                                 addCSSClass( row, 'shadowed' );
702                                 }
703                         }
704                 }
705                 i++;
706         }
707 }
708
709