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