holds are coming along
[Evergreen.git] / Open-ILS / web / opac / skin / default / js / result_common.js
1
2 var recordsHandled = 0;
3 var recordsCache = [];
4
5 /* set up the event handlers */
6 G.evt.result.hitCountReceived.push(resultSetHitInfo);
7 G.evt.result.recordReceived.push(resultDisplayRecord, resultAddCopyCounts);
8 G.evt.result.copyCountsReceived.push(resultDisplayCopyCounts);
9 G.evt.result.allRecordsReceived.push(resultBuildCaches, resultDrawSubjects, resultDrawAuthors, resultDrawSeries);
10
11 /* do this after we have ID's so the rank for mr pages will be correct */
12 attachEvt("result", "preCollectRecords", resultPaginate);
13
14 /* returns the last 'index' postion ocurring in this page */
15 function resultFinalPageIndex() {
16         if(getHitCount() < (getOffset() + getDisplayCount())) 
17                 return getHitCount() - 1;
18         return getOffset() + getDisplayCount() - 1;
19 }
20
21 /* set the search result info, number of hits, which results we're 
22         displaying, links to the next/prev pages, etc. */
23 function resultSetHitInfo() { 
24         var c;  
25         if( getDisplayCount() > (getHitCount() - getOffset()))  c = getHitCount();
26         else c = getDisplayCount() + getOffset();
27
28         var pages = getHitCount() / getDisplayCount();
29         if(pages % 1) pages = parseInt(pages) + 1;
30
31         G.ui.result.current_page.appendChild(text( (getOffset()/getDisplayCount()) + 1));
32         G.ui.result.num_pages.appendChild(text(pages + ")")); /* the ) is dumb */
33
34         G.ui.result.offset_start.appendChild(text(getOffset() + 1));
35         G.ui.result.offset_end.appendChild(text(c));
36         G.ui.result.result_count.appendChild(text(getHitCount()));
37         unHideMe(G.ui.result.info);
38 }
39
40
41 function resultPaginate() {
42         var o = getOffset();
43
44         if( !((o + getDisplayCount()) >= getHitCount()) ) {
45
46                 var args = {};
47                 args[PARAM_OFFSET] = o + getDisplayCount();
48                 G.ui.result.next_link.setAttribute("href", buildOPACLink(args)); 
49                 addCSSClass(G.ui.result.next_link, config.css.result.nav_active);
50
51                 args[PARAM_OFFSET] = getHitCount() - (getHitCount() % getDisplayCount());
52                 G.ui.result.end_link.setAttribute("href", buildOPACLink(args)); 
53                 addCSSClass(G.ui.result.end_link, config.css.result.nav_active);
54         }
55
56         if( o > 0 ) {
57
58                 var args = {};
59                 args[PARAM_OFFSET] = o - getDisplayCount();
60                 G.ui.result.prev_link.setAttribute( "href", buildOPACLink(args)); 
61                 addCSSClass(G.ui.result.prev_link, config.css.result.nav_active);
62
63                 args[PARAM_OFFSET] = 0;
64                 G.ui.result.home_link.setAttribute( "href", buildOPACLink(args)); 
65                 addCSSClass(G.ui.result.home_link, config.css.result.nav_active);
66         }
67         if(getDisplayCount() < getHitCount())
68                 unHideMe($('start_end_links_span'));
69 }
70
71
72 /* display the record info in the record display table 'pos' is the 
73                 zero based position the record should have in the display table */
74 function resultDisplayRecord(rec, pos, is_mr) {
75
76         if(rec == null) rec = new mvr(); /* so the page won't die if there was an error */
77         recordsHandled++;
78         recordsCache.push(rec);
79
80         var r = table.rows[pos + 1];
81         
82         try {
83                 var rank = parseFloat(ranks[pos + getOffset()]);
84                 rank = ( rank / getTopRank() ) * 100;
85                 rank = parseInt(rank) + "%";
86                 var relspan = $n(r, "relevancy_span");
87                 relspan.appendChild(text(rank));
88                 unHideMe(relspan.parentNode);
89         } catch(e){ }
90
91         var pic = $n(r, config.names.result.item_jacket);
92         pic.setAttribute("src", buildISBNSrc(cleanISBN(rec.isbn())));
93
94         var title_link = $n(r, config.names.result.item_title);
95         var author_link = $n(r, config.names.result.item_author);
96
97         if( is_mr )  {
98                 var onlyrec = onlyrecord[ getOffset() + pos ];
99                 if(onlyrec) {
100                         var args = {};
101                         args.page = RDETAIL;
102                         args[PARAM_OFFSET] = 0;
103                         args[PARAM_RID] = onlyrec;
104                         args[PARAM_MRID] = rec.doc_id();
105                         pic.parentNode.setAttribute("href", buildOPACLink(args));
106                         title_link.setAttribute("href", buildOPACLink(args));
107                         title_link.appendChild(text(normalize(truncate(rec.title(), 65))));
108                         
109                 } else {
110                         buildTitleLink(rec, title_link); 
111                         var args = {};
112                         args.page = RRESULT;
113                         args[PARAM_OFFSET] = 0;
114                         args[PARAM_MRID] = rec.doc_id();
115                         pic.parentNode.setAttribute("href", buildOPACLink(args));
116                 }
117
118         } else {
119                 buildTitleDetailLink(rec, title_link); 
120                 var args = {};
121                 args.page = RDETAIL;
122                 args[PARAM_OFFSET] = 0;
123                 args[PARAM_RID] = rec.doc_id();
124                 pic.parentNode.setAttribute("href", buildOPACLink(args));
125
126                 unHideMe($n(r,'place_hold_span'));
127                 $n(r,'place_hold_link').setAttribute(
128                         'href','javascript:resultDrawHoldsWindow("'+rec.doc_id()+'");');
129         }
130
131         buildSearchLink(STYPE_AUTHOR, rec.author(), author_link);
132
133         if(! is_mr ) {
134         
135                 if(!isNull(rec.edition()))      {
136                         unHideMe( $n(r, "result_table_extra_span"));
137                         $n(r, "result_table_edition_span").appendChild( text( rec.edition()) );
138                 }
139                 if(!isNull(rec.pubdate())) {
140                         unHideMe( $n(r, "result_table_extra_span"));
141                         unHideMe($n(r, "result_table_pub_span"));
142                         $n(r, "result_table_pub_span").appendChild( text( rec.pubdate() ));
143                 }
144                 if(!isNull(rec.publisher()) ) {
145                         unHideMe( $n(r, "result_table_extra_span"));
146                         unHideMe($n(r, "result_table_pub_span"));
147                         $n(r, "result_table_pub_span").appendChild( text( " " + rec.publisher() ));
148                 }
149         }
150
151         resultBuildFormatIcons( r, rec );
152
153         unHideMe(r);
154         
155         runEvt("result", "recordDrawn", rec.doc_id(), title_link);
156
157         if(resultPageIsDone())  {
158                 /* hide the 'now loading...' message */
159                 /*
160                 hideMe(G.ui.common.loading);
161                 */
162                 runEvt('result', 'allRecordsReceived', recordsCache);
163         }
164 }
165
166 function _resultFindRec(id) {
167         for( var i = 0; i != recordsCache.length; i++ ) {
168                 var rec = recordsCache[i];
169                 if( rec && rec.doc_id() == id )
170                         return rec;
171         }
172         return null;
173 }
174
175 var currentHoldRecord;
176 var holdsOrgSelectorBuilt = false;
177 function resultDrawHoldsWindow(recid) {
178
179         if(recid == null) {
180                 recid = currentHoldRecord;
181                 if(recid == null) return;
182         }
183         currentHoldRecord = recid;
184
185         if(!(G.user && G.user.session)) {
186
187                 attachEvt('common','loggedIn', resultDrawHoldsWindow)
188                 initLogin();
189                 return;
190         }
191         swapCanvas($('holds_box'));
192
193         var rec = _resultFindRec(recid);
194
195         if(!holdsOrgSelectorBuilt) {
196                 resultBuildHoldsSelector(null, 0);
197                 holdsOrgSelectorBuilt = true;
198         }
199
200         removeChildren($('holds_title'));
201         removeChildren($('holds_author'));
202         removeChildren($('holds_format'));
203         removeChildren($('holds_email'));
204         removeChildren($('holds_email'));
205
206         $('holds_title').appendChild(text(rec.title()));
207         $('holds_author').appendChild(text(rec.author()));
208
209         for( var i in rec.types_of_resource() ) {
210                 var res = rec.types_of_resource()[i];
211                 var img = elem("img");
212                 setResourcePic(img, res);
213                 $('holds_format').appendChild(text(' '+res+' '));
214                 $('holds_format').appendChild(img);
215                 $('holds_format').appendChild(text(' '));
216         }
217
218         $('holds_phone').appendChild(text(G.user.day_phone()));
219         $('holds_email').appendChild(text(G.user.email()));
220         $('holds_cancel').onclick = showCanvas;
221         $('holds_submit').onclick = resultPlaceHold; 
222 }
223
224
225 function resultBuildHoldsSelector(node, depth) {
226
227         if(!node) {
228                 node = globalOrgTree;
229                 depth = 0;
230         }
231
232         var selector = $('holds_org_selector');
233         var index = selector.options.length;
234
235         if(IE) {
236                 var pre = elem("pre");
237                 for(var x=2; x <= findOrgType(node.ou_type()).depth(); x++) {
238                         pre.appendChild(text("    "));
239                 }
240                 pre.appendChild(text(node.name()));
241                 var select = new Option("", node.id());
242                 selector.options[index] = select;
243                 select.appendChild(pre);
244         
245         } else {
246                 var pad = (findOrgType(node.ou_type()).depth() - 1) * 12;
247                 var select = new Option(node.name(), node.id());
248                 select.setAttribute("style", "padding-left: " + pad);
249                 selector.options[index] = select;
250         }       
251
252         if( node.id() == getLocation() ) {
253                 selector.selectedIndex = index;
254                 selector.options[index].selected = true;        
255         }
256
257         for( var i in node.children() ) {
258                 var child = node.children()[i];
259                 if(child) {
260                         resultBuildHoldsSelector(child, depth+1);
261                 }
262         }
263 }
264
265 function resultPlaceHold() {
266         //alert("placing hold for " + currentHoldRecord );
267
268         var hold = new ahr();
269         hold.pickup_lib( 1 ); /* */
270         hold.requestor(G.user.id());
271         hold.usr(G.user.id());
272         hold.hold_type('T');
273         hold.email_notify(G.user.email());
274         hold.phone_notify(G.user.day_phone());
275         hold.target(currentHoldRecord);
276         
277         var req = new Request( CREATE_HOLD, G.user.session, hold );
278         req.send(true);
279         var res = req.result();
280
281         /* XMLize me */
282         if( res == '1' ) {
283                 alert('ok');
284         } else {
285                 alert('hold failed');
286         }
287 }
288
289
290
291 function resultBuildFormatIcons( row, rec ) {
292
293         var ress = rec.types_of_resource();
294
295         for( var i in ress ) {
296
297                 var res = ress[i];
298                 var link = $n(row, res + "_link");
299                 link.title = res;
300                 var img = link.getElementsByTagName("img")[0];
301                 removeCSSClass( img, config.css.dim );
302
303                 var f = getForm();
304                 if( f != "all" ) {
305                         /*
306                         if( f != modsFormatToMARC(res) ) 
307                                 addCSSClass( img, config.css.dim2);
308                         else
309                                 addCSSClass( img, "dim2_border");
310                                 */
311                         if( f == modsFormatToMARC(res) ) 
312                                 addCSSClass( img, "dim2_border");
313                 }
314
315
316                 var args = {};
317                 args.page = RRESULT;
318                 args[PARAM_OFFSET] = 0;
319                 args[PARAM_MRID] = rec.doc_id();
320                 args[PARAM_FORM] = modsFormatToMARC(res);
321
322                 link.setAttribute("href", buildOPACLink(args));
323
324         }
325
326 }
327
328
329 function resultPageIsDone(pos) {
330         return (recordsHandled == getDisplayCount() 
331                 || recordsHandled + getOffset() == getHitCount());
332 }
333
334 var resultCCHeaderApplied = false;
335
336 /* -------------------------------------------------------------------- */
337 /* dynamically add the copy count rows based on the org type 'countsrow' 
338         is the row into which we will add TD's to hold the copy counts 
339         This code generates copy count cells with an id of
340         'copy_count_cell_<depth>_<pagePosition>'  */
341 function resultAddCopyCounts(rec, pagePosition) {
342
343         var r = table.rows[pagePosition + 1];
344         var countsrow = $n(r, config.names.result.counts_row );
345         var ccell = $n(countsrow, config.names.result.count_cell);
346
347         var nodes = orgNodeTrail(findOrgUnit(getLocation()));
348         var node = nodes[0];
349         var type = findOrgType(node.ou_type());
350         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
351         ccell.title = type.opac_label();
352         //addCSSClass(ccell, config.css.result.cc_cell_even);
353
354         var lastcell = ccell;
355         var lastheadcell = null;
356
357         var cchead = null;
358         var ccheadcell = null;
359         if(!resultCCHeaderApplied) {
360                 ccrow = $('result_thead_row');
361                 ccheadcell =  ccrow.removeChild($n(ccrow, "result_thead_ccell"));
362                 var t = ccheadcell.cloneNode(true);
363                 lastheadcell = t;
364                 t.appendChild(text(type.opac_label()));
365                 ccrow.appendChild(t);
366                 resultCCHeaderApplied = true;
367         }
368
369         if(nodes[1]) {
370
371                 var x = 1;
372                 var d = findOrgDepth(nodes[1]);
373                 var d2 = findOrgDepth(nodes[nodes.length -1]);
374
375                 for( var i = d; i <= d2 ; i++ ) {
376         
377                         ccell = ccell.cloneNode(true);
378
379                         //if((i % 2)) removeCSSClass(ccell, "copy_count_cell_even");
380                         //else addCSSClass(ccell, "copy_count_cell_even");
381
382                         var node = nodes[x++];
383                         var type = findOrgType(node.ou_type());
384         
385                         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
386                         ccell.title = type.opac_label();
387                         countsrow.insertBefore(ccell, lastcell);
388                         lastcell = ccell;
389
390                         if(ccheadcell) {
391                                 var t = ccheadcell.cloneNode(true);
392                                 t.appendChild(text(type.opac_label()));
393                                 ccrow.insertBefore(t, lastheadcell);
394                                 lastheadcell = t;
395                         }
396                 }
397         }
398
399         unHideMe($("search_info_table"));
400 }
401
402 /* collect copy counts for a record using method 'methodName' */
403 function resultCollectCopyCounts(rec, pagePosition, methodName) {
404         if(rec == null || rec.doc_id() == null) return;
405         var req = new Request(methodName, getLocation(), rec.doc_id(), getForm() );
406         req.request.userdata = [ rec, pagePosition ];
407         req.callback(resultHandleCopyCounts);
408         req.send();
409 }
410
411 function resultHandleCopyCounts(r) {
412         runEvt('result', 'copyCountsReceived', r.userdata[0], r.userdata[1], r.getResultObject()); 
413 }
414
415
416 /* display the collected copy counts */
417 function resultDisplayCopyCounts(rec, pagePosition, copy_counts) {
418         if(copy_counts == null || rec == null) return;
419         var i = 0;
420         while(copy_counts[i] != null) {
421                 var cell = $("copy_count_cell_" + i +"_" + pagePosition);
422                 /*
423                 var span = cell.getElementsByTagName("div")[0];
424                 */
425                 cell.appendChild(text(copy_counts[i].available + " / " + copy_counts[i].count));
426
427                 i++;
428         }
429 }
430
431
432 /* captures extraneous info from each record */
433
434 var subjectCache = {};
435 var authorCache = {};
436 var seriesCache = {};
437
438 function resultBuildCaches(records) {
439         for( var r in records ) {
440                 var rec = records[r];
441                 for( var s in rec.subject() ) 
442                         subjectCache[s] == null ? subjectCache[s] = 1 : subjectCache[s]++;
443                 authorCache[rec.author()] = 1;
444                 for( var s in rec.series() ) seriesCache[rec.series()[s]] = 1;
445         }
446 }
447
448 function resultSortSubjects(a, b) { return -(a.count - b.count); } /* sort in reverse */
449 function resultDrawSubjects() {
450
451         var subjs = [];
452         for( var s in subjectCache )
453                 subjs.push( { sub : s, count : subjectCache[s] } );
454         subjs.sort(resultSortSubjects);
455
456         var ss = [];
457         for( var s in subjs ) ss.push(subjs[s].sub);
458
459         resultDrawSidebarTrees( 
460                 STYPE_SUBJECT, 
461                 "subjectSidebarTree", ss, 
462                 $("subject_tree_sidebar"), 
463                 $("subject_sidebar_tree_div") );
464 }
465
466 function resultDrawAuthors() {
467         var auths = new Array();
468         for( var s in authorCache ) auths.push(s);
469
470         resultDrawSidebarTrees( 
471                 STYPE_AUTHOR, 
472                 "authorSidebarTree", auths.sort(), 
473                 $("author_tree_sidebar"), 
474                 $("author_sidebar_tree_div") );
475 }
476
477 function resultDrawSeries() {
478         var sers = new Array();
479         for( var s in seriesCache ) sers.push(s);
480         resultDrawSidebarTrees( 
481                 STYPE_SERIES, 
482                 "seriesSidebarTree", sers.sort(), 
483                 $("series_tree_sidebar"), 
484                 $("series_sidebar_tree_div") );
485 }
486
487 function resultDrawSidebarTrees( stype, treeName, items, wrapperNode, destNode ) {
488         var tree;
489         eval("tree = " + treeName);
490
491         var found = false;
492         var x = 0;
493         for( var i in items ) {
494
495                 if(isNull(items[i])) continue;
496                 if(x++ > 7) break;
497                 found = true;
498
499                 var item = normalize(truncate(items[i], 65));
500                 var trunc = 65;
501                 var args = {};
502                 var href = resultQuickLink( items[i], stype );
503                 tree.addNode( stype + "_" + items[i], treeName + 'Root', item, href );
504
505                 /*
506                 if(!IE)
507                         setTimeout('resultFireXRefReq("'+treeName+'","'+stype+'","'+item+'");',200);
508                         */
509                 if(!IE) resultFireXRefReq(treeName, stype, items[i]);
510         }
511
512         if(found) {
513                 unHideMe(wrapperNode);
514                 //tree.close(tree.rootid);
515         }
516 }
517
518 function resultFireXRefReq( treeName, stype, item ) {
519         var tree;
520         eval('tree=' + treeName);
521         var req = new Request(FETCH_CROSSREF, stype, item);
522         req.request._tree = tree;
523         req.request._item = item;
524         req.request._stype = stype;
525         req.callback(resultAppendCrossRef);
526         req.send();
527 }
528
529
530 function resultQuickLink( term, type ) {
531         var args = {};
532         args.page = MRESULT;
533         args[PARAM_OFFSET] = 0;
534         args[PARAM_TERM] = term;
535         args[PARAM_STYPE] = type;
536         return buildOPACLink(args);
537 }
538
539
540 function resultAppendCrossRef(r) {
541         var tree                = r._tree
542         var item                = r._item
543         var stype       = r._stype;
544         var result      = r.getResultObject();
545         if(!result) return;
546         var froms       = result['from'];
547         var alsos       = result['also'];
548
549         var total = 0;
550
551         for( var i = 0; (total++ < 5 && i < froms.length); i++ ) {
552                 var string = normalize(truncate(froms[i], 45));
553                 if($(stype + '_' + froms[i])) continue;
554                 tree.addNode(stype + '_' + froms[i], 
555                         stype + '_' + item, string, resultQuickLink(froms[i],stype));
556         }
557         for( var i = 0; (total++ < 10 && i < alsos.length); i++ ) {
558                 var string = normalize(truncate(alsos[i], 45));
559                 if($(stype + '_' + alsos[i])) continue;
560                 tree.addNode(stype + '_' + alsos[i], 
561                         stype + '_' + item, string, resultQuickLink(alsos[i],stype));
562         }
563 }
564
565
566
567
568