7 /******************************************************************************************************/
8 /* setup JSAN and some initial libraries */
10 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
11 if (typeof JSAN == 'undefined') { throw( "The JSAN library object is missing."); }
12 JSAN.errorLevel = "die"; // none, warn, or die
13 JSAN.addRepository('/xul/server/');
14 JSAN.use('util.error'); g.error = new util.error();
15 g.error.sdump('D_TRACE','my_init() for cat/copy_editor.xul');
17 JSAN.use('util.functional');
18 JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
19 JSAN.use('util.network'); g.network = new util.network();
21 g.docid = xul_param('docid',{'modal_xulG':true});
22 g.handle_update = xul_param('handle_update',{'modal_xulG':true});
24 /******************************************************************************************************/
25 /* Get the copy ids from various sources and flesh them */
27 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});
28 if (!copy_ids) copy_ids = [];
30 if (copy_ids.length > 0) g.copies = g.network.simple_request(
31 'FM_ACP_FLESHED_BATCH_RETRIEVE',
35 /******************************************************************************************************/
36 /* And other fleshed copies if any */
38 if (!g.copies) g.copies = [];
39 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})
40 if (c) g.copies = g.copies.concat(c);
42 /******************************************************************************************************/
43 /* We try to retrieve callnumbers for existing copies, but for new copies, we rely on this */
45 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});
48 /******************************************************************************************************/
49 /* Quick fix, this was defined inline in the global scope but now needs g.error and g.copies from my_init */
53 /******************************************************************************************************/
54 /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
56 if (xul_param('edit',{'modal_xulG':true}) == '1') {
58 document.getElementById('caption').setAttribute('label','Copy Editor');
59 document.getElementById('save').setAttribute('hidden','false');
60 g.retrieve_templates();
62 $('top_nav').setAttribute('hidden','true');
65 if (g.copies.length > 0 && g.copies[0].id() < 0) {
66 document.getElementById('copy_notes').setAttribute('hidden','true');
67 g.apply("status",5 /* In Process */);
68 $('save').setAttribute('label','Create Copies');
70 g.panes_and_field_names.left_pane =
75 render: 'typeof fm.status() == "object" ? fm.status().name() : g.data.hash.ccs[ fm.status() ].name()',
76 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,
77 //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);',
80 ].concat(g.panes_and_field_names.left_pane);
83 if (g.copies.length != 1) {
84 document.getElementById('copy_notes').setAttribute('hidden','true');
87 /******************************************************************************************************/
88 /* Show the Record Details? */
91 document.getElementById('brief_display').setAttribute(
93 urls.XUL_BIB_BRIEF + '?docid=' + g.docid
96 document.getElementById('brief_display').setAttribute('hidden','true');
99 /******************************************************************************************************/
100 /* Add stat cats to the panes_and_field_names.right_pane4 */
102 g.populate_stat_cats();
104 /******************************************************************************************************/
105 /* Backup copies :) */
107 g.original_copies = js2JSON( g.copies );
109 /******************************************************************************************************/
112 g.summarize( g.copies );
116 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
117 "system administrator or software developer the following:\ncat/copy_editor.xul\n" + E + '\n';
118 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
123 /******************************************************************************************************/
124 /* Retrieve Templates */
126 g.retrieve_templates = function() {
128 JSAN.use('util.widgets'); JSAN.use('util.functional');
130 var robj = g.network.simple_request('FM_AUS_RETRIEVE',[ses(),g.data.list.au[0].id()]);
131 if (typeof robj['staff_client.copy_editor.templates'] != 'undefined') {
132 g.templates = robj['staff_client.copy_editor.templates'];
134 util.widgets.remove_children('template_placeholder');
135 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
137 g.template_menu = util.widgets.make_menulist( list );
138 g.template_menu.setAttribute('id','template_menu');
139 $('template_placeholder').appendChild(g.template_menu);
140 g.template_menu.addEventListener(
142 function() { g.copy_editor_prefs[ 'template_menu' ] = { 'value' : g.template_menu.value }; g.save_attributes(); },
146 g.error.standard_unexpected_error_alert('Error retrieving templates',E);
150 /******************************************************************************************************/
153 g.apply_template = function() {
155 var name = g.template_menu.value;
156 if (g.templates[ name ] != 'undefined') {
157 var template = g.templates[ name ];
158 for (var i in template) {
159 g.changed[ i ] = template[ i ];
160 switch( template[i].type ) {
162 g.apply(template[i].field,template[i].value);
165 if (g.stat_cat_seen[ template[i].field ]) g.apply_stat_cat(template[i].field,template[i].value);
168 g.apply_owning_lib(template[i].value);
172 g.summarize( g.copies );
176 g.error.standard_unexpected_error_alert('Error applying template',E);
180 /******************************************************************************************************/
181 /* Save as Template */
183 g.save_template = function() {
185 var name = window.prompt('Enter template name:','','Save As Template');
187 g.templates[name] = g.changed;
188 var robj = g.network.simple_request(
189 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
191 if (typeof robj.ilsevent != 'undefined') {
194 alert('Template "' + name + '" saved.');
198 g.retrieve_templates();
200 g.error.standard_unexpected_error_alert('Error saving template',E);
206 g.error.standard_unexpected_error_alert('Error saving template',E);
210 /******************************************************************************************************/
211 /* Delete Template */
213 g.delete_template = function() {
215 var name = g.template_menu.value;
217 if (! window.confirm('Delete template "' + name + '"?') ) return;
218 delete(g.templates[name]);
219 var robj = g.network.simple_request(
220 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
222 if (typeof robj.ilsevent != 'undefined') {
225 alert('Template "' + name + '" deleted.');
229 g.retrieve_templates();
231 g.error.standard_unexpected_error_alert('Error deleting template',E);
237 g.error.standard_unexpected_error_alert('Error deleting template',E);
241 /******************************************************************************************************/
242 /* Export Templates */
244 g.export_templates = function() {
246 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
247 JSAN.use('util.file'); var f = new util.file('');
248 f.export_file( { 'title' : 'Save Templates File As', 'data' : g.templates } );
250 g.error.standard_unexpected_error_alert('Error exporting templates',E);
254 /******************************************************************************************************/
255 /* Import Templates */
257 g.import_templates = function() {
259 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
260 JSAN.use('util.file'); var f = new util.file('');
261 var temp = f.import_file( { 'title' : 'Import Templates File' } );
263 for (var i in temp) {
265 if (g.templates[i]) {
267 var r = g.error.yns_alert(
268 'Replace the existing template with the imported template?\n' + g.error.pretty_print( js2JSON( temp[i] ) ),
269 'Template ' + i + ' already exists.','Yes','No',null,'Click here'
272 if (r == 0 /* Yes */) g.templates[i] = temp[i];
276 g.templates[i] = temp[i];
282 var r = g.error.yns_alert(
283 'Save all of these imported templates permanently to this account?',
284 'Final Warning', 'Yes', 'No', null, 'Click here'
287 if (r == 0 /* Yes */) {
288 var robj = g.network.simple_request(
289 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
291 if (typeof robj.ilsevent != 'undefined') {
294 alert('All templates saved.');
298 g.retrieve_templates();
300 g.error.standard_unexpected_error_alert('Error saving templates',E);
306 util.widgets.remove_children('template_placeholder');
307 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
308 g.template_menu = util.widgets.make_menulist( list );
309 $('template_placeholder').appendChild(g.template_menu);
310 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.");
315 g.error.standard_unexpected_error_alert('Error importing templates',E);
320 /******************************************************************************************************/
321 /* Restore backup copies */
323 g.reset = function() {
325 g.copies = JSON2js( g.original_copies );
326 g.summarize( g.copies );
330 /******************************************************************************************************/
331 /* Apply a value to a specific field on all the copies being edited */
333 g.apply = function(field,value) {
334 g.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
335 if (value == '<HACK:KLUDGE:NULL>') value = null;
336 if (field == 'alert_message') { value = value.replace(/^\W+$/g,''); }
337 if (field == 'price' || field == 'deposit_amount') {
338 if (value == '') { value = null; } else { JSAN.use('util.money'); value = util.money.sanitize( value ); }
340 for (var i = 0; i < g.copies.length; i++) {
341 var copy = g.copies[i];
343 copy[field]( value ); copy.ischanged('1');
350 /******************************************************************************************************/
351 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
353 g.apply_stat_cat = function(sc_id,entry_id) {
354 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
355 for (var i = 0; i < g.copies.length; i++) {
356 var copy = g.copies[i];
359 var temp = copy.stat_cat_entries();
360 if (!temp) temp = [];
361 temp = util.functional.filter_list(
364 return (obj.stat_cat() != sc_id);
367 if (entry_id > -1) temp.push(
368 util.functional.find_id_object_in_list(
369 g.data.hash.asc[sc_id].entries(),
373 copy.stat_cat_entries( temp );
376 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
381 /******************************************************************************************************/
382 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
385 g.apply_owning_lib = function(ou_id) {
386 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
387 for (var i = 0; i < g.copies.length; i++) {
388 var copy = g.copies[i];
390 if (!g.map_acn[copy.call_number()]) {
391 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
392 if (typeof volume.ilsevent != 'undefined') {
393 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);
396 g.map_acn[copy.call_number()] = volume;
398 var old_volume = g.map_acn[copy.call_number()];
399 var acn_id = g.network.simple_request(
400 'FM_ACN_FIND_OR_CREATE',
401 [ses(),old_volume.label(),old_volume.record(),ou_id]
403 if (typeof acn_id.ilsevent != 'undefined') {
404 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);
407 copy.call_number(acn_id);
410 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
415 /******************************************************************************************************/
416 /* This returns true if none of the copies being edited are pre-cats */
418 g.safe_to_change_owning_lib = function() {
421 for (var i = 0; i < g.copies.length; i++) {
422 var cn = g.copies[i].call_number();
423 if (typeof cn == 'object') { cn = cn.id(); }
424 if (cn == -1) { safe = false; }
428 g.error.standard_unexpected_error_alert('safe_to_change_owning_lib?',E);
433 /******************************************************************************************************/
434 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
436 g.safe_to_edit_copy_status = function() {
439 for (var i = 0; i < g.copies.length; i++) {
440 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
441 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
445 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
450 /******************************************************************************************************/
451 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
453 g.populate_alert_message_input = function(tb) {
455 var seen = {}; var s = '';
456 for (var i = 0; i < g.copies.length; i++) {
457 var msg = g.copies[i].alert_message();
459 if (typeof seen[msg] == 'undefined') {
465 tb.setAttribute('value',s);
467 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
471 /******************************************************************************************************/
472 /* This returns a list of acpl's appropriate for the copies being edited */
474 g.get_acpl_list = function() {
477 JSAN.use('util.functional');
479 function get(lib_id,only_these) {
480 g.data.stash_retrieve();
481 var label = 'acpl_list_for_lib_'+lib_id;
482 if (typeof g.data[label] == 'undefined') {
483 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
484 if (typeof robj.ilsevent != 'undefined') throw(robj);
486 for (var j = 0; j < robj.length; j++) {
487 var my_acpl = robj[j];
488 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
489 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
490 g.data.list.acpl.push( my_acpl );
492 var only_this_lib = my_acpl.owning_lib(); if (typeof only_this_lib == 'object') only_this_lib = only_this_lib.id();
493 if (only_these.indexOf( String( only_this_lib ) ) != -1) {
494 temp_list.push( my_acpl );
497 g.data[label] = temp_list; g.data.stash(label,'hash','list');
499 return g.data[label];
502 var temp_acpl_list = [];
504 /* find acpl's based on owning_lib */
507 for (var i = 0; i < g.copies.length; i++) {
508 var cn_id = g.copies[i].call_number();
510 if (! g.map_acn[ cn_id ]) {
511 g.map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
513 var consider_lib = g.map_acn[ cn_id ].owning_lib();
514 if ( libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { libs.push( consider_lib ); }
518 for (var i in g.callnumbers) {
519 var consider_lib = g.callnumbers[i].owning_lib;
520 if (typeof consider_lib == 'object') consider_lib = consider_lib.id();
521 if ( libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { libs.push( consider_lib ); }
524 JSAN.use('util.fm_utils');
525 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
526 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
529 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
530 var acpl_list = get(ancestor, ancestors);
531 if (acpl_list) for (var i = 0; i < acpl_list.length; i++) {
532 if (acpl_list[i] != null) {
533 temp_acpl_list.push(acpl_list[i]);
538 /* find acpl's based on circ_lib */
542 for (var i = 0; i < g.copies.length; i++) {
543 var consider_lib = g.copies[i].circ_lib();
544 if (typeof consider_lib == 'object') consider_lib = consider_lib.id();
545 if ( circ_libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { circ_libs.push( consider_lib ); }
548 if (circ_libs.length > 0) {
549 var circ_ancestor = util.fm_utils.find_common_aou_ancestor( circ_libs );
550 if (typeof circ_ancestor == 'object' && circ_ancestor != null) circ_ancestor = circ_ancestor.id();
553 var circ_ancestors = util.fm_utils.find_common_aou_ancestors( circ_libs );
554 var circ_acpl_list = get(circ_ancestor, circ_ancestors);
555 var flat_acpl_list = util.functional.map_list( temp_acpl_list, function(o){return o.id();} );
556 for (var i = 0; i < circ_acpl_list.length; i++) {
557 var consider_acpl = circ_acpl_list[i].id();
558 if ( flat_acpl_list.indexOf( String( consider_acpl ) ) > -1 ) {
559 /* already in list */
561 if (circ_acpl_list[i] != null) temp_acpl_list.push( circ_acpl_list[i] );
567 return temp_acpl_list;
570 g.error.standard_unexpected_error_alert('get_acpl_list',E);
576 /******************************************************************************************************/
577 /* This keeps track of what fields have been edited for styling purposes */
581 /******************************************************************************************************/
582 /* These need data from the middle layer to render */
584 g.special_exception = {
585 'Owning Lib : Call Number' : function(label,value) {
586 JSAN.use('util.widgets');
587 if (value>0) { /* an existing call number */
589 api.FM_ACN_RETRIEVE.app,
590 api.FM_ACN_RETRIEVE.method,
593 var cn = '??? id = ' + value;
595 cn = req.getResultObject();
597 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
599 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
602 } else { /* a yet to be created call number */
604 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
608 'Creator' : function(label,value) {
609 if (value == null || value == '' || value == 'null') return;
610 g.network.simple_request(
611 'FM_AU_RETRIEVE_VIA_ID',
614 var p = '??? id = ' + value;
616 p = req.getResultObject();
620 g.error.sdump('D_ERROR','patron retrieve: ' + E);
622 JSAN.use('util.widgets');
623 util.widgets.set_text(label,p);
627 'Last Editor' : function(label,value) {
628 if (value == null || value == '' || value == 'null') return;
629 g.network.simple_request(
630 'FM_AU_RETRIEVE_VIA_ID',
633 var p = '??? id = ' + value;
635 p = req.getResultObject();
639 g.error.sdump('D_ERROR','patron retrieve: ' + E);
641 util.widgets.set_text(label,p);
648 /******************************************************************************************************/
649 g.readonly_stat_cat_names = [];
650 g.editable_stat_cat_names = [];
652 /******************************************************************************************************/
653 /* These get show in the left panel */
655 function init_panes() {
656 g.panes_and_field_names = {
663 render: 'fm.barcode();',
669 render: 'util.date.formatted_date( fm.create_date(), "%F");',
675 render: 'fm.creator();',
681 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
687 render: 'fm.editor();',
698 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
699 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);',
704 "Circulation Library",
706 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
707 //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);',
708 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);',
712 "Owning Lib : Call Number",
714 render: 'fm.call_number();',
715 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,
721 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
722 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);',
734 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
735 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);',
741 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
742 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);',
748 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
749 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);',
756 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
757 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);',
764 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
765 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);',
772 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
773 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);',
777 "Circulation Modifier",
779 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
780 /*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);',*/
781 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);',
790 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
791 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);',
798 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
799 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);',
805 render: 'if (fm.deposit_amount() == null) { "<Unset>"; } else { util.money.sanitize( fm.deposit_amount() ); }',
806 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);',
812 render: 'if (fm.price() == null) { "<Unset>"; } else { util.money.sanitize( fm.price() ); }',
813 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);',
820 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
821 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);',
827 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
828 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);',
840 /******************************************************************************************************/
841 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
843 g.summarize = function( copies ) {
844 /******************************************************************************************************/
847 JSAN.use('util.date'); JSAN.use('util.money');
850 for (var i in g.panes_and_field_names) {
851 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
853 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
854 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
856 /******************************************************************************************************/
857 /* Loop through the field names */
859 for (var i = 0; i < g.field_names.length; i++) {
861 var field_name = g.field_names[i][0];
862 var render = g.field_names[i][1].render;
863 var attr = g.field_names[i][1].attr;
864 g.summary[ field_name ] = {};
866 /******************************************************************************************************/
867 /* Loop through the copies */
869 for (var j = 0; j < copies.length; j++) {
872 var cmd = render || ('fm.' + field_name + '();');
875 /**********************************************************************************************/
876 /* Try to retrieve the value for this field for this copy */
881 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
883 if (typeof value == 'object' && value != null) {
884 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
887 /**********************************************************************************************/
888 /* Tally the count */
890 if (g.summary[ field_name ][ value ]) {
891 g.summary[ field_name ][ value ]++;
893 g.summary[ field_name ][ value ] = 1;
897 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
900 /******************************************************************************************************/
901 /* Display the summarized data and inputs for editing */
903 g.render = function() {
905 /******************************************************************************************************/
906 /* Library setup and clear any existing interface */
908 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
910 for (var i in g.panes_and_field_names) {
911 var p = document.getElementById(i);
912 if (p) util.widgets.remove_children(p);
915 /******************************************************************************************************/
916 /* Populate the library filter menu for stat cats */
919 for (var i = 0; i < g.panes_and_field_names.right_pane4.length; i++) {
920 sc_libs[ g.panes_and_field_names.right_pane4[i][1].attr.sc_lib ] = true;
923 for (var i in sc_libs) { sc_libs2.push( [ g.data.hash.aou[ i ].shortname(), i ] ); }
925 var x = document.getElementById("stat_cat_lib_filter_menu").firstChild;
926 JSAN.use('util.widgets'); util.widgets.remove_children(x);
927 for (var i = 0; i < sc_libs2.length; i++) {
928 var menuitem = document.createElement('menuitem');
929 menuitem.setAttribute('id','filter_'+sc_libs2[i][1]);
930 menuitem.setAttribute('type','checkbox');
931 menuitem.setAttribute('checked','true');
932 menuitem.setAttribute('label',sc_libs2[i][0]);
933 menuitem.setAttribute('value',sc_libs2[i][1]);
934 menuitem.setAttribute('oncommand','try{g.toggle_stat_cat_display(this);}catch(E){alert(E);}');
935 x.appendChild(menuitem);
938 /******************************************************************************************************/
939 /* Prepare the panes */
941 var groupbox; var caption; var vbox; var grid; var rows;
943 /******************************************************************************************************/
944 /* Loop through the field names */
946 for (h in g.panes_and_field_names) {
947 if (!document.getElementById(h)) continue;
948 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
950 var f = g.panes_and_field_names[h][i]; var fn = f[0]; var attr = f[1].attr;
951 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
953 for (var a in attr) {
954 groupbox.setAttribute(a,attr[a]);
957 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
958 caption = document.createElement('caption'); groupbox.appendChild(caption);
959 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
960 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
961 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
962 grid.setAttribute('flex','1');
963 rows = grid.lastChild;
966 /**************************************************************************************/
967 /* Loop through each value for the field */
969 for (var j in g.summary[fn]) {
970 var value = j; var count = g.summary[fn][j];
971 row = document.createElement('row'); rows.appendChild(row);
972 var label1 = document.createElement('description'); row.appendChild(label1);
973 if (g.special_exception[ fn ]) {
974 g.special_exception[ fn ]( label1, value );
976 label1.appendChild( document.createTextNode(value) );
978 var label2 = document.createElement('description'); row.appendChild(label2);
979 var unit = count == 1 ? 'copy' : 'copies';
980 label2.appendChild( document.createTextNode(count + ' ' + unit) );
982 var hbox = document.createElement('hbox');
983 hbox.setAttribute('id',fn);
984 groupbox.appendChild(hbox);
985 var hbox2 = document.createElement('hbox');
986 groupbox.appendChild(hbox2);
988 /**************************************************************************************/
989 /* Render the input widget */
991 if (f[1].input && g.edit) {
992 g.render_input(hbox,f[1]);
996 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1002 /******************************************************************************************************/
1003 /* Synchronize stat cat visibility with library filter menu, and default template selection */
1004 JSAN.use('util.file');
1005 var file = new util.file('copy_editor_prefs.'+g.data.server_unadorned);
1006 g.copy_editor_prefs = util.widgets.load_attributes(file);
1007 for (var i in g.copy_editor_prefs) {
1008 if (i.match(/filter_/) && g.copy_editor_prefs[i].checked == '') {
1010 g.toggle_stat_cat_display( document.getElementById(i) );
1011 } catch(E) { alert(E); }
1014 g.template_menu.value = g.template_menu.getAttribute('value');
1018 /******************************************************************************************************/
1019 /* This actually draws the change button and input widget for a given field */
1020 g.render_input = function(node,blob) {
1022 // node = hbox ; groupbox -> hbox, hbox
1024 var groupbox = node.parentNode;
1025 var caption = groupbox.firstChild;
1026 var vbox = node.previousSibling;
1028 var hbox2 = node.nextSibling;
1030 var input_cmd = blob.input;
1031 var render_cmd = blob.render;
1032 var attr = blob.attr;
1034 var block = false; var first = true;
1036 function on_mouseover(ev) {
1037 groupbox.setAttribute('style','background: white');
1040 function on_mouseout(ev) {
1041 groupbox.setAttribute('style','');
1044 vbox.addEventListener('mouseover',on_mouseover,false);
1045 vbox.addEventListener('mouseout',on_mouseout,false);
1046 groupbox.addEventListener('mouseover',on_mouseover,false);
1047 groupbox.addEventListener('mouseout',on_mouseout,false);
1048 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1049 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1051 function on_click(ev){
1053 if (block) return; block = true;
1055 function post_c(v) {
1057 /* FIXME - kludgy */
1058 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1062 f = input_cmd.match(/apply\("(.+?)",/)[1];
1065 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1071 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1075 g.summarize( g.copies );
1077 document.getElementById(caption.id).focus();
1081 g.error.standard_unexpected_error_alert('post_c',E);
1084 var x; var c; eval( input_cmd );
1086 util.widgets.remove_children(vbox);
1087 util.widgets.remove_children(hbox);
1088 util.widgets.remove_children(hbox2);
1089 hbox.appendChild(x);
1090 var apply = document.createElement('button');
1091 apply.setAttribute('label','Apply');
1092 apply.setAttribute('accesskey','A');
1093 hbox2.appendChild(apply);
1094 apply.addEventListener('command',function() { c(x.value); },false);
1095 var cancel = document.createElement('button');
1096 cancel.setAttribute('label','Cancel');
1097 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1098 hbox2.appendChild(cancel);
1099 setTimeout( function() { x.focus(); }, 0 );
1102 g.error.standard_unexpected_error_alert('render_input',E);
1105 vbox.addEventListener('click',on_click, false);
1106 hbox.addEventListener('click',on_click, false);
1107 caption.addEventListener('click',on_click, false);
1108 caption.addEventListener('keypress',function(ev) {
1109 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1111 caption.setAttribute('style','-moz-user-focus: normal');
1112 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1113 caption.setAttribute('onblur','this.setAttribute("class","")');
1116 g.error.sdump('D_ERROR',E + '\n');
1120 /******************************************************************************************************/
1121 /* store the copies in the global xpcom stash */
1123 g.stash_and_close = function() {
1125 if (g.handle_update) {
1127 var r = g.network.request(
1128 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1129 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1130 [ ses(), g.copies, true ]
1132 if (typeof r.ilsevent != 'undefined') {
1133 g.error.standard_unexpected_error_alert('copy update',r);
1135 alert('Items added/modified.');
1137 /* FIXME -- revisit the return value here */
1139 alert('copy update error: ' + js2JSON(E));
1142 //g.data.temp_copies = js2JSON( g.copies );
1143 //g.data.stash('temp_copies');
1144 xulG.copies = g.copies;
1145 update_modal_xulG(xulG);
1148 g.error.standard_unexpected_error_alert('stash and close',E);
1152 /******************************************************************************************************/
1153 /* spawn copy notes interface */
1155 g.copy_notes = function() {
1156 JSAN.use('util.window'); var win = new util.window();
1158 urls.XUL_COPY_NOTES,
1159 //+ '?copy_id=' + window.escape(g.copies[0].id()),
1160 'Copy Notes','chrome,resizable,modal',
1161 { 'copy_id' : g.copies[0].id() }
1165 /******************************************************************************************************/
1166 /* hides or unhides stat cats based on library stat cat filter menu */
1167 g.toggle_stat_cat_display = function(el) {
1169 var visible = el.getAttribute('checked');
1170 var nl = document.getElementsByAttribute('sc_lib',el.getAttribute('value'));
1171 for (var n = 0; n < nl.length; n++) {
1173 nl[n].setAttribute('hidden','false');
1175 nl[n].setAttribute('hidden','true');
1178 g.copy_editor_prefs[ el.getAttribute('id') ] = { 'checked' : visible };
1179 g.save_attributes();
1182 /******************************************************************************************************/
1183 /* This adds a stat cat definition to the stat cat pane for rendering */
1184 g.save_attributes = function() {
1185 JSAN.use('util.widgets'); JSAN.use('util.file'); var file = new util.file('copy_editor_prefs.'+g.data.server_unadorned);
1186 var what_to_save = {};
1187 for (var i in g.copy_editor_prefs) {
1188 what_to_save[i] = [];
1189 for (var j in g.copy_editor_prefs[i]) what_to_save[i].push(j);
1191 util.widgets.save_attributes(file, what_to_save );
1194 /******************************************************************************************************/
1195 /* This adds a stat cat definition to the stat cat pane for rendering */
1196 g.add_stat_cat = function(sc) {
1198 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; g.data.stash('hash'); }
1202 if (typeof sc == 'object') {
1207 if (typeof g.stat_cat_seen[sc_id] != 'undefined') { return; }
1209 g.stat_cat_seen[ sc_id ] = 1;
1211 if (typeof sc != 'object') {
1213 sc = g.network.simple_request(
1214 'FM_ASC_BATCH_RETRIEVE',
1215 [ ses(), [ sc_id ] ]
1220 g.data.hash.asc[ sc.id() ] = sc; g.data.stash('hash');
1222 var label_name = g.data.hash.aou[ sc.owner() ].shortname() + " : " + sc.name();
1227 render: 'var l = util.functional.find_list( fm.stat_cat_entries(), function(e){ return e.stat_cat() == '
1228 + sc.id() + '; } ); l ? l.value() : "<Unset>";',
1229 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()
1230 + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ) ).sort() ); '
1231 + 'x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c),false);',
1238 g.panes_and_field_names.right_pane4.push( temp_array );
1240 g.error.standard_unexpected_error_alert('Error adding stat cat to display definition',E);
1244 /******************************************************************************************************/
1245 /* Add stat cats to the panes_and_field_names.right_pane4 */
1246 g.populate_stat_cats = function() {
1248 g.data.stash_retrieve();
1249 g.stat_cat_seen = {};
1251 function get(lib_id,only_these) {
1252 g.data.stash_retrieve();
1253 var label = 'asc_list_for_lib_'+lib_id;
1254 if (typeof g.data[label] == 'undefined') {
1255 var robj = g.network.simple_request('FM_ASC_RETRIEVE_VIA_AOU', [ ses(), lib_id ]);
1256 if (typeof robj.ilsevent != 'undefined') throw(robj);
1258 for (var j = 0; j < robj.length; j++) {
1259 var my_asc = robj[j];
1260 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; }
1261 if (typeof g.data.hash.asc[ my_asc.id() ] == 'undefined') {
1262 g.data.hash.asc[ my_asc.id() ] = my_asc;
1264 var only_this_lib = my_asc.owner(); if (typeof only_this_lib == 'object') only_this_lib = only_this_lib.id();
1265 if (only_these.indexOf( String( only_this_lib ) ) != -1) {
1266 temp_list.push( my_asc );
1269 g.data[label] = temp_list; g.data.stash(label,'hash','list');
1271 return g.data[label];
1274 /* The stat cats for the pertinent library -- this is based on workstation ou */
1275 var label = 'asc_list_for_' + typeof g.data.ws_ou == 'object' ? g.data.ws_ou.id() : g.data.ws_ou;
1276 g.data[ label ] = g.data.list.my_asc; g.data.stash('label');
1277 for (var i = 0; i < g.data.list.my_asc.length; i++) {
1278 g.add_stat_cat( g.data.list.my_asc[i] );
1281 /* For the others, we want to consider the owning libs, circ libs, and any libs that have stat cats already on the copies,
1282 however, if batch editing, we only want to show the ones they have in common. So let's compile the libs */
1284 function add_common_ancestors(sc_libs) {
1285 JSAN.use('util.fm_utils');
1286 var libs = []; for (var i in sc_libs) libs.push(i);
1287 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
1288 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
1290 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
1291 var asc_list = get(ancestor, ancestors);
1292 for (var i = 0; i < asc_list.length; i++) {
1293 g.add_stat_cat( asc_list[i] );
1298 /* stat cats based on stat cat entries present on these copies */
1300 for (var i = 0; i < g.copies.length; i++) {
1301 var entries = g.copies[i].stat_cat_entries();
1302 if (!entries) entries = [];
1303 for (var j = 0; j < entries.length; j++) {
1304 var lib = entries[j].owner(); if (typeof lib == 'object') lib = lib.id();
1305 sc_libs[ lib ] = true;
1308 add_common_ancestors(sc_libs); // CAVEAT - if a copy has no stat_cat_entries, it basically gets no vote here
1310 /* stat cats based on Circ Lib */
1312 for (var i = 0; i < g.copies.length; i++) {
1313 var circ_lib = g.copies[i].circ_lib(); if (typeof circ_lib == 'object') circ_lib = circ_lib.id();
1314 sc_libs[ circ_lib ] = true;
1316 add_common_ancestors(sc_libs);
1318 /* stat cats based on Owning Lib */
1320 for (var i = 0; i < g.copies.length; i++) {
1321 var cn_id = g.copies[i].call_number();
1323 if (! g.map_acn[ cn_id ]) {
1324 g.map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
1326 var owning_lib = g.map_acn[ cn_id ].owning_lib(); if (typeof owning_lib == 'object') owning_lib = owning_lib.id();
1327 sc_libs[ owning_lib ] = true;
1330 add_common_ancestors(sc_libs); // CAVEAT - if a copy is a pre-cat, it basically gets no vote here
1332 g.panes_and_field_names.right_pane4.sort();
1335 g.error.standard_unexpected_error_alert('Error populating stat cats for display',E);