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 //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>", null ] ].concat( util.functional.map_list( g.data.hash.asc[' + sc.id()
140 // + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ).sort() ) ); '
141 + 'x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c),false);',
145 dump('temp_array = ' + js2JSON(temp_array) + '\n');
147 g.panes_and_field_names.right_pane4.push( temp_array );
150 /* The stat cats for the pertinent library */
151 for (var i = 0; i < g.data.list.my_asc.length; i++) {
152 add_stat_cat( g.data.list.my_asc[i] );
155 /* Other stat cats present on these copies */
156 for (var i = 0; i < g.copies.length; i++) {
157 var entries = g.copies[i].stat_cat_entries();
158 if (!entries) entries = [];
159 for (var j = 0; j < entries.length; j++) {
160 var sc_id = entries[j].stat_cat();
161 add_stat_cat( sc_id );
165 /******************************************************************************************************/
166 /* Backup copies :) */
168 g.original_copies = js2JSON( g.copies );
170 /******************************************************************************************************/
173 g.summarize( g.copies );
177 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
178 "system administrator or software developer the following:\ncat/copy_editor.xul\n" + E + '\n';
179 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
184 /******************************************************************************************************/
185 /* File picker for template export/import */
187 function pick_file(mode) {
188 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
189 var nsIFilePicker = Components.interfaces.nsIFilePicker;
190 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance( nsIFilePicker );
193 mode == 'open' ? "Import Templates File" : "Save Templates File As",
194 mode == 'open' ? nsIFilePicker.modeOpen : nsIFilePicker.modeSave
196 fp.appendFilters( nsIFilePicker.filterAll );
197 var fp_result = fp.show();
198 if ( ( fp_result == nsIFilePicker.returnOK || fp_result == nsIFilePicker.returnReplace ) && fp.file ) {
205 /******************************************************************************************************/
206 /* Retrieve Templates */
208 g.retrieve_templates = function() {
210 JSAN.use('util.widgets'); JSAN.use('util.functional');
212 var robj = g.network.simple_request('FM_AUS_RETRIEVE',[ses(),g.data.list.au[0].id()]);
213 if (typeof robj['staff_client.copy_editor.templates'] != 'undefined') {
214 g.templates = robj['staff_client.copy_editor.templates'];
216 util.widgets.remove_children('template_placeholder');
217 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
219 g.template_menu = util.widgets.make_menulist( list );
220 $('template_placeholder').appendChild(g.template_menu);
222 g.error.standard_unexpected_error_alert('Error retrieving templates',E);
226 /******************************************************************************************************/
229 g.apply_template = function() {
231 var name = g.template_menu.value;
232 if (g.templates[ name ] != 'undefined') {
233 var template = g.templates[ name ];
234 for (var i in template) {
235 g.changed[ i ] = template[ i ];
236 switch( template[i].type ) {
238 g.apply(template[i].field,template[i].value);
241 if (g.stat_cat_seen[ template[i].field ]) g.apply_stat_cat(template[i].field,template[i].value);
244 g.apply_owning_lib(template[i].value);
248 g.summarize( g.copies );
252 g.error.standard_unexpected_error_alert('Error applying template',E);
256 /******************************************************************************************************/
257 /* Save as Template */
259 g.save_template = function() {
261 var name = window.prompt('Enter template name:','','Save As Template');
263 g.templates[name] = g.changed;
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 + '" saved.');
274 g.retrieve_templates();
276 g.error.standard_unexpected_error_alert('Error saving template',E);
282 g.error.standard_unexpected_error_alert('Error saving template',E);
286 /******************************************************************************************************/
287 /* Delete Template */
289 g.delete_template = function() {
291 var name = g.template_menu.value;
293 if (! window.confirm('Delete template "' + name + '"?') ) return;
294 delete(g.templates[name]);
295 var robj = g.network.simple_request(
296 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
298 if (typeof robj.ilsevent != 'undefined') {
301 alert('Template "' + name + '" deleted.');
305 g.retrieve_templates();
307 g.error.standard_unexpected_error_alert('Error deleting template',E);
313 g.error.standard_unexpected_error_alert('Error deleting template',E);
317 /******************************************************************************************************/
318 /* Export Templates */
320 g.export_templates = function() {
322 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
323 JSAN.use('util.file');
324 var f = pick_file('save');
327 var r = G.error.yns_alert(
328 'Would you like to overwrite the existing file ' + f.leafName + '?',
329 'Templates Export Warning',
333 'Check here to confirm this message'
335 if (r != 0) { file.close(); alert('Not overwriting file.'); return; }
337 var e_file = new util.file(''); e_file._file = f;
338 e_file.write_content( 'truncate', js2JSON( g.templates ) );
340 alert('Templates exported as file ' + f.leafName);
342 alert('File not chosen for export.');
346 g.error.standard_unexpected_error_alert('Error exporting templates',E);
350 /******************************************************************************************************/
351 /* Import Templates */
353 g.import_templates = function() {
355 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
356 JSAN.use('util.file');
357 var f = pick_file('open');
358 if (f && f.exists()) {
359 var i_file = new util.file(''); i_file._file = f;
360 var temp = JSON2js( i_file.get_content() );
362 for (var i in temp) {
364 if (g.templates[i]) {
366 var r = g.error.yns_alert(
367 'Replace the existing template with the imported template?\n' + g.error.pretty_print( js2JSON( temp[i] ) ),
368 'Template ' + i + ' already exists.','Yes','No',null,'Click here'
371 if (r == 0 /* Yes */) g.templates[i] = temp[i];
375 g.templates[i] = temp[i];
381 var r = g.error.yns_alert(
382 'Save all of these imported templates permanently to this account?',
383 'Final Warning', 'Yes', 'No', null, 'Click here'
386 if (r == 0 /* Yes */) {
387 var robj = g.network.simple_request(
388 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
390 if (typeof robj.ilsevent != 'undefined') {
393 alert('All templates saved.');
397 g.retrieve_templates();
399 g.error.standard_unexpected_error_alert('Error saving templates',E);
405 util.widgets.remove_children('template_placeholder');
406 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
407 g.template_menu = util.widgets.make_menulist( list );
408 $('template_placeholder').appendChild(g.template_menu);
409 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.");
413 alert('File not chosen for import.');
416 g.error.standard_unexpected_error_alert('Error importing templates',E);
421 /******************************************************************************************************/
422 /* Restore backup copies */
424 g.reset = function() {
426 g.copies = JSON2js( g.original_copies );
427 g.summarize( g.copies );
431 /******************************************************************************************************/
432 /* Apply a value to a specific field on all the copies being edited */
434 g.apply = function(field,value) {
435 g.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
436 if (value == '<HACK:KLUDGE:NULL>') value = null;
437 if (field == 'alert_message') { value = value.replace(/^\W+$/g,''); }
438 if (field == 'price' || field == 'deposit_amount') {
439 if (value == '') { value = null; } else { JSAN.use('util.money'); value = util.money.sanitize( value ); }
441 for (var i = 0; i < g.copies.length; i++) {
442 var copy = g.copies[i];
444 copy[field]( value ); copy.ischanged('1');
451 /******************************************************************************************************/
452 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
454 g.apply_stat_cat = function(sc_id,entry_id) {
455 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
456 for (var i = 0; i < g.copies.length; i++) {
457 var copy = g.copies[i];
460 var temp = copy.stat_cat_entries();
461 if (!temp) temp = [];
462 temp = util.functional.filter_list(
465 return (obj.stat_cat() != sc_id);
468 if (entry_id > -1) temp.push(
469 util.functional.find_id_object_in_list(
470 g.data.hash.asc[sc_id].entries(),
474 copy.stat_cat_entries( temp );
477 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
482 /******************************************************************************************************/
483 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
485 g.apply_owning_lib = function(ou_id) {
486 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
488 for (var i = 0; i < g.copies.length; i++) {
489 var copy = g.copies[i];
491 if (!map_acn[copy.call_number()]) {
492 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
493 if (typeof volume.ilsevent != 'undefined') {
494 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);
497 map_acn[copy.call_number()] = volume;
499 var old_volume = map_acn[copy.call_number()];
500 var acn_id = g.network.simple_request(
501 'FM_ACN_FIND_OR_CREATE',
502 [ses(),old_volume.label(),old_volume.record(),ou_id]
504 if (typeof acn_id.ilsevent != 'undefined') {
505 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);
508 copy.call_number(acn_id);
511 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
516 /******************************************************************************************************/
517 /* This returns true if none of the copies being edited are pre-cats */
519 g.safe_to_change_owning_lib = function() {
522 for (var i = 0; i < g.copies.length; i++) {
523 var cn = g.copies[i].call_number();
524 if (typeof cn == 'object') { cn = cn.id(); }
525 if (cn == -1) { safe = false; }
529 g.error.standard_unexpected_error_alert('safe_to_change_owning_lib?',E);
534 /******************************************************************************************************/
535 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
537 g.safe_to_edit_copy_status = function() {
540 for (var i = 0; i < g.copies.length; i++) {
541 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
542 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
546 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
551 /******************************************************************************************************/
552 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
554 g.populate_alert_message_input = function(tb) {
556 var seen = {}; var s = '';
557 for (var i = 0; i < g.copies.length; i++) {
558 var msg = g.copies[i].alert_message();
560 if (typeof seen[msg] == 'undefined') {
566 tb.setAttribute('value',s);
568 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
572 /******************************************************************************************************/
573 /* This returns a list of acpl's appropriate for the copies being edited */
575 g.get_acpl_list = function() {
578 JSAN.use('util.functional');
580 function get(lib_id,only_these) {
581 g.data.stash_retrieve();
582 var label = 'acpl_list_for_lib_'+lib_id;
583 if (typeof g.data[label] == 'undefined') {
584 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
585 if (typeof robj.ilsevent != 'undefined') throw(robj);
587 for (var j = 0; j < robj.length; j++) {
588 var my_acpl = robj[j];
589 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
590 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
591 g.data.list.acpl.push( my_acpl );
593 var only_this_lib = my_acpl.owning_lib(); if (typeof only_this_lib == 'object') only_this_lib = only_this_lib.id();
594 if (only_these.indexOf( String( only_this_lib ) ) != -1) {
595 temp_list.push( my_acpl );
598 g.data[label] = temp_list; g.data.stash(label,'hash','list');
600 return g.data[label];
603 var temp_acpl_list = [];
605 /* find acpl's based on owning_lib */
607 var libs = []; var map_acn = {};
608 for (var i = 0; i < g.copies.length; i++) {
609 var cn_id = g.copies[i].call_number();
611 if (! map_acn[ cn_id ]) {
612 map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
613 var consider_lib = map_acn[ cn_id ].owning_lib();
614 if ( libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { libs.push( consider_lib ); }
619 for (var i in g.callnumbers) {
620 var consider_lib = g.callnumbers[i].owning_lib;
621 if (typeof consider_lib == 'object') consider_lib = consider_lib.id();
622 if ( libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { libs.push( consider_lib ); }
625 JSAN.use('util.fm_utils');
626 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
627 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
629 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
632 var acpl_list = get(ancestor, ancestors);
633 for (var i = 0; i < acpl_list.length; i++) {
634 if (acpl_list[i] != null) {
635 temp_acpl_list.push(acpl_list[i]);
640 /* find acpl's based on circ_lib */
644 for (var i = 0; i < g.copies.length; i++) {
645 var consider_lib = g.copies[i].circ_lib();
646 if (typeof consider_lib == 'object') consider_lib = consider_lib.id();
647 if ( circ_libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { circ_libs.push( consider_lib ); }
650 if (circ_libs.length > 0) {
651 var circ_ancestor = util.fm_utils.find_common_aou_ancestor( circ_libs );
652 if (typeof circ_ancestor == 'object' && circ_ancestor != null) circ_ancestor = circ_ancestor.id();
654 circ_ancestors = util.fm_utils.find_common_aou_ancestors( circ_libs );
657 var circ_acpl_list = get(circ_ancestor, circ_ancestors);
658 var flat_acpl_list = util.functional.map_list( temp_acpl_list, function(o){return o.id();} );
659 for (var i = 0; i < circ_acpl_list.length; i++) {
660 var consider_acpl = circ_acpl_list[i].id();
661 if ( flat_acpl_list.indexOf( String( consider_acpl ) ) > -1 ) {
662 /* already in list */
664 if (acpl_list[i] != null) temp_acpl_list.push( circ_acpl_list[i] );
670 return temp_acpl_list;
673 g.error.standard_unexpected_error_alert('get_acpl_list',E);
679 /******************************************************************************************************/
680 /* This keeps track of what fields have been edited for styling purposes */
684 /******************************************************************************************************/
685 /* These need data from the middle layer to render */
687 g.special_exception = {
688 'Owning Lib : Call Number' : function(label,value) {
689 JSAN.use('util.widgets');
690 if (value>0) { /* an existing call number */
692 api.FM_ACN_RETRIEVE.app,
693 api.FM_ACN_RETRIEVE.method,
696 var cn = '??? id = ' + value;
698 cn = req.getResultObject();
700 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
702 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
705 } else { /* a yet to be created call number */
707 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
711 'Creator' : function(label,value) {
712 if (value == null || value == '' || value == 'null') return;
713 g.network.simple_request(
714 'FM_AU_RETRIEVE_VIA_ID',
717 var p = '??? id = ' + value;
719 p = req.getResultObject();
723 g.error.sdump('D_ERROR','patron retrieve: ' + E);
725 JSAN.use('util.widgets');
726 util.widgets.set_text(label,p);
730 'Last Editor' : function(label,value) {
731 if (value == null || value == '' || value == 'null') return;
732 g.network.simple_request(
733 'FM_AU_RETRIEVE_VIA_ID',
736 var p = '??? id = ' + value;
738 p = req.getResultObject();
742 g.error.sdump('D_ERROR','patron retrieve: ' + E);
744 util.widgets.set_text(label,p);
751 /******************************************************************************************************/
752 g.readonly_stat_cat_names = [];
753 g.editable_stat_cat_names = [];
755 /******************************************************************************************************/
756 /* These get show in the left panel */
758 function init_panes() {
759 g.panes_and_field_names = {
766 render: 'fm.barcode();',
772 render: 'util.date.formatted_date( fm.create_date(), "%F");',
778 render: 'fm.creator();',
784 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
790 render: 'fm.editor();',
801 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
802 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);',
807 "Circulation Library",
809 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
810 //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);',
811 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);',
815 "Owning Lib : Call Number",
817 render: 'fm.call_number();',
818 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,
824 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
825 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);',
837 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
838 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);',
844 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
845 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);',
851 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
852 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);',
859 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
860 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);',
867 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
868 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);',
875 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
876 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);',
880 "Circulation Modifier",
882 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
883 /*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);',*/
884 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);',
893 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
894 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);',
901 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
902 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);',
908 render: 'if (fm.deposit_amount() == null) { "<Unset>"; } else { util.money.sanitize( fm.deposit_amount() ); }',
909 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);',
915 render: 'if (fm.price() == null) { "<Unset>"; } else { util.money.sanitize( fm.price() ); }',
916 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);',
923 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
924 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);',
930 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
931 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);',
943 /******************************************************************************************************/
944 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
946 g.summarize = function( copies ) {
947 /******************************************************************************************************/
950 JSAN.use('util.date'); JSAN.use('util.money');
953 for (var i in g.panes_and_field_names) {
954 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
956 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
957 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
959 /******************************************************************************************************/
960 /* Loop through the field names */
962 for (var i = 0; i < g.field_names.length; i++) {
964 var field_name = g.field_names[i][0];
965 var render = g.field_names[i][1].render;
966 g.summary[ field_name ] = {};
968 /******************************************************************************************************/
969 /* Loop through the copies */
971 for (var j = 0; j < copies.length; j++) {
974 var cmd = render || ('fm.' + field_name + '();');
977 /**********************************************************************************************/
978 /* Try to retrieve the value for this field for this copy */
983 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
985 if (typeof value == 'object' && value != null) {
986 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
989 /**********************************************************************************************/
990 /* Tally the count */
992 if (g.summary[ field_name ][ value ]) {
993 g.summary[ field_name ][ value ]++;
995 g.summary[ field_name ][ value ] = 1;
999 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
1002 /******************************************************************************************************/
1003 /* Display the summarized data and inputs for editing */
1005 g.render = function() {
1007 /******************************************************************************************************/
1008 /* Library setup and clear any existing interface */
1010 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
1012 for (var i in g.panes_and_field_names) {
1013 var p = document.getElementById(i);
1014 if (p) util.widgets.remove_children(p);
1017 /******************************************************************************************************/
1018 /* Prepare the panes */
1020 var groupbox; var caption; var vbox; var grid; var rows;
1022 /******************************************************************************************************/
1023 /* Loop through the field names */
1025 for (h in g.panes_and_field_names) {
1026 if (!document.getElementById(h)) continue;
1027 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
1029 var f = g.panes_and_field_names[h][i]; var fn = f[0];
1030 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
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 /* This actually draws the change button and input widget for a given field */
1078 g.render_input = function(node,blob) {
1080 // node = hbox ; groupbox -> hbox, hbox
1082 var groupbox = node.parentNode;
1083 var caption = groupbox.firstChild;
1084 var vbox = node.previousSibling;
1086 var hbox2 = node.nextSibling;
1088 var input_cmd = blob.input;
1089 var render_cmd = blob.render;
1091 var block = false; var first = true;
1093 function on_mouseover(ev) {
1094 groupbox.setAttribute('style','background: white');
1097 function on_mouseout(ev) {
1098 groupbox.setAttribute('style','');
1101 vbox.addEventListener('mouseover',on_mouseover,false);
1102 vbox.addEventListener('mouseout',on_mouseout,false);
1103 groupbox.addEventListener('mouseover',on_mouseover,false);
1104 groupbox.addEventListener('mouseout',on_mouseout,false);
1105 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1106 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1108 function on_click(ev){
1110 if (block) return; block = true;
1112 function post_c(v) {
1114 /* FIXME - kludgy */
1115 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1119 f = input_cmd.match(/apply\("(.+?)",/)[1];
1122 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1128 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1132 g.summarize( g.copies );
1134 document.getElementById(caption.id).focus();
1138 g.error.standard_unexpected_error_alert('post_c',E);
1141 var x; var c; eval( input_cmd );
1143 util.widgets.remove_children(vbox);
1144 util.widgets.remove_children(hbox);
1145 util.widgets.remove_children(hbox2);
1146 hbox.appendChild(x);
1147 var apply = document.createElement('button');
1148 apply.setAttribute('label','Apply');
1149 apply.setAttribute('accesskey','A');
1150 hbox2.appendChild(apply);
1151 apply.addEventListener('command',function() { c(x.value); },false);
1152 var cancel = document.createElement('button');
1153 cancel.setAttribute('label','Cancel');
1154 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1155 hbox2.appendChild(cancel);
1156 setTimeout( function() { x.focus(); }, 0 );
1159 g.error.standard_unexpected_error_alert('render_input',E);
1162 vbox.addEventListener('click',on_click, false);
1163 hbox.addEventListener('click',on_click, false);
1164 caption.addEventListener('click',on_click, false);
1165 caption.addEventListener('keypress',function(ev) {
1166 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1168 caption.setAttribute('style','-moz-user-focus: normal');
1169 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1170 caption.setAttribute('onblur','this.setAttribute("class","")');
1173 g.error.sdump('D_ERROR',E + '\n');
1177 /******************************************************************************************************/
1178 /* store the copies in the global xpcom stash */
1180 g.stash_and_close = function() {
1182 if (g.handle_update) {
1184 var r = g.network.request(
1185 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1186 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1187 [ ses(), g.copies, true ]
1189 if (typeof r.ilsevent != 'undefined') {
1190 g.error.standard_unexpected_error_alert('copy update',r);
1192 alert('Items added/modified.');
1194 /* FIXME -- revisit the return value here */
1196 alert('copy update error: ' + js2JSON(E));
1199 //g.data.temp_copies = js2JSON( g.copies );
1200 //g.data.stash('temp_copies');
1201 xulG.copies = g.copies;
1202 update_modal_xulG(xulG);
1205 g.error.standard_unexpected_error_alert('stash and close',E);
1209 /******************************************************************************************************/
1210 /* spawn copy notes interface */
1212 g.copy_notes = function() {
1213 JSAN.use('util.window'); var win = new util.window();
1215 urls.XUL_COPY_NOTES,
1216 //+ '?copy_id=' + window.escape(g.copies[0].id()),
1217 'Copy Notes','chrome,resizable,modal',
1218 { 'copy_id' : g.copies[0].id() }