5 /******************************************************************************************************/
6 /* setup JSAN and some initial libraries */
8 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
9 if (typeof JSAN == 'undefined') { throw( "The JSAN library object is missing."); }
10 JSAN.errorLevel = "die"; // none, warn, or die
11 JSAN.addRepository('/xul/server/');
12 JSAN.use('util.error'); g.error = new util.error();
13 g.error.sdump('D_TRACE','my_init() for cat/copy_editor.xul');
15 JSAN.use('util.functional');
16 JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
17 JSAN.use('util.network'); g.network = new util.network();
21 g.docid = g.cgi.param('docid');
22 g.handle_update = g.cgi.param('handle_update');
24 /******************************************************************************************************/
25 /* Get the copy ids from various sources and flesh them */
28 if (g.cgi.param('copy_ids')) copy_ids = JSON2js( g.cgi.param('copy_ids') );
29 if (window.xulG && window.xulG.copy_ids) copy_ids = copy_ids.concat( window.xulG.copy_ids );
30 if (typeof g.data.temp_copy_ids != 'undefined' && g.data.temp_copy_ids != null) copy_ids = copy_ids.concat( JSON2js( g.data.temp_copy_ids ) );
31 if (!copy_ids) copy_ids = [];
33 if (copy_ids.length > 0) g.copies = g.network.request(
34 api.FM_ACP_FLESHED_BATCH_RETRIEVE.app,
35 api.FM_ACP_FLESHED_BATCH_RETRIEVE.method,
39 /******************************************************************************************************/
40 /* And other fleshed copies if any */
42 if (!g.copies) g.copies = [];
43 if (window.xulG && window.xulG.copies) g.copies = g.copies.concat( window.xulG.copies );
44 if (g.cgi.param('copies')) g.copies = g.copies.concat( JSON2js( g.cgi.param('copies') ) );
45 if (g.data.temp_copies != 'undefined' && g.data.temp_copies) g.copies = g.copies.concat( JSON2js( g.data.temp_copies ) );
46 g.data.temp_copies = null; g.data.stash('temp_copies');
48 /******************************************************************************************************/
49 /* We try to retrieve callnumbers for existing copies, but for new copies, we rely on this */
51 if (window.xulG && window.xulG.callnumbers) g.callnumbers = window.xulG.callnumbers;
52 if (g.cgi.param('callnumbers')) g.callnumbers = JSON2js( g.cgi.param('callnumbers') );
53 if (g.data.temp_callnumbers != 'undefined') g.callnumbers = JSON2js( g.data.temp_callnumbers );
55 /******************************************************************************************************/
56 /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
58 if (g.cgi.param('edit') == '1') {
60 document.getElementById('caption').setAttribute('label','Copy Editor');
61 document.getElementById('save').setAttribute('hidden','false');
62 g.retrieve_templates();
64 $('top_nav').setAttribute('hidden','true');
67 if (g.copies.length > 0 && g.copies[0].id() < 0) {
68 document.getElementById('copy_notes').setAttribute('hidden','true');
69 g.apply("status",5 /* In Process */);
70 $('save').setAttribute('label','Create Copies');
72 g.panes_and_field_names.left_pane =
77 render: 'typeof fm.status() == "object" ? fm.status().name() : g.data.hash.ccs[ fm.status() ].name()',
78 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,
79 //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);',
82 ].concat(g.panes_and_field_names.left_pane);
85 if (g.copies.length != 1) {
86 document.getElementById('copy_notes').setAttribute('hidden','true');
89 /******************************************************************************************************/
90 /* Show the Record Details? */
93 document.getElementById('brief_display').setAttribute(
95 urls.XUL_BIB_BRIEF + '?docid=' + g.docid
98 document.getElementById('brief_display').setAttribute('hidden','true');
101 /******************************************************************************************************/
102 /* Add stat cats to the panes_and_field_names.right_pane4 */
104 g.stat_cat_seen = {};
106 function add_stat_cat(sc) {
108 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; g.data.stash('hash'); }
112 if (typeof sc == 'object') {
117 if (typeof g.stat_cat_seen[sc_id] != 'undefined') { return; }
119 g.stat_cat_seen[ sc_id ] = 1;
121 if (typeof sc != 'object') {
123 sc = g.network.simple_request(
124 'FM_ASC_BATCH_RETRIEVE',
130 g.data.hash.asc[ sc.id() ] = sc; g.data.stash('hash');
132 var label_name = g.data.hash.aou[ sc.owner() ].shortname() + " : " + sc.name();
137 render: 'var l = util.functional.find_list( fm.stat_cat_entries(), function(e){ return e.stat_cat() == '
138 + sc.id() + '; } ); l ? l.value() : "<Unset>";',
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>", -1 ] ].concat( util.functional.map_list( g.data.hash.asc[' + sc.id()
140 + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ) ).sort() ); '
141 //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()
142 // + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ).sort() ) ); '
143 + 'x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c),false);',
147 dump('temp_array = ' + js2JSON(temp_array) + '\n');
149 g.panes_and_field_names.right_pane4.push( temp_array );
152 /* The stat cats for the pertinent library */
153 for (var i = 0; i < g.data.list.my_asc.length; i++) {
154 add_stat_cat( g.data.list.my_asc[i] );
157 /* Other stat cats present on these copies */
158 for (var i = 0; i < g.copies.length; i++) {
159 var entries = g.copies[i].stat_cat_entries();
160 if (!entries) entries = [];
161 for (var j = 0; j < entries.length; j++) {
162 var sc_id = entries[j].stat_cat();
163 add_stat_cat( sc_id );
167 /******************************************************************************************************/
168 /* Backup copies :) */
170 g.original_copies = js2JSON( g.copies );
172 /******************************************************************************************************/
175 g.summarize( g.copies );
179 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
180 "system administrator or software developer the following:\ncat/copy_editor.xul\n" + E + '\n';
181 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
186 /******************************************************************************************************/
187 /* File picker for template export/import */
189 function pick_file(mode) {
190 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
191 var nsIFilePicker = Components.interfaces.nsIFilePicker;
192 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance( nsIFilePicker );
195 mode == 'open' ? "Import Templates File" : "Save Templates File As",
196 mode == 'open' ? nsIFilePicker.modeOpen : nsIFilePicker.modeSave
198 fp.appendFilters( nsIFilePicker.filterAll );
199 if ( fp.show( ) == nsIFilePicker.returnOK && fp.file ) {
206 /******************************************************************************************************/
207 /* Retrieve Templates */
209 g.retrieve_templates = function() {
211 JSAN.use('util.widgets'); JSAN.use('util.functional');
213 var robj = g.network.simple_request('FM_AUS_RETRIEVE',[ses(),g.data.list.au[0].id()]);
214 if (typeof robj['staff_client.copy_editor.templates'] != 'undefined') {
215 g.templates = robj['staff_client.copy_editor.templates'];
217 util.widgets.remove_children('template_placeholder');
218 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
220 g.template_menu = util.widgets.make_menulist( list );
221 $('template_placeholder').appendChild(g.template_menu);
223 g.error.standard_unexpected_error_alert('Error retrieving templates',E);
227 /******************************************************************************************************/
230 g.apply_template = function() {
232 var name = g.template_menu.value;
233 if (g.templates[ name ] != 'undefined') {
234 var template = g.templates[ name ];
235 for (var i in template) {
236 g.changed[ i ] = template[ i ];
237 switch( template[i].type ) {
239 g.apply(template[i].field,template[i].value);
242 if (g.stat_cat_seen[ template[i].field ]) g.apply_stat_cat(template[i].field,template[i].value);
245 g.apply_owning_lib(template[i].value);
249 g.summarize( g.copies );
253 g.error.standard_unexpected_error_alert('Error applying template',E);
257 /******************************************************************************************************/
258 /* Save as Template */
260 g.save_template = function() {
262 var name = window.prompt('Enter template name:','','Save As Template');
264 g.templates[name] = g.changed;
265 var robj = g.network.simple_request(
266 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
268 if (typeof robj.ilsevent != 'undefined') {
271 alert('Template "' + name + '" saved.');
275 g.retrieve_templates();
277 g.error.standard_unexpected_error_alert('Error saving template',E);
283 g.error.standard_unexpected_error_alert('Error saving template',E);
287 /******************************************************************************************************/
288 /* Delete Template */
290 g.delete_template = function() {
292 var name = g.template_menu.value;
294 if (! window.confirm('Delete template "' + name + '"?') ) return;
295 delete(g.templates[name]);
296 var robj = g.network.simple_request(
297 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
299 if (typeof robj.ilsevent != 'undefined') {
302 alert('Template "' + name + '" deleted.');
306 g.retrieve_templates();
308 g.error.standard_unexpected_error_alert('Error deleting template',E);
314 g.error.standard_unexpected_error_alert('Error deleting template',E);
318 /******************************************************************************************************/
319 /* Export Templates */
321 g.export_templates = function() {
323 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
324 JSAN.use('util.file');
325 var f = pick_file('save');
328 var r = G.error.yns_alert(
329 'Would you like to overwrite the existing file ' + f.leafName + '?',
330 'Templates Export Warning',
334 'Check here to confirm this message'
336 if (r != 0) { file.close(); alert('Not overwriting file.'); return; }
338 var e_file = new util.file(''); e_file._file = f;
339 e_file.write_content( 'truncate', js2JSON( g.templates ) );
341 alert('Templates exported as file ' + f.leafName);
343 alert('File not chosen for export.');
347 g.error.standard_unexpected_error_alert('Error exporting templates',E);
351 /******************************************************************************************************/
352 /* Import Templates */
354 g.import_templates = function() {
356 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
357 JSAN.use('util.file');
358 var f = pick_file('open');
359 if (f && f.exists()) {
360 var i_file = new util.file(''); i_file._file = f;
361 var temp = JSON2js( i_file.get_content() );
363 for (var i in temp) {
365 if (g.templates[i]) {
367 var r = g.error.yns_alert(
368 'Replace the existing template with the imported template?\n' + g.error.pretty_print( js2JSON( temp[i] ) ),
369 'Template ' + i + ' already exists.','Yes','No',null,'Click here'
372 if (r == 0 /* Yes */) g.templates[i] = temp[i];
376 g.templates[i] = temp[i];
382 var r = g.error.yns_alert(
383 'Save all of these imported templates permanently to this account?',
384 'Final Warning', 'Yes', 'No', null, 'Click here'
387 if (r == 0 /* Yes */) {
388 var robj = g.network.simple_request(
389 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
391 if (typeof robj.ilsevent != 'undefined') {
394 alert('All templates saved.');
398 g.retrieve_templates();
400 g.error.standard_unexpected_error_alert('Error saving templates',E);
406 util.widgets.remove_children('template_placeholder');
407 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
408 g.template_menu = util.widgets.make_menulist( list );
409 $('template_placeholder').appendChild(g.template_menu);
410 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.");
414 alert('File not chosen for import.');
417 g.error.standard_unexpected_error_alert('Error exporting templates',E);
422 /******************************************************************************************************/
423 /* Restore backup copies */
425 g.reset = function() {
427 g.copies = JSON2js( g.original_copies );
428 g.summarize( g.copies );
432 /******************************************************************************************************/
433 /* Apply a value to a specific field on all the copies being edited */
435 g.apply = function(field,value) {
436 g.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
437 if (value == '<HACK:KLUDGE:NULL>') value = null;
438 for (var i = 0; i < g.copies.length; i++) {
439 var copy = g.copies[i];
441 copy[field]( value ); copy.ischanged('1');
448 /******************************************************************************************************/
449 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
451 g.apply_stat_cat = function(sc_id,entry_id) {
452 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
453 for (var i = 0; i < g.copies.length; i++) {
454 var copy = g.copies[i];
457 var temp = copy.stat_cat_entries();
458 if (!temp) temp = [];
459 temp = util.functional.filter_list(
462 return (obj.stat_cat() != sc_id);
465 if (entry_id > -1) temp.push(
466 util.functional.find_id_object_in_list(
467 g.data.hash.asc[sc_id].entries(),
471 copy.stat_cat_entries( temp );
474 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
479 /******************************************************************************************************/
480 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
482 g.apply_owning_lib = function(ou_id) {
483 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
485 for (var i = 0; i < g.copies.length; i++) {
486 var copy = g.copies[i];
488 if (!map_acn[copy.call_number()]) {
489 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
490 if (typeof volume.ilsevent != 'undefined') {
491 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);
494 map_acn[copy.call_number()] = volume;
496 var old_volume = map_acn[copy.call_number()];
497 var acn_id = g.network.simple_request(
498 'FM_ACN_FIND_OR_CREATE',
499 [ses(),old_volume.label(),old_volume.record(),ou_id]
501 if (typeof acn_id.ilsevent != 'undefined') {
502 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);
505 copy.call_number(acn_id);
508 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
514 /******************************************************************************************************/
515 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
517 g.safe_to_edit_copy_status = function() {
520 for (var i = 0; i < g.copies.length; i++) {
521 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
522 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
526 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
531 /******************************************************************************************************/
532 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
534 g.populate_alert_message_input = function(tb) {
536 var seen = {}; var s = '';
537 for (var i = 0; i < g.copies.length; i++) {
538 var msg = g.copies[i].alert_message();
540 if (typeof seen[msg] == 'undefined') {
546 tb.setAttribute('value',s);
548 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
552 /******************************************************************************************************/
553 /* This returns a list of acpl's appropriate for the copies being edited */
555 g.get_acpl_list = function() {
558 JSAN.use('util.functional');
560 function get(lib_id,only_these) {
561 g.data.stash_retrieve();
562 var label = 'acpl_list_for_lib_'+lib_id;
563 if (typeof g.data[label] == 'undefined') {
564 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
565 if (typeof robj.ilsevent != 'undefined') throw(robj);
567 for (var j = 0; j < robj.length; j++) {
568 var my_acpl = robj[j];
569 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
570 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
571 g.data.list.acpl.push( my_acpl );
573 if (only_these.indexOf( String( my_acpl.owning_lib() ) ) != -1) {
574 temp_list.push( my_acpl );
577 g.data[label] = temp_list; g.data.stash(label,'hash','list');
579 return g.data[label];
582 var libs = []; var map_acn = {};
583 for (var i = 0; i < g.copies.length; i++) {
584 var cn_id = g.copies[i].call_number();
586 if (! map_acn[ cn_id ]) {
587 map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
588 libs.push( map_acn[ cn_id ].owning_lib() );
593 for (var i in g.callnumbers) {
594 if ( ( libs.indexOf( g.callnumbers[i].owning_lib ) > -1 ) || ( libs.indexOf( String( g.callnumbers[i].owning_lib ) ) > -1 ) ) { /* already in list */ } else { libs.push( g.callnumbers[i].owning_lib ); }
597 JSAN.use('util.fm_utils');
598 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
599 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
601 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
604 return get(ancestor, ancestors);
610 g.error.standard_unexpected_error_alert('get_acpl_list',E);
616 /******************************************************************************************************/
617 /* This keeps track of what fields have been edited for styling purposes */
621 /******************************************************************************************************/
622 /* These need data from the middle layer to render */
624 g.special_exception = {
625 'Owning Lib : Call Number' : function(label,value) {
626 JSAN.use('util.widgets');
627 if (value>0) { /* an existing call number */
629 api.FM_ACN_RETRIEVE.app,
630 api.FM_ACN_RETRIEVE.method,
633 var cn = '??? id = ' + value;
635 cn = req.getResultObject();
637 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
639 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
642 } else { /* a yet to be created call number */
644 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
648 'Creator' : function(label,value) {
649 if (value == null || value == '' || value == 'null') return;
650 g.network.simple_request(
651 'FM_AU_RETRIEVE_VIA_ID',
654 var p = '??? id = ' + value;
656 p = req.getResultObject();
660 g.error.sdump('D_ERROR','patron retrieve: ' + E);
662 JSAN.use('util.widgets');
663 util.widgets.set_text(label,p);
667 'Last Editor' : function(label,value) {
668 if (value == null || value == '' || value == 'null') return;
669 g.network.simple_request(
670 'FM_AU_RETRIEVE_VIA_ID',
673 var p = '??? id = ' + value;
675 p = req.getResultObject();
679 g.error.sdump('D_ERROR','patron retrieve: ' + E);
681 util.widgets.set_text(label,p);
688 /******************************************************************************************************/
689 g.readonly_stat_cat_names = [];
690 g.editable_stat_cat_names = [];
692 /******************************************************************************************************/
693 /* These get show in the left panel */
695 g.panes_and_field_names = {
702 render: 'fm.barcode();',
708 render: 'util.date.formatted_date( fm.create_date(), "%F");',
714 render: 'fm.creator();',
720 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
726 render: 'fm.editor();',
737 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
738 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);',
743 "Circulation Library",
745 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
746 //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);',
747 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);',
751 "Owning Lib : Call Number",
753 render: 'fm.call_number();',
754 input: '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);',
760 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
761 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);',
773 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
774 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);',
780 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
781 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);',
787 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
788 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);',
795 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
796 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);',
803 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
804 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);',
811 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
812 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);',
816 "Circulation Modifier",
818 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
819 /*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);',*/
820 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);',
829 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
830 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( String(ev.target.value).replace(/^\s+$/,"") ); } }(c), false);',
837 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
838 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);',
844 render: 'util.money.sanitize( fm.deposit_amount() );',
845 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);',
851 render: 'util.money.sanitize( fm.price() );',
852 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);',
859 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
860 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);',
866 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
867 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);',
878 /******************************************************************************************************/
879 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
881 g.summarize = function( copies ) {
882 /******************************************************************************************************/
885 JSAN.use('util.date'); JSAN.use('util.money');
888 for (var i in g.panes_and_field_names) {
889 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
891 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
892 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
894 /******************************************************************************************************/
895 /* Loop through the field names */
897 for (var i = 0; i < g.field_names.length; i++) {
899 var field_name = g.field_names[i][0];
900 var render = g.field_names[i][1].render;
901 g.summary[ field_name ] = {};
903 /******************************************************************************************************/
904 /* Loop through the copies */
906 for (var j = 0; j < copies.length; j++) {
909 var cmd = render || ('fm.' + field_name + '();');
912 /**********************************************************************************************/
913 /* Try to retrieve the value for this field for this copy */
918 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
920 if (typeof value == 'object' && value != null) {
921 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
924 /**********************************************************************************************/
925 /* Tally the count */
927 if (g.summary[ field_name ][ value ]) {
928 g.summary[ field_name ][ value ]++;
930 g.summary[ field_name ][ value ] = 1;
934 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
937 /******************************************************************************************************/
938 /* Display the summarized data and inputs for editing */
940 g.render = function() {
942 /******************************************************************************************************/
943 /* Library setup and clear any existing interface */
945 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
947 for (var i in g.panes_and_field_names) {
948 var p = document.getElementById(i);
949 if (p) util.widgets.remove_children(p);
952 /******************************************************************************************************/
953 /* Prepare the panes */
955 var groupbox; var caption; var vbox; var grid; var rows;
957 /******************************************************************************************************/
958 /* Loop through the field names */
960 for (h in g.panes_and_field_names) {
961 if (!document.getElementById(h)) continue;
962 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
964 var f = g.panes_and_field_names[h][i]; var fn = f[0];
965 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
966 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
967 caption = document.createElement('caption'); groupbox.appendChild(caption);
968 caption.setAttribute('label',fn);
969 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
970 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
971 grid.setAttribute('flex','1');
972 rows = grid.lastChild;
975 /**************************************************************************************/
976 /* Loop through each value for the field */
978 for (var j in g.summary[fn]) {
979 var value = j; var count = g.summary[fn][j];
980 row = document.createElement('row'); rows.appendChild(row);
981 var label1 = document.createElement('description'); row.appendChild(label1);
982 if (g.special_exception[ fn ]) {
983 g.special_exception[ fn ]( label1, value );
985 label1.appendChild( document.createTextNode(value) );
987 var label2 = document.createElement('description'); row.appendChild(label2);
988 var unit = count == 1 ? 'copy' : 'copies';
989 label2.appendChild( document.createTextNode(count + ' ' + unit) );
991 var hbox = document.createElement('hbox');
992 hbox.setAttribute('id',fn);
993 groupbox.appendChild(hbox);
994 var hbox2 = document.createElement('hbox');
995 groupbox.appendChild(hbox2);
997 /**************************************************************************************/
998 /* Render the input widget */
1000 if (f[1].input && g.edit) {
1001 g.render_input(hbox,f[1]);
1005 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1011 /******************************************************************************************************/
1012 /* This actually draws the change button and input widget for a given field */
1013 g.render_input = function(node,blob) {
1015 // node = hbox ; groupbox -> hbox, hbox
1017 var groupbox = node.parentNode;
1018 var caption = groupbox.firstChild;
1019 var vbox = node.previousSibling;
1021 var hbox2 = node.nextSibling;
1023 var input_cmd = blob.input;
1024 var render_cmd = blob.render;
1026 var block = false; var first = true;
1028 function on_mouseover(ev) {
1029 groupbox.setAttribute('style','background: white');
1032 function on_mouseout(ev) {
1033 groupbox.setAttribute('style','');
1036 vbox.addEventListener('mouseover',on_mouseover,false);
1037 vbox.addEventListener('mouseout',on_mouseout,false);
1038 groupbox.addEventListener('mouseover',on_mouseover,false);
1039 groupbox.addEventListener('mouseout',on_mouseout,false);
1040 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1041 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1043 function on_click(ev){
1045 if (block) return; block = true;
1047 function post_c(v) {
1049 /* FIXME - kludgy */
1050 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1054 f = input_cmd.match(/apply\("(.+?)",/)[1];
1057 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1063 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1067 g.summarize( g.copies );
1072 g.error.standard_unexpected_error_alert('post_c',E);
1075 var x; var c; eval( input_cmd );
1077 util.widgets.remove_children(vbox);
1078 util.widgets.remove_children(hbox);
1079 util.widgets.remove_children(hbox2);
1080 hbox.appendChild(x);
1081 var apply = document.createElement('button');
1082 apply.setAttribute('label','Apply');
1083 apply.setAttribute('accesskey','A');
1084 hbox2.appendChild(apply);
1085 apply.addEventListener('command',function() { c(x.value); },false);
1086 var cancel = document.createElement('button');
1087 cancel.setAttribute('label','Cancel');
1088 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); }, 0); }, false);
1089 hbox2.appendChild(cancel);
1090 setTimeout( function() { x.focus(); }, 0 );
1093 g.error.standard_unexpected_error_alert('render_input',E);
1096 vbox.addEventListener('click',on_click, false);
1097 hbox.addEventListener('click',on_click, false);
1098 caption.addEventListener('click',on_click, false);
1099 caption.addEventListener('keypress',function(ev) {
1100 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1102 caption.setAttribute('style','-moz-user-focus: normal');
1103 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1104 caption.setAttribute('onblur','this.setAttribute("class","")');
1107 g.error.sdump('D_ERROR',E + '\n');
1111 /******************************************************************************************************/
1112 /* store the copies in the global xpcom stash */
1114 g.stash_and_close = function() {
1115 if (g.handle_update) {
1117 var r = g.network.request(
1118 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1119 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1120 [ ses(), g.copies, true ]
1122 if (typeof r.ilsevent != 'undefined') {
1123 g.error.standard_unexpected_error_alert('copy update',r);
1125 alert('Items added/modified.');
1127 /* FIXME -- revisit the return value here */
1129 alert('copy update error: ' + js2JSON(E));
1132 g.data.temp_copies = js2JSON( g.copies );
1133 g.data.stash('temp_copies');
1134 g.error.sdump('D_CAT','in modal window, g.data.temp_copies = \n' + g.data.temp_copies + '\n');
1138 /******************************************************************************************************/
1139 /* spawn copy notes interface */
1141 g.copy_notes = function() {
1142 JSAN.use('util.window'); var win = new util.window();
1143 win.open(urls.XUL_COPY_NOTES + '?copy_id=' + window.escape(g.copies[0].id()),'Copy Notes','chrome,resizable,modal');