1 var globalRecordDetailPage = null;
2 RecordDetailPage.prototype = new Page();
3 RecordDetailPage.prototype.constructor = RecordDetailPage;
4 RecordDetailPage.baseClass = Page.constructor;
6 var globalDetailRecord;
8 function RecordDetailPage() {
9 if( globalRecordDetailPage != null )
10 return globalRecordDetailPage;
11 this.searchBar = new SearchBarChunk();
14 RecordDetailPage.prototype.setPageTrail = function() {
15 var box = getById("page_trail");
18 var d = this.buildTrailLink("start",true);
22 d = this.buildTrailLink("advanced_search",true);
27 var b = this.buildTrailLink("mr_result", true);
30 box.appendChild(this.buildDivider());
34 box.appendChild(this.buildDivider());
36 box.appendChild(this.buildTrailLink("record_result", true));
37 } catch(E) {} /* doesn't work when deep linking */
39 box.appendChild(this.buildDivider());
41 this.buildTrailLink("record_detail",false));
45 RecordDetailPage.prototype.buildContextMenu = function(record) {
47 var menu_name = "record_detail_menu";
48 var menu = globalMenuManager.buildMenu(menu_name);
50 globalMenuManager.setContext(getById("record_detail_main_box"), menu);
51 var func = buildViewMARCWindow(record);
52 menu.addItem("View MARC", func);
55 xulEvtRecordDetailDisplayed( menu, record );
56 getDocument().body.appendChild(menu.getNode());
60 RecordDetailPage.instance = function() {
61 if( globalRecordDetailPage != null )
62 return globalRecordDetailPage;
63 return new RecordDetailPage();
66 RecordDetailPage.prototype.init = function() {
67 debug("Initing RecordDetailPage");
71 RecordDetailPage.prototype.draw = function() {
73 this.mainBox = getById("record_detail_copy_info");
75 this.copyLocationTree = elem("select");
77 "Select a location whose Volumes/Copies you wish to see");
78 this.copyLocationTree.options[this.copyLocationTree.options.length] = opt;
79 var tree = this.copyLocationTree;
83 tree.onchange = function() {
85 var idx = tree.selectedIndex;
86 debug("INDEX is " + idx);
87 var org_id = tree.options[idx].value;
88 if(org_id == null) return;
89 obj.drawCopyTrees(findOrgUnit(org_id), obj.record);
91 tree.selectedIndex = idx;
92 var opt = tree.options[idx];
93 if(opt) opt.selected = true;
95 obj.displayParentLink(findOrgUnit(org_id), obj.record);
99 var table = elem("table", { width: "100%" } );
100 table.width = "100%";
102 var linksDiv = table.insertRow(0);
103 var leftLink = linksDiv.insertCell(0);
104 var rightLink = linksDiv.insertCell(1);
106 leftLink.width = "50%";
107 rightLink.width = "50%";
108 leftLink.align = "left";
109 rightLink.align = "right";
111 this.parentLink = elem("a",
112 { href : "javascript:void(0)",
114 style : "text-decoration:underline" } );
116 leftLink.appendChild(this.copyLocationTree);
117 rightLink.appendChild(this.parentLink);
118 this.mainBox.appendChild(table);
119 /* --------------------------------------------- */
122 this.treeDiv = elem("div");
123 this.mainBox.appendChild(this.treeDiv);
125 this.fetchRecord(paramObj.__record); /* sets this.record */
126 this.viewMarc = getById("record_detail_view_marc");
134 RecordDetailPage.prototype.buildCustomOrgTree = function(record) {
136 var req = new RemoteRequest(
138 "open-ils.search.biblio.copy_counts.retrieve",
142 req.setCompleteCallback(
144 _fleshOrgTree(req.getResultObject(), obj.copyLocationTree);}
146 debug("Sending copy tree request");
150 /* builds the select list with the appropriate org units */
151 function _fleshOrgTree(org_array, selector) {
153 debug("Fleshing org tree selector with " + org_array);
155 for( var idx in org_array ) {
156 var slot = org_array[idx];
157 var org = findOrgUnit(slot[0]);
158 _addOrgAndParents(selector, org);
161 /* clear out the state flags we added after the tree is built */
162 setTimeout(function(){_clearOrgFlags();}, 500);
164 debug("Tree is built..");
167 function _clearOrgFlags(node) {
169 node = globalOrgTree;
171 for(var c in node.children())
172 _clearOrgFlags(node.children()[c]);
176 function _addOrgAndParents(selector, org) {
178 if(!org || org.added) return;
180 debug("Checking org " + org.name());
182 if(org.ou_type() == "1") {
187 var par = findOrgUnit(org.parent_ou());
188 if(par && !par.added)
189 _addOrgAndParents(selector, par);
192 /* build the selector text part */
194 var node = elem("pre");
195 for(var x=2; x <= findOrgType(org.ou_type()).depth(); x++) {
196 node.appendChild(mktext(" "));
198 node.appendChild(mktext(org.name()));
200 var select = new Option("", org.id());
201 selector.options[selector.options.length] = select;
202 select.appendChild(node);
206 var pad = (findOrgType(org.ou_type()).depth() - 1) * 10;
207 var select = new Option(org.name(), org.id());
208 select.setAttribute("style", "padding-left: " + pad);
209 selector.options[selector.options.length] = select;
216 function _buildCustomOrgTree(org_node, root) {
221 item = new WebFXTree(org_node.name());
222 item.setBehavior('classic');
224 item = new WebFXTreeItem(org_node.name());
228 "javascript:globalPage.drawCopyTrees(" +
229 org_node.id() + ", logicNode.globalDetailRecord );" +
230 "globalPage.copyLocationTree.hide();";
233 for( var index in org_node.children()) {
234 var childorg = org_node.children()[index];
235 if( childorg != null ) {
236 var tree_node = buildCustomOrgTree(childorg);
237 if(tree_node != null)
246 RecordDetailPage.prototype.setViewMarc = function(record) {
247 var marcb = elem( "a",
248 { href:"javascript:void(0)",
249 style: "text-decoration:underline;color:#EFF;" },
252 debug(".ou_type()Setting up view marc callback with record " + record.doc_id());
254 var func = buildViewMARCWindow(record);
255 marcb.onclick = func;
256 this.viewMarc.appendChild(marcb);
259 RecordDetailPage.prototype.setPlaceHold = function(record) {
260 var holds = elem( "a",
262 href:"javascript:void(0)",
263 style: "text-decoration:underline;color:#EFF;"
267 var user = UserSession.instance();
269 if(user.verifySession()) {
270 win = new HoldsWindow(record.doc_id(),
271 "T", user.userObject, user.userObject, user.session_id);
273 win = new HoldsWindow(record.doc_id(),
274 "T", null, null, null);
276 holds.onclick = function() { win.toggle(holds); }
278 var space = elem("span", {style:"padding:5px"},null, " ");
279 this.viewMarc.appendChild(space);
280 this.viewMarc.appendChild(holds);
284 RecordDetailPage.prototype.fetchRecord = function(id) {
286 debug("No ID in fetchRecord");
290 var req = new RemoteRequest(
292 "open-ils.search.biblio.record.mods_slim.retrieve",
296 req.setCompleteCallback(
298 obj.record = req.getResultObject();
299 globalDetailRecord = obj.record;
300 obj.buildCustomOrgTree(obj.record);
301 obj.drawRecord(obj.record);
302 obj.setViewMarc(obj.record);
303 obj.setPlaceHold(obj.record);
311 RecordDetailPage.prototype.drawRecord = function(record) {
313 var title_cell = getById("record_detail_title_cell");
314 var author_cell = getById("record_detail_author_cell");
315 var isbn_cell = getById("record_detail_isbn_cell");
317 var edition_cell = getById("record_detail_edition_cell");
318 var pubdate_cell = getById("record_detail_pubdate_cell");
319 var publisher_cell = getById("record_detail_publisher_cell");
321 var subject_cell = getById("record_detail_subject_cell");
322 var tcn_cell = getById("record_detail_tcn_cell");
323 var resource_cell = getById("record_detail_resource_cell");
324 var pic_cell = getById("record_detail_pic_cell");
325 var abstract_cell = getById("record_detail_abstract_cell");
327 add_css_class(title_cell, "detail_item_cell");
328 add_css_class(author_cell, "detail_item_cell");
329 add_css_class(isbn_cell, "detail_item_cell");
330 add_css_class(edition_cell, "detail_item_cell");
331 add_css_class(pubdate_cell, "detail_item_cell");
332 add_css_class(publisher_cell, "detail_item_cell");
333 add_css_class(subject_cell, "detail_item_cell");
334 add_css_class(tcn_cell, "detail_item_cell");
335 add_css_class(resource_cell, "detail_item_cell");
336 add_css_class(abstract_cell, "detail_item_cell");
338 title_cell.appendChild(
339 createAppTextNode(normalize(record.title())));
340 author_cell.appendChild(
341 createAppTextNode(normalize(record.author())));
342 isbn_cell.appendChild(
343 createAppTextNode(record.isbn()));
345 edition_cell.appendChild(
346 createAppTextNode(record.edition()));
347 pubdate_cell.appendChild(
348 createAppTextNode(record.pubdate()));
349 publisher_cell.appendChild(
350 createAppTextNode(record.publisher()));
352 subject_cell.appendChild(
353 createAppTextNode(record.subject()));
354 tcn_cell.appendChild(
355 createAppTextNode(record.tcn()));
357 var abs = record.synopsis();
358 if(abs == null || abs == "") abs = "N/A";
359 abstract_cell.appendChild(mktext(abs));
363 var resource = record.types_of_resource()[0];
364 if(resource.indexOf("sound recording") != -1)
365 resource = "sound recording";
366 var r_pic = elem("img",
367 { src: "/images/" + resource + ".jpg" } );
368 resource_cell.appendChild(r_pic);
369 resource_cell.appendChild(createAppTextNode(" "));
371 resource_cell.appendChild(
372 createAppTextNode(record.types_of_resource()));
374 pic_cell.appendChild(this.mkImage(record));
377 var locs = record.online_loc();
378 if(locs && locs.length > 0){
379 var tab = pic_cell.parentNode.parentNode;
380 var loc_row = tab.insertRow(tab.rows.length);
381 var desc_cell =loc_row.insertCell(0);
382 add_css_class(desc_cell, "detail_item_label");
383 desc_cell.appendChild(mktext("Other Resources"));
384 var links_cell =loc_row.insertCell(1);
386 var found = new Array(); /* weed out duplicates */
387 /* online location field is of the form [link, title, link, title, ...] */
388 for(var i = 0; i!= locs.length; i++ ) {
391 if(find_list(found,function(f){return (f==ref);}))
394 var a = elem("a", {style:"text-decoration:underline",
395 target:"_blank",href:ref,title:ttl}, null, ttl);
396 links_cell.appendChild(a);
397 links_cell.appendChild(mktext(" "));
401 var orgUnit = globalSelectedLocation;
402 if(!orgUnit) orgUnit = globalLocation;
404 this.drawCopyTrees(orgUnit, record);
405 this.buildContextMenu(record);
408 /* sets up the cover art image */
409 RecordDetailPage.prototype.mkImage = function(record) {
411 var isbn = record.isbn();
413 if(isbn) isbn = isbn.replace(/\s+/,"");
417 var big_pic = elem("a", {
418 href : "http://images.amazon.com/images/P/" + cleanISBN(isbn) + ".01.LZZZZZZZ.jpg",
419 title : "Click for larger image" } );
421 var img_src = buildISBNSrc(cleanISBN(record.isbn()));
422 //var img_src = "http://images.amazon.com/images/P/" +isbn + ".01.MZZZZZZZ.jpg";
423 var pic = elem ( "img", { src : img_src }, { border : "0px none" });
424 big_pic.appendChild(pic);
430 /* if sync, it is a synchronous call */
431 RecordDetailPage.prototype.grabCopyTree = function(record, orgUnit, callback, sync) {
433 var orgIds = new Array();
434 if(orgUnit.constructor == Array) {
435 for(var x = 0; x < orgUnit.length; x++) {
436 orgIds.push(orgUnit[x].id());
439 orgIds.push(orgUnit.id());
442 debug("Grabbing copy tree for " + orgIds);
444 var req = new RemoteRequest(
446 "open-ils.cat.asset.copy_tree.retrieve",
447 null, record.doc_id(), orgIds );
451 if(sync) { /* synchronous call */
453 callback(req.getResultObject());
456 req.setCompleteCallback(
457 function(r) { callback(r.getResultObject()); });
463 /* entry point for displaying the copy details pane */
464 RecordDetailPage.prototype.drawCopyTrees = function(orgUnit, record) {
466 debug("Got ORG unit " + orgUnit);
467 orgUnit = findOrgUnit(orgUnit);
468 if(orgUnit == null) return;
470 debug("OrgUnit depth is: " + findOrgType(orgUnit.ou_type()).depth());
471 removeChildren(this.treeDiv);
473 /* display a 'hold on' message */
474 this.treeDiv.appendChild(elem("br"));
475 this.treeDiv.appendChild(elem("br"));
477 var depth = parseInt(findOrgType(orgUnit.ou_type()).depth());
479 this.treeDiv.appendChild(elem("div", null, null, "Loading copy information..."));
480 if(parseInt(findOrgType(orgUnit.ou_type()).can_have_vols()))
481 this.displayParentLink(orgUnit, record);
482 this.displayTrees(orgUnit, record);
487 /* displays a link to view info for the parent org
488 if showMe == true, we don't search for the parent,
489 but use the given orgUnit as the link point */
490 RecordDetailPage.prototype.displayParentLink = function(orgUnit, record) {
492 var href = this.parentLink;
493 removeChildren(href);
494 var region = orgUnit;
495 if(region == null) return;
497 var depth = parseInt(findOrgType(region.ou_type()).depth());
499 if(depth < 2) return;
501 region = findOrgUnit(orgUnit.parent_ou());
503 href.appendChild(createAppTextNode(
504 "View Volumes/Copies for " + region.name()));
507 href.onclick = function() {
509 removeChildren(obj.treeDiv);
510 obj.treeDiv.appendChild(elem("br"));
511 obj.treeDiv.appendChild(elem("br"));
512 obj.treeDiv.appendChild(elem("div", null, null, "Loading copy information..."));
514 /* allows the above message to be displayed */
515 setTimeout(function() { obj.displayTrees(region, record, true) }, 100);
517 obj.displayParentLink(null);
520 var reg_div = createAppElement("div");
521 //reg_div.appendChild(href);
522 this.mainBox.insertBefore(reg_div, this.treeDiv);
525 /* displays copy info for orgUnit and all of it's children.
526 if orgUnit is a region (depth == 1), then we just show
527 all of our children. if it's a branch, sub-branch, etc.
528 the current branch as well as all of it's children are displayed */
529 RecordDetailPage.prototype.displayTrees = function(orgUnit, record, sync) {
531 var orgs = orgUnit.children();
534 if(parseInt(findOrgType(orgUnit.ou_type()).can_have_vols()))
535 orgs.unshift(orgUnit);
537 this.grabCopyTree(record, orgs,
539 obj.displayCopyTree(tree, "Volumes/Copies for " + orgUnit.name() );
544 /* displays a single copy tree */
545 RecordDetailPage.prototype.displayCopyTree = function(tree, title) {
547 debug("Displaying copy tree for " + title);
549 if(!globalCopyStatus) grabCopyStatus(); /* just to be safe */
551 var treeDiv = this.treeDiv;
552 removeChildren(treeDiv);
553 add_css_class( treeDiv, "copy_tree_div" );
555 var table = createAppElement("table");
556 add_css_class(table, "copy_tree_table");
557 var header_row = table.insertRow(table.rows.length);
558 add_css_class(header_row, "top_header_row");
559 var header = header_row.insertCell(header_row.cells.length);
561 header.setAttribute("colspan", 3);
562 var bold = createAppElement("b");
563 bold.appendChild(createAppTextNode(title));
564 header.appendChild(bold);
566 var row2 = table.insertRow(table.rows.length);
567 var cell1 = row2.insertCell(row2.cells.length);
568 var cell2 = row2.insertCell(row2.cells.length);
569 var cell3 = row2.insertCell(row2.cells.length);
570 var cell4 = row2.insertCell(row2.cells.length);
571 var cell5 = row2.insertCell(row2.cells.length);
573 cell1.appendChild(createAppTextNode("Library"));
574 cell2.appendChild(createAppTextNode("Callnumber"));
575 cell3.appendChild(createAppTextNode("Barcode(s)"));
576 cell4.appendChild(createAppTextNode("Location"));
577 cell5.appendChild(createAppTextNode("Availability"));
579 add_css_class(cell1, "detail_header_cell");
580 add_css_class(cell2, "detail_header_cell");
581 add_css_class(cell3, "detail_header_cell");
582 add_css_class(cell4, "detail_header_cell");
583 add_css_class(cell5, "detail_header_cell");
585 if(tree.length == 0) {
586 var row = table.insertRow(table.rows.length);
587 row.insertCell(0).appendChild(
588 createAppTextNode("No copies available for this location"));
591 var libsVisited = new Array();
593 for( var i in tree ) {
594 var row = table.insertRow(table.rows.length);
595 if(x%2) add_css_class(row, "copy_tree_row_highlight");
596 var volume = tree[i];
598 var cell1 = row.insertCell(row.cells.length);
599 add_css_class(cell1, "detail_item_cell");
602 /* here we don't want to repeat the same libs name */
603 if(find_list( libsVisited,
606 return (name == findOrgUnit(volume.owning_lib()).name()); })) {
607 cell1.appendChild(createAppTextNode(" "));
610 var name = findOrgUnit(volume.owning_lib()).name();
611 cell1.appendChild(createAppTextNode(name));
612 libsVisited.push(name);
615 var cell2 = row.insertCell(row.cells.length);
616 add_css_class(cell2, "detail_item_cell");
617 cell2.appendChild(createAppTextNode(volume.label()));
619 var cell3 = row.insertCell(row.cells.length);
620 add_css_class(cell3, "detail_item_cell");
621 cell3.appendChild(createAppTextNode(" "));
623 var cell4 = row.insertCell(row.cells.length);
624 add_css_class(cell4, "detail_item_cell");
625 cell4.appendChild(createAppTextNode(" "));
627 var cell5 = row.insertCell(row.cells.length);
628 add_css_class(cell4, "detail_item_cell");
629 cell5.appendChild(createAppTextNode(" "));
631 var copies = volume.copies();
634 while(c < copies.length) {
636 var copy = copies[c];
637 var loc = findCopyLocation(copy.location()).name();
639 if(c == 0) { /* put the first barcode in the same row as the callnumber */
641 removeChildren(cell3);
642 cell3.appendChild(createAppTextNode(copy.barcode()));
644 removeChildren(cell4);
645 cell4.appendChild(createAppTextNode(loc));
647 removeChildren(cell5);
648 var status = find_list(globalCopyStatus,
649 function(i) { return (i.id() == copy.status());} );
652 if(status) sname = status.name();
653 cell5.appendChild(createAppTextNode(sname));
657 var row = table.insertRow(table.rows.length);
658 if(x%2) add_css_class(row, "copy_tree_row_highlight");
659 row.insertCell(0).appendChild(createAppTextNode(" "));
660 row.insertCell(1).appendChild(createAppTextNode(" "));
662 var ce = row.insertCell(2);
663 var loc_cell = row.insertCell(3);
664 var status_cell = row.insertCell(4);
666 add_css_class(ce, "detail_item_cell");
667 add_css_class(loc_cell, "detail_item_cell");
668 add_css_class(status_cell, "detail_item_cell");
670 ce.appendChild(createAppTextNode(copy.barcode()));
671 loc_cell.appendChild(createAppTextNode(loc));
673 var status = find_list(globalCopyStatus,
674 function(i) { return (i.id() == copy.status());} );
676 if(status) sname = status.name();
677 status_cell.appendChild(mktext(sname))
685 treeDiv.appendChild(table);