8 /******************************************************************************************************/
9 /* setup JSAN and some initial libraries */
11 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
12 if (typeof JSAN == 'undefined') { throw( "The JSAN library object is missing."); }
13 JSAN.errorLevel = "die"; // none, warn, or die
14 JSAN.addRepository('/xul/server/');
15 JSAN.use('util.error'); g.error = new util.error();
16 g.error.sdump('D_TRACE','my_init() for cat/copy_editor.xul');
18 JSAN.use('util.functional');
19 JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
20 JSAN.use('util.network'); g.network = new util.network();
22 g.docid = xul_param('docid',{'modal_xulG':true});
23 g.handle_update = xul_param('handle_update',{'modal_xulG':true});
25 /******************************************************************************************************/
26 /* Get the copy ids from various sources and flesh them */
28 var copy_ids = xul_param('copy_ids',{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xulG':true,'JSON2js_if_xpcom':true,'stash_name':'temp_copy_ids','clear_xpcom':true,'modal_xulG':true});
29 if (!copy_ids) copy_ids = [];
31 if (copy_ids.length > 0) g.copies = g.network.simple_request(
32 'FM_ACP_FLESHED_BATCH_RETRIEVE',
36 /******************************************************************************************************/
37 /* And other fleshed copies if any */
39 if (!g.copies) g.copies = [];
40 var c = xul_param('copies',{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xpcom':true,'stash_name':'temp_copies','clear_xpcom':true,'modal_xulG':true})
41 if (c) g.copies = g.copies.concat(c);
43 /******************************************************************************************************/
44 /* We try to retrieve callnumbers for existing copies, but for new copies, we rely on this */
46 g.callnumbers = xul_param('callnumbers',{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xpcom':true,'stash_name':'temp_callnumbers','clear_xpcom':true,'modal_xulG':true});
49 /******************************************************************************************************/
50 /* Quick fix, this was defined inline in the global scope but now needs g.error and g.copies from my_init */
54 /******************************************************************************************************/
55 /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
57 if (xul_param('edit',{'modal_xulG':true}) == '1') {
59 // Editor desired, but let's check permissions
63 var check = g.network.simple_request(
64 'PERM_MULTI_ORG_CHECK',
67 g.data.list.au[0].id(),
68 util.functional.map_list(
72 var cn_id = o.call_number();
74 lib = o.circ_lib(); // base perms on circ_lib instead of owning_lib if pre-cat
76 if (! g.map_acn[ cn_id ]) {
77 var req = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
78 if (typeof req.ilsevent == 'undefined') {
79 g.map_acn[ cn_id ] = req;
80 lib = g.map_acn[ cn_id ].owning_lib();
85 lib = g.map_acn[ cn_id ].owning_lib();
91 g.copies.length == 1 ? [ 'UPDATE_COPY' ] : [ 'UPDATE_COPY', 'UPDATE_BATCH_COPY' ]
94 g.edit = check.length == 0;
96 g.error.standard_unexpected_error_alert('batch permission check',E);
100 document.getElementById('caption').setAttribute('label','Copy Editor');
101 document.getElementById('save').setAttribute('hidden','false');
102 g.retrieve_templates();
104 $('top_nav').setAttribute('hidden','true');
107 $('top_nav').setAttribute('hidden','true');
110 if (g.copies.length > 0 && g.copies[0].id() < 0) {
111 document.getElementById('copy_notes').setAttribute('hidden','true');
112 g.apply("status",5 /* In Process */);
113 $('save').setAttribute('label','Create Copies');
115 g.panes_and_field_names.left_pane =
120 render: 'typeof fm.status() == "object" ? fm.status().name() : g.data.hash.ccs[ fm.status() ].name()',
121 input: g.safe_to_edit_copy_status() ? 'c = function(v){ g.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.ccs, function(obj) { return [ obj.name(), obj.id(), typeof my_constants.magical_statuses[obj.id()] != "undefined" ? true : false ]; } ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);' : undefined,
122 //input: 'c = function(v){ g.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( util.functional.filter_list( g.data.list.ccs, function(obj) { return typeof my_constants.magical_statuses[obj.id()] == "undefined"; } ), function(obj) { return [ obj.name(), obj.id() ]; } ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
125 ].concat(g.panes_and_field_names.left_pane);
128 if (g.copies.length != 1) {
129 document.getElementById('copy_notes').setAttribute('hidden','true');
132 /******************************************************************************************************/
133 /* Show the Record Details? */
136 document.getElementById('brief_display').setAttribute(
138 urls.XUL_BIB_BRIEF + '?docid=' + g.docid
141 document.getElementById('brief_display').setAttribute('hidden','true');
144 /******************************************************************************************************/
145 /* Add stat cats to the panes_and_field_names.right_pane4 */
147 g.populate_stat_cats();
149 /******************************************************************************************************/
150 /* Backup copies :) */
152 g.original_copies = js2JSON( g.copies );
154 /******************************************************************************************************/
157 g.summarize( g.copies );
161 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
162 "system administrator or software developer the following:\ncat/copy_editor.xul\n" + E + '\n';
163 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
168 /******************************************************************************************************/
169 /* Retrieve Templates */
171 g.retrieve_templates = function() {
173 JSAN.use('util.widgets'); JSAN.use('util.functional');
175 var robj = g.network.simple_request('FM_AUS_RETRIEVE',[ses(),g.data.list.au[0].id()]);
176 if (typeof robj['staff_client.copy_editor.templates'] != 'undefined') {
177 g.templates = robj['staff_client.copy_editor.templates'];
179 util.widgets.remove_children('template_placeholder');
180 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
182 g.template_menu = util.widgets.make_menulist( list );
183 g.template_menu.setAttribute('id','template_menu');
184 $('template_placeholder').appendChild(g.template_menu);
185 g.template_menu.addEventListener(
187 function() { g.copy_editor_prefs[ 'template_menu' ] = { 'value' : g.template_menu.value }; g.save_attributes(); },
191 g.error.standard_unexpected_error_alert('Error retrieving templates',E);
195 /******************************************************************************************************/
198 g.apply_template = function() {
200 var name = g.template_menu.value;
201 if (g.templates[ name ] != 'undefined') {
202 var template = g.templates[ name ];
203 for (var i in template) {
204 g.changed[ i ] = template[ i ];
205 switch( template[i].type ) {
207 g.apply(template[i].field,template[i].value);
210 if (g.stat_cat_seen[ template[i].field ]) g.apply_stat_cat(template[i].field,template[i].value);
213 g.apply_owning_lib(template[i].value);
217 g.summarize( g.copies );
221 g.error.standard_unexpected_error_alert('Error applying template',E);
225 /******************************************************************************************************/
226 /* Save as Template */
228 g.save_template = function() {
230 var name = window.prompt('Enter template name:','','Save As Template');
232 g.templates[name] = g.changed;
233 var robj = g.network.simple_request(
234 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
236 if (typeof robj.ilsevent != 'undefined') {
239 alert('Template "' + name + '" saved.');
243 g.retrieve_templates();
245 g.error.standard_unexpected_error_alert('Error saving template',E);
251 g.error.standard_unexpected_error_alert('Error saving template',E);
255 /******************************************************************************************************/
256 /* Delete Template */
258 g.delete_template = function() {
260 var name = g.template_menu.value;
262 if (! window.confirm('Delete template "' + name + '"?') ) return;
263 delete(g.templates[name]);
264 var robj = g.network.simple_request(
265 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
267 if (typeof robj.ilsevent != 'undefined') {
270 alert('Template "' + name + '" deleted.');
274 g.retrieve_templates();
276 g.error.standard_unexpected_error_alert('Error deleting template',E);
282 g.error.standard_unexpected_error_alert('Error deleting template',E);
286 /******************************************************************************************************/
287 /* Export Templates */
289 g.export_templates = function() {
291 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
292 JSAN.use('util.file'); var f = new util.file('');
293 f.export_file( { 'title' : 'Save Templates File As', 'data' : g.templates } );
295 g.error.standard_unexpected_error_alert('Error exporting templates',E);
299 /******************************************************************************************************/
300 /* Import Templates */
302 g.import_templates = function() {
304 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
305 JSAN.use('util.file'); var f = new util.file('');
306 var temp = f.import_file( { 'title' : 'Import Templates File' } );
308 for (var i in temp) {
310 if (g.templates[i]) {
312 var r = g.error.yns_alert(
313 'Replace the existing template with the imported template?\n' + g.error.pretty_print( js2JSON( temp[i] ) ),
314 'Template ' + i + ' already exists.','Yes','No',null,'Click here'
317 if (r == 0 /* Yes */) g.templates[i] = temp[i];
321 g.templates[i] = temp[i];
327 var r = g.error.yns_alert(
328 'Save all of these imported templates permanently to this account?',
329 'Final Warning', 'Yes', 'No', null, 'Click here'
332 if (r == 0 /* Yes */) {
333 var robj = g.network.simple_request(
334 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
336 if (typeof robj.ilsevent != 'undefined') {
339 alert('All templates saved.');
343 g.retrieve_templates();
345 g.error.standard_unexpected_error_alert('Error saving templates',E);
351 util.widgets.remove_children('template_placeholder');
352 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
353 g.template_menu = util.widgets.make_menulist( list );
354 $('template_placeholder').appendChild(g.template_menu);
355 alert("Note: These imported templates will get saved along with any new template you try to create, but if that doesn't happen, then these templates will disappear with the next invocation of the item attribute editor.");
360 g.error.standard_unexpected_error_alert('Error importing templates',E);
365 /******************************************************************************************************/
366 /* Restore backup copies */
368 g.reset = function() {
370 g.copies = JSON2js( g.original_copies );
371 g.summarize( g.copies );
375 /******************************************************************************************************/
376 /* Apply a value to a specific field on all the copies being edited */
378 g.apply = function(field,value) {
379 g.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
380 if (value == '<HACK:KLUDGE:NULL>') value = null;
381 if (field == 'alert_message') { value = value.replace(/^\W+$/g,''); }
382 if (field == 'price' || field == 'deposit_amount') {
383 if (value == '') { value = null; } else { JSAN.use('util.money'); value = util.money.sanitize( value ); }
385 for (var i = 0; i < g.copies.length; i++) {
386 var copy = g.copies[i];
388 copy[field]( value ); copy.ischanged('1');
395 /******************************************************************************************************/
396 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
398 g.apply_stat_cat = function(sc_id,entry_id) {
399 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
400 for (var i = 0; i < g.copies.length; i++) {
401 var copy = g.copies[i];
404 var temp = copy.stat_cat_entries();
405 if (!temp) temp = [];
406 temp = util.functional.filter_list(
409 return (obj.stat_cat() != sc_id);
412 if (entry_id > -1) temp.push(
413 util.functional.find_id_object_in_list(
414 g.data.hash.asc[sc_id].entries(),
418 copy.stat_cat_entries( temp );
421 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
426 /******************************************************************************************************/
427 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
429 g.apply_owning_lib = function(ou_id) {
430 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
431 for (var i = 0; i < g.copies.length; i++) {
432 var copy = g.copies[i];
434 if (!g.map_acn[copy.call_number()]) {
435 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
436 if (typeof volume.ilsevent != 'undefined') {
437 g.error.standard_unexpected_error_alert('Error retrieving Volume information for copy ' + copy.barcode() + ". The owning library for this copy won't be changed.",volume);
440 g.map_acn[copy.call_number()] = volume;
442 var old_volume = g.map_acn[copy.call_number()];
443 var acn_id = g.network.simple_request(
444 'FM_ACN_FIND_OR_CREATE',
445 [ses(),old_volume.label(),old_volume.record(),ou_id]
447 if (typeof acn_id.ilsevent != 'undefined') {
448 g.error.standard_unexpected_error_alert('Error changing owning lib for copy ' + copy.barcode() + ". The owning library for this copy won't be changed.",acn_id);
451 copy.call_number(acn_id);
454 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
459 /******************************************************************************************************/
460 /* This returns true if none of the copies being edited are pre-cats */
462 g.safe_to_change_owning_lib = function() {
465 for (var i = 0; i < g.copies.length; i++) {
466 var cn = g.copies[i].call_number();
467 if (typeof cn == 'object') { cn = cn.id(); }
468 if (cn == -1) { safe = false; }
472 g.error.standard_unexpected_error_alert('safe_to_change_owning_lib?',E);
477 /******************************************************************************************************/
478 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
480 g.safe_to_edit_copy_status = function() {
483 for (var i = 0; i < g.copies.length; i++) {
484 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
485 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
489 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
494 /******************************************************************************************************/
495 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
497 g.populate_alert_message_input = function(tb) {
499 var seen = {}; var s = '';
500 for (var i = 0; i < g.copies.length; i++) {
501 var msg = g.copies[i].alert_message();
503 if (typeof seen[msg] == 'undefined') {
509 tb.setAttribute('value',s);
511 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
515 /***************************************************************************************************************/
516 /* This returns a list of acpl's appropriate for the copies being edited (and caches them in the global stash) */
518 g.get_acpl_list_for_lib = function(lib_id,but_only_these) {
519 g.data.stash_retrieve();
520 var label = 'acpl_list_for_lib_'+lib_id;
521 if (typeof g.data[label] == 'undefined') {
522 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]); // This returns acpl's for all ancestors and descendants as well as the lib
523 if (typeof robj.ilsevent != 'undefined') throw(robj);
525 for (var j = 0; j < robj.length; j++) {
526 var my_acpl = robj[j];
527 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
528 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
529 g.data.list.acpl.push( my_acpl );
531 var only_this_lib = my_acpl.owning_lib(); if (!only_this_lib) continue;
532 if (typeof only_this_lib == 'object') only_this_lib = only_this_lib.id();
533 if (but_only_these.indexOf( String( only_this_lib ) ) != -1) { // This filters out some of the libraries (usually the descendants)
534 temp_list.push( my_acpl );
537 g.data[label] = temp_list; g.data.stash(label,'hash','list');
539 return g.data[label];
542 /******************************************************************************************************/
543 /* This returns a list of acpl's appropriate for the copies being edited */
545 g.get_acpl_list = function() {
548 JSAN.use('util.functional');
552 /**************************************/
553 /* get owning libs from call numbers */
555 var owning_libs = {};
556 for (var i = 0; i < g.copies.length; i++) {
557 var callnumber = g.copies[i].call_number();
558 if (!callnumber) continue;
559 var cn_id = typeof callnumber == 'object' ? callnumber.id() : callnumber;
561 if (! g.map_acn[ cn_id ]) {
562 var req = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
563 if (typeof req.ilsevent == 'undefined') {
564 g.map_acn[ cn_id ] = req;
569 var consider_lib = g.map_acn[ cn_id ].owning_lib();
570 if (!consider_lib) continue;
571 owning_libs[ typeof consider_lib == 'object' ? consider_lib.id() : consider_lib ] = true;
575 for (var i in g.callnumbers) {
576 var consider_lib = g.callnumbers[i].owning_lib;
577 if (!consider_lib) continue;
578 owning_libs[ typeof consider_lib == 'object' ? consider_lib.id() : consider_lib ] = true;
582 /***************************************************************************************************/
583 /* now find the first ancestor they all have in common, get the acpl's for it and higher ancestors */
585 JSAN.use('util.fm_utils');
586 var libs = []; for (var i in owning_libs) libs.push(i);
587 if (libs.length > 0) {
588 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
589 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
592 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
593 var acpl_list = g.get_acpl_list_for_lib(ancestor, ancestors);
594 if (acpl_list) for (var i = 0; i < acpl_list.length; i++) {
595 if (acpl_list[i] != null) {
596 my_acpls[ typeof acpl_list[i] == 'object' ? acpl_list[i].id() : acpl_list[i] ] = true;
607 for (var i = 0; i < g.copies.length; i++) {
608 var consider_lib = g.copies[i].circ_lib();
609 if (!consider_lib) continue;
610 circ_libs[ typeof consider_lib == 'object' ? consider_lib.id() : consider_lib ] = true;
613 /***************************************************************************************************/
614 /* now find the first ancestor they all have in common, get the acpl's for it and higher ancestors */
616 libs = []; for (var i in circ_libs) libs.push(i);
617 if (libs.length > 0) {
618 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
619 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
622 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
623 var acpl_list = g.get_acpl_list_for_lib(ancestor, ancestors);
624 if (acpl_list) for (var i = 0; i < acpl_list.length; i++) {
625 if (acpl_list[i] != null) {
626 my_acpls[ typeof acpl_list[i] == 'object' ? acpl_list[i].id() : acpl_list[i] ] = true;
632 var acpl_list = []; for (var i in my_acpls) acpl_list.push( g.data.hash.acpl[ i ] );
633 return acpl_list.sort(
635 var label_a = g.data.hash.aou[ a.owning_lib() ].shortname() + ' : ' + a.name();
636 var label_b = g.data.hash.aou[ b.owning_lib() ].shortname() + ' : ' + b.name();
637 if (label_a < label_b) return -1;
638 if (label_a > label_b) return 1;
644 g.error.standard_unexpected_error_alert('get_acpl_list',E);
650 /******************************************************************************************************/
651 /* This keeps track of what fields have been edited for styling purposes */
655 /******************************************************************************************************/
656 /* These need data from the middle layer to render */
658 g.special_exception = {
659 'Owning Lib : Call Number' : function(label,value) {
660 JSAN.use('util.widgets');
661 if (value>0) { /* an existing call number */
663 api.FM_ACN_RETRIEVE.app,
664 api.FM_ACN_RETRIEVE.method,
667 var cn = '??? id = ' + value;
669 cn = req.getResultObject();
671 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
673 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
676 } else { /* a yet to be created call number */
678 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
682 'Creator' : function(label,value) {
683 if (value == null || value == '' || value == 'null') return;
684 g.network.simple_request(
685 'FM_AU_RETRIEVE_VIA_ID',
688 var p = '??? id = ' + value;
690 p = req.getResultObject();
694 g.error.sdump('D_ERROR','patron retrieve: ' + E);
696 JSAN.use('util.widgets');
697 util.widgets.set_text(label,p);
701 'Last Editor' : function(label,value) {
702 if (value == null || value == '' || value == 'null') return;
703 g.network.simple_request(
704 'FM_AU_RETRIEVE_VIA_ID',
707 var p = '??? id = ' + value;
709 p = req.getResultObject();
713 g.error.sdump('D_ERROR','patron retrieve: ' + E);
715 util.widgets.set_text(label,p);
722 /******************************************************************************************************/
723 g.readonly_stat_cat_names = [];
724 g.editable_stat_cat_names = [];
726 /******************************************************************************************************/
727 /* These get show in the left panel */
729 function init_panes() {
730 g.panes_and_field_names = {
737 render: 'fm.barcode();',
743 render: 'util.date.formatted_date( fm.create_date(), "%F");',
749 render: 'fm.creator();',
755 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
761 render: 'fm.editor();',
772 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
773 input: 'c = function(v){ g.apply("location",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.get_acpl_list(), function(obj) { return [ g.data.hash.aou[ obj.owning_lib() ].shortname() + " : " + obj.name(), obj.id() ]; }).sort()); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
778 "Circulation Library",
780 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
781 //input: 'c = function(v){ g.apply("circ_lib",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( util.functional.filter_list(g.data.list.my_aou, function(obj) { return g.data.hash.aout[ obj.ou_type() ].can_have_vols(); }), function(obj) { return [ obj.shortname(), obj.id() ]; }).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
782 input: 'c = function(v){ g.apply("circ_lib",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.aou, function(obj) { var sname = obj.shortname(); for (i = sname.length; i < 20; i++) sname += " "; return [ obj.name() ? sname + " " + obj.name() : obj.shortname(), obj.id(), ( ! get_bool( g.data.hash.aout[ obj.ou_type() ].can_have_vols() ) ), ( g.data.hash.aout[ obj.ou_type() ].depth() * 2), ]; }), g.data.list.au[0].ws_ou()); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
786 "Owning Lib : Call Number",
788 render: 'fm.call_number();',
789 input: g.safe_to_change_owning_lib() ? 'c = function(v){ g.apply_owning_lib(v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.aou, function(obj) { var sname = obj.shortname(); for (i = sname.length; i < 20; i++) sname += " "; return [ obj.name() ? sname + " " + obj.name() : obj.shortname(), obj.id(), ( ! get_bool( g.data.hash.aout[ obj.ou_type() ].can_have_vols() ) ), ( g.data.hash.aout[ obj.ou_type() ].depth() * 2), ]; }), g.data.list.au[0].ws_ou()); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);' : undefined,
795 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
796 input: 'c = function(v){ g.apply("copy_number",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
808 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
809 input: 'c = function(v){ g.apply("circulate",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
815 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
816 input: 'c = function(v){ g.apply("holdable",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
822 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
823 input: 'c = function(v){ g.apply("age_protect",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "<Remove Protection>", "<HACK:KLUDGE:NULL>" ] ].concat( util.functional.map_list( g.data.list.crahp, function(obj) { return [ obj.name(), obj.id() ]; }).sort() ) ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
830 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
831 input: 'c = function(v){ g.apply("loan_duration",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Short", "1" ], [ "Normal", "2" ], [ "Long", "3" ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
838 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
839 input: 'c = function(v){ g.apply("fine_level",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Low", "1" ], [ "Normal", "2" ], [ "High", "3" ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
846 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
847 input: 'c = function(v){ g.apply("circ_as_type",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.citm, function(n){return [ n.code() + " - " + n.value(), n.code()];} ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
851 "Circulation Modifier",
853 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
854 /*input: 'c = function(v){ g.apply("circ_modifier",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',*/
855 input: 'c = function(v){ g.apply("circ_modifier",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.circ_modifier, function(obj) { return [ obj, obj ]; } ).sort() ); x.setAttribute("editable","true"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
864 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
865 input: 'c = function(v){ g.apply("alert_message",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("multiline",true); g.populate_alert_message_input(x); x.addEventListener("apply",function(f){ return function(ev) { f( ev.target.value ); } }(c), false);',
872 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
873 input: 'c = function(v){ g.apply("deposit",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
879 render: 'if (fm.deposit_amount() == null) { "<Unset>"; } else { util.money.sanitize( fm.deposit_amount() ); }',
880 input: 'c = function(v){ g.apply("deposit_amount",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
886 render: 'if (fm.price() == null) { "<Unset>"; } else { util.money.sanitize( fm.price() ); }',
887 input: 'c = function(v){ g.apply("price",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
894 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
895 input: 'c = function(v){ g.apply("opac_visible",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
901 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
902 input: 'c = function(v){ g.apply("ref",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
914 /******************************************************************************************************/
915 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
917 g.summarize = function( copies ) {
918 /******************************************************************************************************/
921 JSAN.use('util.date'); JSAN.use('util.money');
924 for (var i in g.panes_and_field_names) {
925 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
927 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
928 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
930 /******************************************************************************************************/
931 /* Loop through the field names */
933 for (var i = 0; i < g.field_names.length; i++) {
935 var field_name = g.field_names[i][0];
936 var render = g.field_names[i][1].render;
937 var attr = g.field_names[i][1].attr;
938 g.summary[ field_name ] = {};
940 /******************************************************************************************************/
941 /* Loop through the copies */
943 for (var j = 0; j < copies.length; j++) {
946 var cmd = render || ('fm.' + field_name + '();');
949 /**********************************************************************************************/
950 /* Try to retrieve the value for this field for this copy */
955 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
957 if (typeof value == 'object' && value != null) {
958 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
961 /**********************************************************************************************/
962 /* Tally the count */
964 if (g.summary[ field_name ][ value ]) {
965 g.summary[ field_name ][ value ]++;
967 g.summary[ field_name ][ value ] = 1;
971 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
974 /******************************************************************************************************/
975 /* Display the summarized data and inputs for editing */
977 g.render = function() {
979 /******************************************************************************************************/
980 /* Library setup and clear any existing interface */
982 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
984 for (var i in g.panes_and_field_names) {
985 var p = document.getElementById(i);
986 if (p) util.widgets.remove_children(p);
989 /******************************************************************************************************/
990 /* Populate the library filter menu for stat cats */
993 for (var i = 0; i < g.panes_and_field_names.right_pane4.length; i++) {
994 sc_libs[ g.panes_and_field_names.right_pane4[i][1].attr.sc_lib ] = true;
997 for (var i in sc_libs) { sc_libs2.push( [ g.data.hash.aou[ i ].shortname(), i ] ); }
999 var x = document.getElementById("stat_cat_lib_filter_menu").firstChild;
1000 JSAN.use('util.widgets'); util.widgets.remove_children(x);
1001 for (var i = 0; i < sc_libs2.length; i++) {
1002 var menuitem = document.createElement('menuitem');
1003 menuitem.setAttribute('id','filter_'+sc_libs2[i][1]);
1004 menuitem.setAttribute('type','checkbox');
1005 menuitem.setAttribute('checked','true');
1006 menuitem.setAttribute('label',sc_libs2[i][0]);
1007 menuitem.setAttribute('value',sc_libs2[i][1]);
1008 menuitem.setAttribute('oncommand','try{g.toggle_stat_cat_display(this);}catch(E){alert(E);}');
1009 x.appendChild(menuitem);
1012 /******************************************************************************************************/
1013 /* Prepare the panes */
1015 var groupbox; var caption; var vbox; var grid; var rows;
1017 /******************************************************************************************************/
1018 /* Loop through the field names */
1020 for (h in g.panes_and_field_names) {
1021 if (!document.getElementById(h)) continue;
1022 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
1024 var f = g.panes_and_field_names[h][i]; var fn = f[0]; var attr = f[1].attr;
1025 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
1027 for (var a in attr) {
1028 groupbox.setAttribute(a,attr[a]);
1031 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
1032 caption = document.createElement('caption'); groupbox.appendChild(caption);
1033 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
1034 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
1035 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
1036 grid.setAttribute('flex','1');
1037 rows = grid.lastChild;
1040 /**************************************************************************************/
1041 /* Loop through each value for the field */
1043 for (var j in g.summary[fn]) {
1044 var value = j; var count = g.summary[fn][j];
1045 row = document.createElement('row'); rows.appendChild(row);
1046 var label1 = document.createElement('description'); row.appendChild(label1);
1047 if (g.special_exception[ fn ]) {
1048 g.special_exception[ fn ]( label1, value );
1050 label1.appendChild( document.createTextNode(value) );
1052 var label2 = document.createElement('description'); row.appendChild(label2);
1053 var unit = count == 1 ? 'copy' : 'copies';
1054 label2.appendChild( document.createTextNode(count + ' ' + unit) );
1056 var hbox = document.createElement('hbox');
1057 hbox.setAttribute('id',fn);
1058 groupbox.appendChild(hbox);
1059 var hbox2 = document.createElement('hbox');
1060 groupbox.appendChild(hbox2);
1062 /**************************************************************************************/
1063 /* Render the input widget */
1065 if (f[1].input && g.edit) {
1066 g.render_input(hbox,f[1]);
1070 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1076 /******************************************************************************************************/
1077 /* Synchronize stat cat visibility with library filter menu, and default template selection */
1078 JSAN.use('util.file');
1079 var file = new util.file('copy_editor_prefs.'+g.data.server_unadorned);
1080 g.copy_editor_prefs = util.widgets.load_attributes(file);
1081 for (var i in g.copy_editor_prefs) {
1082 if (i.match(/filter_/) && g.copy_editor_prefs[i].checked == '') {
1084 g.toggle_stat_cat_display( document.getElementById(i) );
1085 } catch(E) { alert(E); }
1088 if (g.template_menu) g.template_menu.value = g.template_menu.getAttribute('value');
1092 /******************************************************************************************************/
1093 /* This actually draws the change button and input widget for a given field */
1094 g.render_input = function(node,blob) {
1096 // node = hbox ; groupbox -> hbox, hbox
1098 var groupbox = node.parentNode;
1099 var caption = groupbox.firstChild;
1100 var vbox = node.previousSibling;
1102 var hbox2 = node.nextSibling;
1104 var input_cmd = blob.input;
1105 var render_cmd = blob.render;
1106 var attr = blob.attr;
1108 var block = false; var first = true;
1110 function on_mouseover(ev) {
1111 groupbox.setAttribute('style','background: white');
1114 function on_mouseout(ev) {
1115 groupbox.setAttribute('style','');
1118 vbox.addEventListener('mouseover',on_mouseover,false);
1119 vbox.addEventListener('mouseout',on_mouseout,false);
1120 groupbox.addEventListener('mouseover',on_mouseover,false);
1121 groupbox.addEventListener('mouseout',on_mouseout,false);
1122 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1123 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1125 function on_click(ev){
1127 if (block) return; block = true;
1129 function post_c(v) {
1131 /* FIXME - kludgy */
1132 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1136 f = input_cmd.match(/apply\("(.+?)",/)[1];
1139 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1145 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1149 g.summarize( g.copies );
1151 document.getElementById(caption.id).focus();
1155 g.error.standard_unexpected_error_alert('post_c',E);
1158 var x; var c; eval( input_cmd );
1160 util.widgets.remove_children(vbox);
1161 util.widgets.remove_children(hbox);
1162 util.widgets.remove_children(hbox2);
1163 hbox.appendChild(x);
1164 var apply = document.createElement('button');
1165 apply.setAttribute('label','Apply');
1166 apply.setAttribute('accesskey','A');
1167 hbox2.appendChild(apply);
1168 apply.addEventListener('command',function() { c(x.value); },false);
1169 var cancel = document.createElement('button');
1170 cancel.setAttribute('label','Cancel');
1171 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1172 hbox2.appendChild(cancel);
1173 setTimeout( function() { x.focus(); }, 0 );
1176 g.error.standard_unexpected_error_alert('render_input',E);
1179 vbox.addEventListener('click',on_click, false);
1180 hbox.addEventListener('click',on_click, false);
1181 caption.addEventListener('click',on_click, false);
1182 caption.addEventListener('keypress',function(ev) {
1183 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1185 caption.setAttribute('style','-moz-user-focus: normal');
1186 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1187 caption.setAttribute('onblur','this.setAttribute("class","")');
1190 g.error.sdump('D_ERROR',E + '\n');
1194 /******************************************************************************************************/
1195 /* store the copies in the global xpcom stash */
1197 g.stash_and_close = function() {
1199 if (g.handle_update) {
1201 var r = g.network.request(
1202 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1203 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1204 [ ses(), g.copies, true ]
1206 if (typeof r.ilsevent != 'undefined') {
1207 g.error.standard_unexpected_error_alert('copy update',r);
1209 alert('Items added/modified.');
1211 /* FIXME -- revisit the return value here */
1213 alert('copy update error: ' + js2JSON(E));
1216 //g.data.temp_copies = js2JSON( g.copies );
1217 //g.data.stash('temp_copies');
1218 xulG.copies = g.copies;
1219 update_modal_xulG(xulG);
1222 g.error.standard_unexpected_error_alert('stash and close',E);
1226 /******************************************************************************************************/
1227 /* spawn copy notes interface */
1229 g.copy_notes = function() {
1230 JSAN.use('util.window'); var win = new util.window();
1232 urls.XUL_COPY_NOTES,
1233 //+ '?copy_id=' + window.escape(g.copies[0].id()),
1234 'Copy Notes','chrome,resizable,modal',
1235 { 'copy_id' : g.copies[0].id() }
1239 /******************************************************************************************************/
1240 /* hides or unhides stat cats based on library stat cat filter menu */
1241 g.toggle_stat_cat_display = function(el) {
1243 var visible = el.getAttribute('checked');
1244 var nl = document.getElementsByAttribute('sc_lib',el.getAttribute('value'));
1245 for (var n = 0; n < nl.length; n++) {
1247 nl[n].setAttribute('hidden','false');
1249 nl[n].setAttribute('hidden','true');
1252 g.copy_editor_prefs[ el.getAttribute('id') ] = { 'checked' : visible };
1253 g.save_attributes();
1256 /******************************************************************************************************/
1257 /* This adds a stat cat definition to the stat cat pane for rendering */
1258 g.save_attributes = function() {
1259 JSAN.use('util.widgets'); JSAN.use('util.file'); var file = new util.file('copy_editor_prefs.'+g.data.server_unadorned);
1260 var what_to_save = {};
1261 for (var i in g.copy_editor_prefs) {
1262 what_to_save[i] = [];
1263 for (var j in g.copy_editor_prefs[i]) what_to_save[i].push(j);
1265 util.widgets.save_attributes(file, what_to_save );
1268 /******************************************************************************************************/
1269 /* This adds a stat cat definition to the stat cat pane for rendering */
1270 g.add_stat_cat = function(sc) {
1272 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; g.data.stash('hash'); }
1276 if (typeof sc == 'object') {
1281 if (typeof g.stat_cat_seen[sc_id] != 'undefined') { return; }
1283 g.stat_cat_seen[ sc_id ] = 1;
1285 if (typeof sc != 'object') {
1287 sc = g.network.simple_request(
1288 'FM_ASC_BATCH_RETRIEVE',
1289 [ ses(), [ sc_id ] ]
1294 g.data.hash.asc[ sc.id() ] = sc; g.data.stash('hash');
1296 var label_name = g.data.hash.aou[ sc.owner() ].shortname() + " : " + sc.name();
1301 render: 'var l = util.functional.find_list( fm.stat_cat_entries(), function(e){ return e.stat_cat() == '
1302 + sc.id() + '; } ); l ? l.value() : "<Unset>";',
1303 input: 'c = function(v){ g.apply_stat_cat(' + sc.id() + ',v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "<Remove Stat Cat>", -1 ] ].concat( util.functional.map_list( g.data.hash.asc[' + sc.id()
1304 + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ) ).sort() ); '
1305 + 'x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c),false);',
1312 g.panes_and_field_names.right_pane4.push( temp_array );
1314 g.error.standard_unexpected_error_alert('Error adding stat cat to display definition',E);
1318 /******************************************************************************************************/
1319 /* Add stat cats to the panes_and_field_names.right_pane4 */
1320 g.populate_stat_cats = function() {
1322 g.data.stash_retrieve();
1323 g.stat_cat_seen = {};
1325 function get(lib_id,only_these) {
1326 g.data.stash_retrieve();
1327 var label = 'asc_list_for_lib_'+lib_id;
1328 if (typeof g.data[label] == 'undefined') {
1329 var robj = g.network.simple_request('FM_ASC_RETRIEVE_VIA_AOU', [ ses(), lib_id ]);
1330 if (typeof robj.ilsevent != 'undefined') throw(robj);
1332 for (var j = 0; j < robj.length; j++) {
1333 var my_asc = robj[j];
1334 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; }
1335 if (typeof g.data.hash.asc[ my_asc.id() ] == 'undefined') {
1336 g.data.hash.asc[ my_asc.id() ] = my_asc;
1338 var only_this_lib = my_asc.owner(); if (typeof only_this_lib == 'object') only_this_lib = only_this_lib.id();
1339 if (only_these.indexOf( String( only_this_lib ) ) != -1) {
1340 temp_list.push( my_asc );
1343 g.data[label] = temp_list; g.data.stash(label,'hash','list');
1345 return g.data[label];
1348 /* The stat cats for the pertinent library -- this is based on workstation ou */
1349 var label = 'asc_list_for_' + typeof g.data.ws_ou == 'object' ? g.data.ws_ou.id() : g.data.ws_ou;
1350 g.data[ label ] = g.data.list.my_asc; g.data.stash('label');
1351 for (var i = 0; i < g.data.list.my_asc.length; i++) {
1352 g.add_stat_cat( g.data.list.my_asc[i] );
1355 /* For the others, we want to consider the owning libs, circ libs, and any libs that have stat cats already on the copies,
1356 however, if batch editing, we only want to show the ones they have in common. So let's compile the libs */
1358 function add_common_ancestors(sc_libs) {
1359 JSAN.use('util.fm_utils');
1360 var libs = []; for (var i in sc_libs) libs.push(i);
1361 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
1362 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
1364 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
1365 var asc_list = get(ancestor, ancestors);
1366 for (var i = 0; i < asc_list.length; i++) {
1367 g.add_stat_cat( asc_list[i] );
1372 /* stat cats based on stat cat entries present on these copies */
1374 for (var i = 0; i < g.copies.length; i++) {
1375 var entries = g.copies[i].stat_cat_entries();
1376 if (!entries) entries = [];
1377 for (var j = 0; j < entries.length; j++) {
1378 var lib = entries[j].owner(); if (typeof lib == 'object') lib = lib.id();
1379 sc_libs[ lib ] = true;
1382 add_common_ancestors(sc_libs); // CAVEAT - if a copy has no stat_cat_entries, it basically gets no vote here
1384 /* stat cats based on Circ Lib */
1386 for (var i = 0; i < g.copies.length; i++) {
1387 var circ_lib = g.copies[i].circ_lib(); if (typeof circ_lib == 'object') circ_lib = circ_lib.id();
1388 sc_libs[ circ_lib ] = true;
1390 add_common_ancestors(sc_libs);
1392 /* stat cats based on Owning Lib */
1394 for (var i = 0; i < g.copies.length; i++) {
1395 var cn_id = g.copies[i].call_number();
1397 if (! g.map_acn[ cn_id ]) {
1398 var req = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
1399 if (typeof req.ilsevent == 'undefined') {
1400 g.map_acn[ cn_id ] = req;
1405 var owning_lib = g.map_acn[ cn_id ].owning_lib(); if (typeof owning_lib == 'object') owning_lib = owning_lib.id();
1406 sc_libs[ owning_lib ] = true;
1409 add_common_ancestors(sc_libs); // CAVEAT - if a copy is a pre-cat, it basically gets no vote here
1411 g.panes_and_field_names.right_pane4.sort();
1414 g.error.standard_unexpected_error_alert('Error populating stat cats for display',E);