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.stat_cat_seen = {};
104 function add_stat_cat(sc) {
106 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; g.data.stash('hash'); }
110 if (typeof sc == 'object') {
115 if (typeof g.stat_cat_seen[sc_id] != 'undefined') { return; }
117 g.stat_cat_seen[ sc_id ] = 1;
119 if (typeof sc != 'object') {
121 sc = g.network.simple_request(
122 'FM_ASC_BATCH_RETRIEVE',
128 g.data.hash.asc[ sc.id() ] = sc; g.data.stash('hash');
130 var label_name = g.data.hash.aou[ sc.owner() ].shortname() + " : " + sc.name();
135 render: 'var l = util.functional.find_list( fm.stat_cat_entries(), function(e){ return e.stat_cat() == '
136 + sc.id() + '; } ); l ? l.value() : "<Unset>";',
137 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()
138 + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ) ).sort() ); '
139 + 'x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c),false);',
146 dump('temp_array = ' + js2JSON(temp_array) + '\n');
148 g.panes_and_field_names.right_pane4.push( temp_array );
151 /* The stat cats for the pertinent library -- this is based on workstation ou */
152 for (var i = 0; i < g.data.list.my_asc.length; i++) {
153 add_stat_cat( g.data.list.my_asc[i] );
156 /* Other stat cats present on these copies */
157 for (var i = 0; i < g.copies.length; i++) {
158 var entries = g.copies[i].stat_cat_entries();
159 if (!entries) entries = [];
160 for (var j = 0; j < entries.length; j++) {
161 var sc_id = entries[j].stat_cat();
162 add_stat_cat( sc_id );
166 g.panes_and_field_names.right_pane4.sort();
168 /******************************************************************************************************/
169 /* Backup copies :) */
171 g.original_copies = js2JSON( g.copies );
173 /******************************************************************************************************/
176 g.summarize( g.copies );
180 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
181 "system administrator or software developer the following:\ncat/copy_editor.xul\n" + E + '\n';
182 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
187 /******************************************************************************************************/
188 /* File picker for template export/import */
190 function pick_file(mode) {
191 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
192 var nsIFilePicker = Components.interfaces.nsIFilePicker;
193 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance( nsIFilePicker );
196 mode == 'open' ? "Import Templates File" : "Save Templates File As",
197 mode == 'open' ? nsIFilePicker.modeOpen : nsIFilePicker.modeSave
199 fp.appendFilters( nsIFilePicker.filterAll );
200 var fp_result = fp.show();
201 if ( ( fp_result == nsIFilePicker.returnOK || fp_result == nsIFilePicker.returnReplace ) && fp.file ) {
208 /******************************************************************************************************/
209 /* Retrieve Templates */
211 g.retrieve_templates = function() {
213 JSAN.use('util.widgets'); JSAN.use('util.functional');
215 var robj = g.network.simple_request('FM_AUS_RETRIEVE',[ses(),g.data.list.au[0].id()]);
216 if (typeof robj['staff_client.copy_editor.templates'] != 'undefined') {
217 g.templates = robj['staff_client.copy_editor.templates'];
219 util.widgets.remove_children('template_placeholder');
220 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
222 g.template_menu = util.widgets.make_menulist( list );
223 $('template_placeholder').appendChild(g.template_menu);
225 g.error.standard_unexpected_error_alert('Error retrieving templates',E);
229 /******************************************************************************************************/
232 g.apply_template = function() {
234 var name = g.template_menu.value;
235 if (g.templates[ name ] != 'undefined') {
236 var template = g.templates[ name ];
237 for (var i in template) {
238 g.changed[ i ] = template[ i ];
239 switch( template[i].type ) {
241 g.apply(template[i].field,template[i].value);
244 if (g.stat_cat_seen[ template[i].field ]) g.apply_stat_cat(template[i].field,template[i].value);
247 g.apply_owning_lib(template[i].value);
251 g.summarize( g.copies );
255 g.error.standard_unexpected_error_alert('Error applying template',E);
259 /******************************************************************************************************/
260 /* Save as Template */
262 g.save_template = function() {
264 var name = window.prompt('Enter template name:','','Save As Template');
266 g.templates[name] = g.changed;
267 var robj = g.network.simple_request(
268 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
270 if (typeof robj.ilsevent != 'undefined') {
273 alert('Template "' + name + '" saved.');
277 g.retrieve_templates();
279 g.error.standard_unexpected_error_alert('Error saving template',E);
285 g.error.standard_unexpected_error_alert('Error saving template',E);
289 /******************************************************************************************************/
290 /* Delete Template */
292 g.delete_template = function() {
294 var name = g.template_menu.value;
296 if (! window.confirm('Delete template "' + name + '"?') ) return;
297 delete(g.templates[name]);
298 var robj = g.network.simple_request(
299 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
301 if (typeof robj.ilsevent != 'undefined') {
304 alert('Template "' + name + '" deleted.');
308 g.retrieve_templates();
310 g.error.standard_unexpected_error_alert('Error deleting template',E);
316 g.error.standard_unexpected_error_alert('Error deleting template',E);
320 /******************************************************************************************************/
321 /* Export Templates */
323 g.export_templates = function() {
325 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
326 JSAN.use('util.file');
327 var f = pick_file('save');
330 var r = G.error.yns_alert(
331 'Would you like to overwrite the existing file ' + f.leafName + '?',
332 'Templates Export Warning',
336 'Check here to confirm this message'
338 if (r != 0) { file.close(); alert('Not overwriting file.'); return; }
340 var e_file = new util.file(''); e_file._file = f;
341 e_file.write_content( 'truncate', js2JSON( g.templates ) );
343 alert('Templates exported as file ' + f.leafName);
345 alert('File not chosen for export.');
349 g.error.standard_unexpected_error_alert('Error exporting templates',E);
353 /******************************************************************************************************/
354 /* Import Templates */
356 g.import_templates = function() {
358 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
359 JSAN.use('util.file');
360 var f = pick_file('open');
361 if (f && f.exists()) {
362 var i_file = new util.file(''); i_file._file = f;
363 var temp = JSON2js( i_file.get_content() );
365 for (var i in temp) {
367 if (g.templates[i]) {
369 var r = g.error.yns_alert(
370 'Replace the existing template with the imported template?\n' + g.error.pretty_print( js2JSON( temp[i] ) ),
371 'Template ' + i + ' already exists.','Yes','No',null,'Click here'
374 if (r == 0 /* Yes */) g.templates[i] = temp[i];
378 g.templates[i] = temp[i];
384 var r = g.error.yns_alert(
385 'Save all of these imported templates permanently to this account?',
386 'Final Warning', 'Yes', 'No', null, 'Click here'
389 if (r == 0 /* Yes */) {
390 var robj = g.network.simple_request(
391 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
393 if (typeof robj.ilsevent != 'undefined') {
396 alert('All templates saved.');
400 g.retrieve_templates();
402 g.error.standard_unexpected_error_alert('Error saving templates',E);
408 util.widgets.remove_children('template_placeholder');
409 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
410 g.template_menu = util.widgets.make_menulist( list );
411 $('template_placeholder').appendChild(g.template_menu);
412 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 dissappear with the next invocation of the item attribute editor.");
416 alert('File not chosen for import.');
419 g.error.standard_unexpected_error_alert('Error importing templates',E);
424 /******************************************************************************************************/
425 /* Restore backup copies */
427 g.reset = function() {
429 g.copies = JSON2js( g.original_copies );
430 g.summarize( g.copies );
434 /******************************************************************************************************/
435 /* Apply a value to a specific field on all the copies being edited */
437 g.apply = function(field,value) {
438 g.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
439 if (value == '<HACK:KLUDGE:NULL>') value = null;
440 if (field == 'alert_message') { value = value.replace(/^\W+$/g,''); }
441 if (field == 'price' || field == 'deposit_amount') {
442 if (value == '') { value = null; } else { JSAN.use('util.money'); value = util.money.sanitize( value ); }
444 for (var i = 0; i < g.copies.length; i++) {
445 var copy = g.copies[i];
447 copy[field]( value ); copy.ischanged('1');
454 /******************************************************************************************************/
455 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
457 g.apply_stat_cat = function(sc_id,entry_id) {
458 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
459 for (var i = 0; i < g.copies.length; i++) {
460 var copy = g.copies[i];
463 var temp = copy.stat_cat_entries();
464 if (!temp) temp = [];
465 temp = util.functional.filter_list(
468 return (obj.stat_cat() != sc_id);
471 if (entry_id > -1) temp.push(
472 util.functional.find_id_object_in_list(
473 g.data.hash.asc[sc_id].entries(),
477 copy.stat_cat_entries( temp );
480 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
485 /******************************************************************************************************/
486 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
488 g.apply_owning_lib = function(ou_id) {
489 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
491 for (var i = 0; i < g.copies.length; i++) {
492 var copy = g.copies[i];
494 if (!map_acn[copy.call_number()]) {
495 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
496 if (typeof volume.ilsevent != 'undefined') {
497 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);
500 map_acn[copy.call_number()] = volume;
502 var old_volume = map_acn[copy.call_number()];
503 var acn_id = g.network.simple_request(
504 'FM_ACN_FIND_OR_CREATE',
505 [ses(),old_volume.label(),old_volume.record(),ou_id]
507 if (typeof acn_id.ilsevent != 'undefined') {
508 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);
511 copy.call_number(acn_id);
514 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
519 /******************************************************************************************************/
520 /* This returns true if none of the copies being edited are pre-cats */
522 g.safe_to_change_owning_lib = function() {
525 for (var i = 0; i < g.copies.length; i++) {
526 var cn = g.copies[i].call_number();
527 if (typeof cn == 'object') { cn = cn.id(); }
528 if (cn == -1) { safe = false; }
532 g.error.standard_unexpected_error_alert('safe_to_change_owning_lib?',E);
537 /******************************************************************************************************/
538 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
540 g.safe_to_edit_copy_status = function() {
543 for (var i = 0; i < g.copies.length; i++) {
544 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
545 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
549 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
554 /******************************************************************************************************/
555 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
557 g.populate_alert_message_input = function(tb) {
559 var seen = {}; var s = '';
560 for (var i = 0; i < g.copies.length; i++) {
561 var msg = g.copies[i].alert_message();
563 if (typeof seen[msg] == 'undefined') {
569 tb.setAttribute('value',s);
571 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
575 /******************************************************************************************************/
576 /* This returns a list of acpl's appropriate for the copies being edited */
578 g.get_acpl_list = function() {
581 JSAN.use('util.functional');
583 function get(lib_id,only_these) {
584 g.data.stash_retrieve();
585 var label = 'acpl_list_for_lib_'+lib_id;
586 if (typeof g.data[label] == 'undefined') {
587 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
588 if (typeof robj.ilsevent != 'undefined') throw(robj);
590 for (var j = 0; j < robj.length; j++) {
591 var my_acpl = robj[j];
592 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
593 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
594 g.data.list.acpl.push( my_acpl );
596 var only_this_lib = my_acpl.owning_lib(); if (typeof only_this_lib == 'object') only_this_lib = only_this_lib.id();
597 if (only_these.indexOf( String( only_this_lib ) ) != -1) {
598 temp_list.push( my_acpl );
601 g.data[label] = temp_list; g.data.stash(label,'hash','list');
603 return g.data[label];
606 var temp_acpl_list = [];
608 /* find acpl's based on owning_lib */
610 var libs = []; var map_acn = {};
611 for (var i = 0; i < g.copies.length; i++) {
612 var cn_id = g.copies[i].call_number();
614 if (! map_acn[ cn_id ]) {
615 map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
616 var consider_lib = map_acn[ cn_id ].owning_lib();
617 if ( libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { libs.push( consider_lib ); }
622 for (var i in g.callnumbers) {
623 var consider_lib = g.callnumbers[i].owning_lib;
624 if (typeof consider_lib == 'object') consider_lib = consider_lib.id();
625 if ( libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { libs.push( consider_lib ); }
628 JSAN.use('util.fm_utils');
629 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
630 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
632 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
635 var acpl_list = get(ancestor, ancestors);
636 if (acpl_list) for (var i = 0; i < acpl_list.length; i++) {
637 if (acpl_list[i] != null) {
638 temp_acpl_list.push(acpl_list[i]);
643 /* find acpl's based on circ_lib */
647 for (var i = 0; i < g.copies.length; i++) {
648 var consider_lib = g.copies[i].circ_lib();
649 if (typeof consider_lib == 'object') consider_lib = consider_lib.id();
650 if ( circ_libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { circ_libs.push( consider_lib ); }
653 if (circ_libs.length > 0) {
654 var circ_ancestor = util.fm_utils.find_common_aou_ancestor( circ_libs );
655 if (typeof circ_ancestor == 'object' && circ_ancestor != null) circ_ancestor = circ_ancestor.id();
657 circ_ancestors = util.fm_utils.find_common_aou_ancestors( circ_libs );
660 var circ_acpl_list = get(circ_ancestor, circ_ancestors);
661 var flat_acpl_list = util.functional.map_list( temp_acpl_list, function(o){return o.id();} );
662 for (var i = 0; i < circ_acpl_list.length; i++) {
663 var consider_acpl = circ_acpl_list[i].id();
664 if ( flat_acpl_list.indexOf( String( consider_acpl ) ) > -1 ) {
665 /* already in list */
667 if (circ_acpl_list[i] != null) temp_acpl_list.push( circ_acpl_list[i] );
673 return temp_acpl_list;
676 g.error.standard_unexpected_error_alert('get_acpl_list',E);
682 /******************************************************************************************************/
683 /* This keeps track of what fields have been edited for styling purposes */
687 /******************************************************************************************************/
688 /* These need data from the middle layer to render */
690 g.special_exception = {
691 'Owning Lib : Call Number' : function(label,value) {
692 JSAN.use('util.widgets');
693 if (value>0) { /* an existing call number */
695 api.FM_ACN_RETRIEVE.app,
696 api.FM_ACN_RETRIEVE.method,
699 var cn = '??? id = ' + value;
701 cn = req.getResultObject();
703 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
705 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
708 } else { /* a yet to be created call number */
710 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
714 'Creator' : function(label,value) {
715 if (value == null || value == '' || value == 'null') return;
716 g.network.simple_request(
717 'FM_AU_RETRIEVE_VIA_ID',
720 var p = '??? id = ' + value;
722 p = req.getResultObject();
726 g.error.sdump('D_ERROR','patron retrieve: ' + E);
728 JSAN.use('util.widgets');
729 util.widgets.set_text(label,p);
733 'Last Editor' : function(label,value) {
734 if (value == null || value == '' || value == 'null') return;
735 g.network.simple_request(
736 'FM_AU_RETRIEVE_VIA_ID',
739 var p = '??? id = ' + value;
741 p = req.getResultObject();
745 g.error.sdump('D_ERROR','patron retrieve: ' + E);
747 util.widgets.set_text(label,p);
754 /******************************************************************************************************/
755 g.readonly_stat_cat_names = [];
756 g.editable_stat_cat_names = [];
758 /******************************************************************************************************/
759 /* These get show in the left panel */
761 function init_panes() {
762 g.panes_and_field_names = {
769 render: 'fm.barcode();',
775 render: 'util.date.formatted_date( fm.create_date(), "%F");',
781 render: 'fm.creator();',
787 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
793 render: 'fm.editor();',
804 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
805 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);',
810 "Circulation Library",
812 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
813 //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);',
814 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);',
818 "Owning Lib : Call Number",
820 render: 'fm.call_number();',
821 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,
827 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
828 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);',
840 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
841 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);',
847 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
848 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);',
854 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
855 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);',
862 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
863 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);',
870 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
871 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);',
878 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
879 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);',
883 "Circulation Modifier",
885 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
886 /*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);',*/
887 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);',
896 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
897 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);',
904 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
905 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);',
911 render: 'if (fm.deposit_amount() == null) { "<Unset>"; } else { util.money.sanitize( fm.deposit_amount() ); }',
912 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);',
918 render: 'if (fm.price() == null) { "<Unset>"; } else { util.money.sanitize( fm.price() ); }',
919 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);',
926 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
927 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);',
933 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
934 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);',
946 /******************************************************************************************************/
947 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
949 g.summarize = function( copies ) {
950 /******************************************************************************************************/
953 JSAN.use('util.date'); JSAN.use('util.money');
956 for (var i in g.panes_and_field_names) {
957 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
959 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
960 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
962 /******************************************************************************************************/
963 /* Loop through the field names */
965 for (var i = 0; i < g.field_names.length; i++) {
967 var field_name = g.field_names[i][0];
968 var render = g.field_names[i][1].render;
969 var attr = g.field_names[i][1].attr;
970 g.summary[ field_name ] = {};
972 /******************************************************************************************************/
973 /* Loop through the copies */
975 for (var j = 0; j < copies.length; j++) {
978 var cmd = render || ('fm.' + field_name + '();');
981 /**********************************************************************************************/
982 /* Try to retrieve the value for this field for this copy */
987 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
989 if (typeof value == 'object' && value != null) {
990 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
993 /**********************************************************************************************/
994 /* Tally the count */
996 if (g.summary[ field_name ][ value ]) {
997 g.summary[ field_name ][ value ]++;
999 g.summary[ field_name ][ value ] = 1;
1003 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
1006 /******************************************************************************************************/
1007 /* Display the summarized data and inputs for editing */
1009 g.render = function() {
1011 /******************************************************************************************************/
1012 /* Library setup and clear any existing interface */
1014 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
1016 for (var i in g.panes_and_field_names) {
1017 var p = document.getElementById(i);
1018 if (p) util.widgets.remove_children(p);
1021 /******************************************************************************************************/
1022 /* Populate the library filter menu for stat cats */
1025 for (var i = 0; i < g.panes_and_field_names.right_pane4.length; i++) {
1026 sc_libs[ g.panes_and_field_names.right_pane4[i][1].attr.sc_lib ] = true;
1029 for (var i in sc_libs) { sc_libs2.push( [ g.data.hash.aou[ i ].shortname(), i ] ); }
1031 var x = document.getElementById("stat_cat_lib_filter_menu").firstChild;
1032 JSAN.use('util.widgets'); util.widgets.remove_children(x);
1033 for (var i = 0; i < sc_libs2.length; i++) {
1034 var menuitem = document.createElement('menuitem');
1035 menuitem.setAttribute('type','checkbox');
1036 menuitem.setAttribute('checked','true');
1037 menuitem.setAttribute('label',sc_libs2[i][0]);
1038 menuitem.setAttribute('value',sc_libs2[i][1]);
1039 menuitem.setAttribute('oncommand','try{g.toggle_stat_cat_display(this);}catch(E){alert(E);}');
1040 x.appendChild(menuitem);
1043 /******************************************************************************************************/
1044 /* Prepare the panes */
1046 var groupbox; var caption; var vbox; var grid; var rows;
1048 /******************************************************************************************************/
1049 /* Loop through the field names */
1051 for (h in g.panes_and_field_names) {
1052 if (!document.getElementById(h)) continue;
1053 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
1055 var f = g.panes_and_field_names[h][i]; var fn = f[0]; var attr = f[1].attr;
1056 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
1058 for (var a in attr) {
1059 groupbox.setAttribute(a,attr[a]);
1062 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
1063 caption = document.createElement('caption'); groupbox.appendChild(caption);
1064 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
1065 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
1066 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
1067 grid.setAttribute('flex','1');
1068 rows = grid.lastChild;
1071 /**************************************************************************************/
1072 /* Loop through each value for the field */
1074 for (var j in g.summary[fn]) {
1075 var value = j; var count = g.summary[fn][j];
1076 row = document.createElement('row'); rows.appendChild(row);
1077 var label1 = document.createElement('description'); row.appendChild(label1);
1078 if (g.special_exception[ fn ]) {
1079 g.special_exception[ fn ]( label1, value );
1081 label1.appendChild( document.createTextNode(value) );
1083 var label2 = document.createElement('description'); row.appendChild(label2);
1084 var unit = count == 1 ? 'copy' : 'copies';
1085 label2.appendChild( document.createTextNode(count + ' ' + unit) );
1087 var hbox = document.createElement('hbox');
1088 hbox.setAttribute('id',fn);
1089 groupbox.appendChild(hbox);
1090 var hbox2 = document.createElement('hbox');
1091 groupbox.appendChild(hbox2);
1093 /**************************************************************************************/
1094 /* Render the input widget */
1096 if (f[1].input && g.edit) {
1097 g.render_input(hbox,f[1]);
1101 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1107 /******************************************************************************************************/
1108 /* This actually draws the change button and input widget for a given field */
1109 g.render_input = function(node,blob) {
1111 // node = hbox ; groupbox -> hbox, hbox
1113 var groupbox = node.parentNode;
1114 var caption = groupbox.firstChild;
1115 var vbox = node.previousSibling;
1117 var hbox2 = node.nextSibling;
1119 var input_cmd = blob.input;
1120 var render_cmd = blob.render;
1121 var attr = blob.attr;
1123 var block = false; var first = true;
1125 function on_mouseover(ev) {
1126 groupbox.setAttribute('style','background: white');
1129 function on_mouseout(ev) {
1130 groupbox.setAttribute('style','');
1133 vbox.addEventListener('mouseover',on_mouseover,false);
1134 vbox.addEventListener('mouseout',on_mouseout,false);
1135 groupbox.addEventListener('mouseover',on_mouseover,false);
1136 groupbox.addEventListener('mouseout',on_mouseout,false);
1137 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1138 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1140 function on_click(ev){
1142 if (block) return; block = true;
1144 function post_c(v) {
1146 /* FIXME - kludgy */
1147 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1151 f = input_cmd.match(/apply\("(.+?)",/)[1];
1154 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1160 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1164 g.summarize( g.copies );
1166 document.getElementById(caption.id).focus();
1170 g.error.standard_unexpected_error_alert('post_c',E);
1173 var x; var c; eval( input_cmd );
1175 util.widgets.remove_children(vbox);
1176 util.widgets.remove_children(hbox);
1177 util.widgets.remove_children(hbox2);
1178 hbox.appendChild(x);
1179 var apply = document.createElement('button');
1180 apply.setAttribute('label','Apply');
1181 apply.setAttribute('accesskey','A');
1182 hbox2.appendChild(apply);
1183 apply.addEventListener('command',function() { c(x.value); },false);
1184 var cancel = document.createElement('button');
1185 cancel.setAttribute('label','Cancel');
1186 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1187 hbox2.appendChild(cancel);
1188 setTimeout( function() { x.focus(); }, 0 );
1191 g.error.standard_unexpected_error_alert('render_input',E);
1194 vbox.addEventListener('click',on_click, false);
1195 hbox.addEventListener('click',on_click, false);
1196 caption.addEventListener('click',on_click, false);
1197 caption.addEventListener('keypress',function(ev) {
1198 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1200 caption.setAttribute('style','-moz-user-focus: normal');
1201 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1202 caption.setAttribute('onblur','this.setAttribute("class","")');
1205 g.error.sdump('D_ERROR',E + '\n');
1209 /******************************************************************************************************/
1210 /* store the copies in the global xpcom stash */
1212 g.stash_and_close = function() {
1214 if (g.handle_update) {
1216 var r = g.network.request(
1217 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1218 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1219 [ ses(), g.copies, true ]
1221 if (typeof r.ilsevent != 'undefined') {
1222 g.error.standard_unexpected_error_alert('copy update',r);
1224 alert('Items added/modified.');
1226 /* FIXME -- revisit the return value here */
1228 alert('copy update error: ' + js2JSON(E));
1231 //g.data.temp_copies = js2JSON( g.copies );
1232 //g.data.stash('temp_copies');
1233 xulG.copies = g.copies;
1234 update_modal_xulG(xulG);
1237 g.error.standard_unexpected_error_alert('stash and close',E);
1241 /******************************************************************************************************/
1242 /* spawn copy notes interface */
1244 g.copy_notes = function() {
1245 JSAN.use('util.window'); var win = new util.window();
1247 urls.XUL_COPY_NOTES,
1248 //+ '?copy_id=' + window.escape(g.copies[0].id()),
1249 'Copy Notes','chrome,resizable,modal',
1250 { 'copy_id' : g.copies[0].id() }
1254 /******************************************************************************************************/
1255 /* hides or unhides stat cats based on library stat cat filter menu */
1256 g.toggle_stat_cat_display = function(el) {
1257 var visible = el.getAttribute('checked');
1258 var nl = document.getElementsByAttribute('sc_lib',el.getAttribute('value'));
1259 for (var n = 0; n < nl.length; n++) {
1261 nl[n].setAttribute('hidden','false');
1263 nl[n].setAttribute('hidden','true');