2 var recordsHandled = 0;
6 var googleBooksLink = true;
8 var resultFetchAllRecords = false;
9 var resultCompiledSearch = null;
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 fetchGoogleBooksLink);
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);
27 function resultSBSubmit(){searchBarSubmit();}
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;
39 /* generic search method */
40 function resultCollectSearchIds( type, method, handler ) {
42 var sort = (getSort() == SORT_TYPE_REL) ? null : getSort();
43 var sortdir = (sort) ? ((getSortDir()) ? getSortDir() : SORT_DIR_ASC) : null;
50 var form = parseForm(getForm());
51 item_type = form.item_type;
52 item_form = form.item_form;
55 item_type = (getItemType()) ? getItemType().split(/,/) : null;
56 item_form = (getItemForm()) ? getItemForm().split(/,/) : null;
59 var limit = (resultFetchAllRecords) ? 1000 : getDisplayCount();
61 if( getOffset() > 0 ) {
62 if( getHitCount() > 0 && (getOffset() + getDisplayCount()) > getHitCount() )
63 limit = getHitCount() - getOffset();
66 var lasso = getLasso();
68 if (lasso) args.org_unit = -lasso;
69 else args.org_unit = getLocation();
71 args.depth = getDepth();
73 args.offset = getOffset();
74 args.visibility_limit = 3000;
75 args.default_class = getStype();
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;
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(/,/);
93 _debug('Search args: ' + js2JSON(args));
94 _debug('Raw query: ' + getTerm());
96 var req = new Request(method, args, getTerm(), 1);
97 req.callback(handler);
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() {
109 var lasso = getLasso();
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 ) {
119 tmporg = findOrgUnit(tmporg.parent_ou());
121 unHideMe($('including_results_for'));
122 $('including_results_location').appendChild(text(tmporg.name()));
127 try{searchTimer.stop()}catch(e){}
129 //if( findCurrentPage() == MRESULT ) {
130 if( findCurrentPage() == MRESULT ||
132 (findCurrentPage() == RRESULT &&
134 getRtype() == RTYPE_TITLE ||
135 getRtype() == RTYPE_AUTHOR ||
136 getRtype() == RTYPE_SUBJECT ||
137 getRtype() == RTYPE_SERIES ||
138 getRtype() == RTYPE_KEYWORD
143 if(getHitCount() <= lowHitCount && getTerm())
144 runEvt('result', 'lowHits');
147 if(getHitCount() == 0) {
148 runEvt('result', 'zeroHits');
153 var pages = getHitCount() / getDisplayCount();
154 if(pages % 1) pages = parseInt(pages) + 1;
158 var cpage = (getOffset()/getDisplayCount()) + 1;
160 G.ui.result.current_page.appendChild(text(cpage));
161 G.ui.result.num_pages.appendChild(text(pages + ")")); /* the ) is dumb */
163 $('current_page2').appendChild(text(cpage));
164 $('num_pages2').appendChild(text(pages + ")")); /* the ) is dumb */
166 /* set the offsets */
167 var offsetEnd = getDisplayCount() + getOffset();
168 if( getDisplayCount() > (getHitCount() - getOffset()))
169 offsetEnd = getHitCount();
171 G.ui.result.offset_end.appendChild(text(offsetEnd));
172 G.ui.result.offset_start.appendChild(text(getOffset() + 1));
174 $('offset_end2').appendChild(text(offsetEnd));
175 $('offset_start2').appendChild(text(getOffset() + 1));
177 G.ui.result.result_count.appendChild(text(getHitCount()));
178 unHideMe(G.ui.result.info);
180 $('result_count2').appendChild(text(getHitCount()));
181 unHideMe($('result_info_div2'));
184 function resultLowHits() {
186 unHideMe($('result_low_hits'));
187 if(getHitCount() > 0)
188 unHideMe($('result_low_hits_msg'));
191 for(var key in resultCompiledSearch.searches)
192 words.push(resultCompiledSearch.searches[key].term);
194 var sreq = new Request(CHECK_SPELL, words.join(' '));
195 sreq.callback(resultSuggestSpelling);
198 for(var key in resultCompiledSearch.searches) {
199 var areq = new Request(FETCH_CROSSREF, key, resultCompiledSearch.searches[key].term);
200 areq.callback(resultLowHitXRef);
204 if( !(getForm() == null || getForm() == 'all' || getForm() == "") ) {
206 a[PARAM_FORM] = "all";
207 $('low_hits_remove_format_link').setAttribute('href',buildOPACLink(a));
208 unHideMe($('low_hits_remove_format'));
211 resultSuggestSearchClass();
213 if(getTerm()) resultExpandSearch(); /* advanced search */
216 var lowHitsXRefSet = {};
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'));
224 var res = r.getResultObject();
226 arr.concat(res.also);
227 if(arr && arr.length > 0) {
228 unHideMe($('low_hits_cross_ref'));
231 while( word = arr.shift() ) {
233 if (lowHitsXRefSet[word] == 1) continue;
234 lowHitsXRefSet[word] = 1;
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(' '));
248 function resultZeroHits() {
250 unHideMe($('result_low_hits'));
251 unHideMe($('result_zero_hits_msg'));
252 //if(getTerm()) resultExpandSearch(); /* advanced search */
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'));
262 var bottom = getDepth();
263 while( top < bottom ) {
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);
274 function resultSuggestSearchClass() {
275 var stype = getStype();
276 if(stype == STYPE_KEYWORD) return;
278 unHideMe($('low_hits_search_type'));
279 if(stype != STYPE_TITLE) {
280 ref = $('low_hits_title_search');
282 a[PARAM_STYPE] = STYPE_TITLE;
283 ref.setAttribute('href',buildOPACLink(a));
285 if(stype != STYPE_AUTHOR) {
286 ref = $('low_hits_author_search');
288 a[PARAM_STYPE] = STYPE_AUTHOR;
289 ref.setAttribute('href',buildOPACLink(a));
291 if(stype != STYPE_SUBJECT) {
292 ref = $('low_hits_subject_search');
294 a[PARAM_STYPE] = STYPE_SUBJECT;
295 ref.setAttribute('href',buildOPACLink(a));
297 if(stype != STYPE_KEYWORD) {
298 ref = $('low_hits_keyword_search');
300 a[PARAM_STYPE] = STYPE_KEYWORD;
301 ref.setAttribute('href',buildOPACLink(a));
303 if(stype != STYPE_SERIES) {
304 ref = $('low_hits_series_search');
306 a[PARAM_STYPE] = STYPE_SERIES;
307 ref.setAttribute('href',buildOPACLink(a));
311 function resultSuggestSpelling(r) {
312 var res = r.getResultObject();
313 var phrase = getTerm();
314 var words = phrase.split(/ /);
318 for( var w = 0; w < words.length; w++ ) {
320 var blob = grep(res, function(i){return (i.word == word);});
321 if( blob ) blob = blob[0];
323 if( blob.word == word ) {
324 if( blob.suggestions && blob.suggestions[0] ) {
325 newterm += " " + blob.suggestions[0];
326 unHideMe($('did_you_mean'));
328 newterm += " " + word;
334 arg[PARAM_TERM] = newterm;
335 $('spell_check_link').setAttribute('href', buildOPACLink(arg));
336 $('spell_check_link').appendChild(text(newterm));
340 function resultPaginate() {
343 if( !( ((o) + getDisplayCount()) >= getHitCount()) ) {
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);
351 G.ui.result.next_link.setAttribute("href", buildOPACLink(args));
352 addCSSClass(G.ui.result.next_link, config.css.result.nav_active);
354 $('next_link2').setAttribute("href", buildOPACLink(args));
355 addCSSClass($('next_link2'), config.css.result.nav_active);
357 args[PARAM_OFFSET] = getHitCount() - (getHitCount() % getDisplayCount());
359 /* when hit count is divisible by display count, we have to adjust */
360 if( getHitCount() % getDisplayCount() == 0 )
361 args[PARAM_OFFSET] -= getDisplayCount();
364 G.ui.result.end_link.setAttribute("href", buildOPACLink(args));
365 addCSSClass(G.ui.result.end_link, config.css.result.nav_active);
367 $('end_link2').setAttribute("href", buildOPACLink(args));
368 addCSSClass($('end_link2'), config.css.result.nav_active);
375 args[PARAM_SORT] = SORT;
376 args[PARAM_SORT_DIR] = SORT_DIR;
377 args[PARAM_RLIST] = new CGI().param(PARAM_RLIST);
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);
383 $('prev_link2').setAttribute( "href", buildOPACLink(args));
384 addCSSClass($('prev_link2'), config.css.result.nav_active);
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);
390 $('search_home_link2').setAttribute( "href", buildOPACLink(args));
391 addCSSClass($('search_home_link2'), config.css.result.nav_active);
394 if(getDisplayCount() < getHitCount()) {
395 unHideMe($('start_end_links_span'));
396 unHideMe($('start_end_links_span2'));
400 try{searchTimer.stop()}catch(e){}
403 function buildunAPISpan (span, type, id) {
407 addCSSClass(span,'unapi-id');
411 'tag:' + cgi.server_name + ',' +
413 ':' + type + '/' + id
417 function unhideGoogleBooksLink (data) {
418 for ( var i in data ) {
419 //if (data[i].preview == 'noview') continue;
421 var gbspan = $n(document.documentElement, 'googleBooksLink-' + i);
422 var gba = $n(gbspan, "googleBooks-link");
428 removeCSSClass( gbspan, 'hide_me' );
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) {
436 if(rec == null) rec = new mvr(); /* so the page won't die if there was an error */
438 recordsCache.push(rec);
440 var r = table.rows[pos + 1];
441 var currentISBN = cleanISBN(rec.isbn());
443 if (googleBooksLink) {
444 var gbspan = $n(r, "googleBooksLink");
448 gbspan.getAttribute('name') + '-' + currentISBN
451 if (isbnList) isbnList += ', ';
452 isbnList += currentISBN;
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);
466 var pic = $n(r, config.names.result.item_jacket);
467 pic.setAttribute("src", buildISBNSrc(currentISBN));
469 var title_link = $n(r, config.names.result.item_title);
470 var author_link = $n(r, config.names.result.item_author);
473 var onlyrec = onlyrecord[ getOffset() + pos ];
475 buildunAPISpan($n(r,'unapi'), 'biblio-record_entry', onlyrec);
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))));
486 var here = findOrgUnit(getLocation());
487 if (findOrgType(here.ou_type()).can_have_vols()) { // show the callnumber list
488 dojo.require('openils.BibTemplate');
489 var l_cn_list = $n(r,'local_callnumber_list');
494 new openils.BibTemplate({
496 record : '' + onlyrec + '[10]',
497 org_unit : here.shortname()
504 buildunAPISpan($n(r,'unapi'), 'metabib-metarecord', rec.doc_id());
506 buildTitleLink(rec, title_link);
509 args[PARAM_OFFSET] = 0;
510 args[PARAM_MRID] = rec.doc_id();
511 pic.parentNode.setAttribute("href", buildOPACLink(args));
515 buildunAPISpan($n(r,'unapi'), 'biblio-record_entry', rec.doc_id());
517 buildTitleDetailLink(rec, title_link);
520 args[PARAM_OFFSET] = 0;
521 args[PARAM_RID] = rec.doc_id();
522 pic.parentNode.setAttribute("href", buildOPACLink(args));
524 unHideMe($n(r,'place_hold_span'));
525 $n(r,'place_hold_link').setAttribute(
526 'href','javascript:holdsDrawEditor({record:"'+rec.doc_id()+'",type:"T"});');
528 var here = findOrgUnit(getLocation());
529 if (findOrgType(here.ou_type()).can_have_vols()) { // show the callnumber list
530 dojo.require('openils.BibTemplate');
531 var l_cn_list = $n(r,'local_callnumber_list');
532 var onlyrec = rec.doc_id();
537 new openils.BibTemplate({
539 record : '' + onlyrec + '[10]',
540 org_unit : here.shortname()
547 buildSearchLink(STYPE_AUTHOR, rec.author(), author_link);
551 if(!isNull(rec.edition())) {
552 unHideMe( $n(r, "result_table_extra_span"));
553 $n(r, "result_table_edition_span").appendChild( text( rec.edition()) );
555 if(!isNull(rec.pubdate())) {
556 unHideMe( $n(r, "result_table_extra_span"));
557 unHideMe($n(r, "result_table_pub_span"));
558 $n(r, "result_table_pub_span").appendChild( text( rec.pubdate() ));
560 if(!isNull(rec.publisher()) ) {
561 unHideMe( $n(r, "result_table_extra_span"));
562 unHideMe($n(r, "result_table_pub_span"));
563 $n(r, "result_table_pub_span").appendChild( text( " " + rec.publisher() ));
566 if(!isNull(rec.physical_description()) ) {
567 unHideMe( $n(r, "result_table_extra_span"));
568 var t = " " + rec.physical_description();
569 //$n(r, "result_table_phys_span").appendChild( text(t.replace(/:.*/g,'')));
570 $n(r, "result_table_phys_span").appendChild( text(t));
575 resultBuildFormatIcons( r, rec, is_mr );
579 runEvt("result", "recordDrawn", rec.doc_id(), title_link);
582 if(resultPageIsDone()) {
583 runEvt('result', 'allRecordsReceived', recordsCache);
588 function _resultFindRec(id) {
589 for( var i = 0; i != recordsCache.length; i++ ) {
590 var rec = recordsCache[i];
591 if( rec && rec.doc_id() == id )
598 function resultBuildFormatIcons( row, rec, is_mr ) {
600 var ress = rec.types_of_resource();
602 for( var i in ress ) {
607 var link = $n(row, res + "_link");
609 var img = link.getElementsByTagName("img")[0];
610 removeCSSClass( img, config.css.dim );
614 if( f == modsFormatToMARC(res) )
615 addCSSClass( img, "dim2_border");
619 args[PARAM_OFFSET] = 0;
623 args[PARAM_TFORM] = modsFormatToMARC(res);
624 args[PARAM_MRID] = rec.doc_id();
628 args[PARAM_RID] = rec.doc_id();
631 link.setAttribute("href", buildOPACLink(args));
636 function fetchGoogleBooksLink () {
637 if (isbnList && googleBooksLink) {
638 var scriptElement = document.createElement("script");
639 scriptElement.setAttribute("id", "jsonScript");
640 scriptElement.setAttribute("src",
641 "http://books.google.com/books?bibkeys=" +
642 escape(isbnList) + "&jscmd=viewapi&callback=unhideGoogleBooksLink");
643 scriptElement.setAttribute("type", "text/javascript");
644 // make the request to Google Book Search
645 document.documentElement.firstChild.appendChild(scriptElement);
649 function resultPageIsDone(pos) {
651 return (recordsHandled == getDisplayCount()
652 || recordsHandled + getOffset() == getHitCount());
655 var resultCCHeaderApplied = false;
657 /* -------------------------------------------------------------------- */
658 /* dynamically add the copy count rows based on the org type 'countsrow'
659 is the row into which we will add TD's to hold the copy counts
660 This code generates copy count cells with an id of
661 'copy_count_cell_<depth>_<pagePosition>' */
662 function resultAddCopyCounts(rec, pagePosition) {
664 var r = table.rows[pagePosition + 1];
665 var countsrow = $n(r, config.names.result.counts_row );
666 var ccell = $n(countsrow, config.names.result.count_cell);
668 var nodes = orgNodeTrail(findOrgUnit(getLocation()));
670 var type = findOrgType(node.ou_type());
671 ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
672 ccell.title = type.opac_label();
673 //addCSSClass(ccell, config.css.result.cc_cell_even);
675 var lastcell = ccell;
676 var lastheadcell = null;
679 var ccheadcell = null;
680 if(!resultCCHeaderApplied && !getLasso()) {
681 ccrow = $('result_thead_row');
682 ccheadcell = ccrow.removeChild($n(ccrow, "result_thead_ccell"));
683 var t = ccheadcell.cloneNode(true);
685 t.appendChild(text(type.opac_label()));
686 ccrow.appendChild(t);
687 resultCCHeaderApplied = true;
693 var d = findOrgDepth(nodes[1]);
694 var d2 = findOrgDepth(nodes[nodes.length -1]);
696 for( var i = d; i <= d2 ; i++ ) {
698 ccell = ccell.cloneNode(true);
700 //if((i % 2)) removeCSSClass(ccell, "copy_count_cell_even");
701 //else addCSSClass(ccell, "copy_count_cell_even");
703 var node = nodes[x++];
704 var type = findOrgType(node.ou_type());
706 ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
707 ccell.title = type.opac_label();
708 countsrow.insertBefore(ccell, lastcell);
712 var t = ccheadcell.cloneNode(true);
713 t.appendChild(text(type.opac_label()));
714 ccrow.insertBefore(t, lastheadcell);
720 unHideMe($("search_info_table"));
723 /* collect copy counts for a record using method 'methodName' */
724 function resultCollectCopyCounts(rec, pagePosition, methodName) {
725 if(rec == null || rec.doc_id() == null) return;
727 var loc = getLasso();
729 else loc= getLocation();
731 var req = new Request(methodName, loc, rec.doc_id(), getForm() );
732 req.request.userdata = [ rec, pagePosition ];
733 req.callback(resultHandleCopyCounts);
737 function resultHandleCopyCounts(r) {
738 runEvt('result', 'copyCountsReceived', r.userdata[0], r.userdata[1], r.getResultObject());
742 /* XXX Needs to understand Lasso copy counts... */
743 /* display the collected copy counts */
744 function resultDisplayCopyCounts(rec, pagePosition, copy_counts) {
745 if(copy_counts == null || rec == null) return;
748 var copy_counts_lasso = {
754 org_unit : getLasso()
757 for (var i in copy_counts) {
758 copy_counts_lasso.transcendant = copy_counts[i].transcendant;
759 copy_counts_lasso.count += parseInt(copy_counts[i].count);
760 copy_counts_lasso.unshadow += parseInt(copy_counts[i].unshadow);
761 copy_counts_lasso.available += parseInt(copy_counts[i].available);
764 copy_counts = [ copy_counts_lasso ];
768 while(copy_counts[i] != null) {
769 var cell = $("copy_count_cell_" + i +"_" + pagePosition);
770 var cts = copy_counts[i];
771 cell.appendChild(text(cts.available + " / " + cts.count));
774 /* here we style opac-invisible records for xul */
776 if( cts.depth == 0 ) {
777 if(cts.transcendant == null && cts.unshadow == 0) {
778 _debug("found an opac-shadowed record: " + rec.doc_id());
779 var row = cell.parentNode.parentNode.parentNode.parentNode.parentNode;
781 addCSSClass( row, 'no_copies' );
783 addCSSClass( row, 'shadowed' );