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 importing 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 if (field == 'alert_message') { value = value.replace(/^\W+$/g,''); }
439 for (var i = 0; i < g.copies.length; i++) {
440 var copy = g.copies[i];
442 copy[field]( value ); copy.ischanged('1');
449 /******************************************************************************************************/
450 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
452 g.apply_stat_cat = function(sc_id,entry_id) {
453 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
454 for (var i = 0; i < g.copies.length; i++) {
455 var copy = g.copies[i];
458 var temp = copy.stat_cat_entries();
459 if (!temp) temp = [];
460 temp = util.functional.filter_list(
463 return (obj.stat_cat() != sc_id);
466 if (entry_id > -1) temp.push(
467 util.functional.find_id_object_in_list(
468 g.data.hash.asc[sc_id].entries(),
472 copy.stat_cat_entries( temp );
475 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
480 /******************************************************************************************************/
481 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
483 g.apply_owning_lib = function(ou_id) {
484 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
486 for (var i = 0; i < g.copies.length; i++) {
487 var copy = g.copies[i];
489 if (!map_acn[copy.call_number()]) {
490 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
491 if (typeof volume.ilsevent != 'undefined') {
492 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);
495 map_acn[copy.call_number()] = volume;
497 var old_volume = map_acn[copy.call_number()];
498 var acn_id = g.network.simple_request(
499 'FM_ACN_FIND_OR_CREATE',
500 [ses(),old_volume.label(),old_volume.record(),ou_id]
502 if (typeof acn_id.ilsevent != 'undefined') {
503 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);
506 copy.call_number(acn_id);
509 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
515 /******************************************************************************************************/
516 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
518 g.safe_to_edit_copy_status = function() {
521 for (var i = 0; i < g.copies.length; i++) {
522 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
523 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
527 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
532 /******************************************************************************************************/
533 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
535 g.populate_alert_message_input = function(tb) {
537 var seen = {}; var s = '';
538 for (var i = 0; i < g.copies.length; i++) {
539 var msg = g.copies[i].alert_message();
541 if (typeof seen[msg] == 'undefined') {
547 tb.setAttribute('value',s);
549 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
553 /******************************************************************************************************/
554 /* This returns a list of acpl's appropriate for the copies being edited */
556 g.get_acpl_list = function() {
559 JSAN.use('util.functional');
561 function get(lib_id,only_these) {
562 g.data.stash_retrieve();
563 var label = 'acpl_list_for_lib_'+lib_id;
564 if (typeof g.data[label] == 'undefined') {
565 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
566 if (typeof robj.ilsevent != 'undefined') throw(robj);
568 for (var j = 0; j < robj.length; j++) {
569 var my_acpl = robj[j];
570 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
571 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
572 g.data.list.acpl.push( my_acpl );
574 if (only_these.indexOf( String( my_acpl.owning_lib() ) ) != -1) {
575 temp_list.push( my_acpl );
578 g.data[label] = temp_list; g.data.stash(label,'hash','list');
580 return g.data[label];
583 var libs = []; var map_acn = {};
584 for (var i = 0; i < g.copies.length; i++) {
585 var cn_id = g.copies[i].call_number();
587 if (! map_acn[ cn_id ]) {
588 map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
589 libs.push( map_acn[ cn_id ].owning_lib() );
594 for (var i in g.callnumbers) {
595 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 ); }
598 JSAN.use('util.fm_utils');
599 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
600 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
602 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
605 return get(ancestor, ancestors);
611 g.error.standard_unexpected_error_alert('get_acpl_list',E);
617 /******************************************************************************************************/
618 /* This keeps track of what fields have been edited for styling purposes */
622 /******************************************************************************************************/
623 /* These need data from the middle layer to render */
625 g.special_exception = {
626 'Owning Lib : Call Number' : function(label,value) {
627 JSAN.use('util.widgets');
628 if (value>0) { /* an existing call number */
630 api.FM_ACN_RETRIEVE.app,
631 api.FM_ACN_RETRIEVE.method,
634 var cn = '??? id = ' + value;
636 cn = req.getResultObject();
638 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
640 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
643 } else { /* a yet to be created call number */
645 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
649 'Creator' : function(label,value) {
650 if (value == null || value == '' || value == 'null') return;
651 g.network.simple_request(
652 'FM_AU_RETRIEVE_VIA_ID',
655 var p = '??? id = ' + value;
657 p = req.getResultObject();
661 g.error.sdump('D_ERROR','patron retrieve: ' + E);
663 JSAN.use('util.widgets');
664 util.widgets.set_text(label,p);
668 'Last Editor' : function(label,value) {
669 if (value == null || value == '' || value == 'null') return;
670 g.network.simple_request(
671 'FM_AU_RETRIEVE_VIA_ID',
674 var p = '??? id = ' + value;
676 p = req.getResultObject();
680 g.error.sdump('D_ERROR','patron retrieve: ' + E);
682 util.widgets.set_text(label,p);
689 /******************************************************************************************************/
690 g.readonly_stat_cat_names = [];
691 g.editable_stat_cat_names = [];
693 /******************************************************************************************************/
694 /* These get show in the left panel */
696 g.panes_and_field_names = {
703 render: 'fm.barcode();',
709 render: 'util.date.formatted_date( fm.create_date(), "%F");',
715 render: 'fm.creator();',
721 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
727 render: 'fm.editor();',
738 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
739 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);',
744 "Circulation Library",
746 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
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( 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);',
748 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);',
752 "Owning Lib : Call Number",
754 render: 'fm.call_number();',
755 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);',
761 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
762 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);',
774 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
775 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);',
781 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
782 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);',
788 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
789 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);',
796 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
797 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);',
804 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
805 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);',
812 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
813 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);',
817 "Circulation Modifier",
819 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
820 /*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);',*/
821 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);',
830 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
831 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);',
838 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
839 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);',
845 render: 'util.money.sanitize( fm.deposit_amount() );',
846 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);',
852 render: 'util.money.sanitize( fm.price() );',
853 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);',
860 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
861 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);',
867 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
868 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);',
879 /******************************************************************************************************/
880 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
882 g.summarize = function( copies ) {
883 /******************************************************************************************************/
886 JSAN.use('util.date'); JSAN.use('util.money');
889 for (var i in g.panes_and_field_names) {
890 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
892 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
893 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
895 /******************************************************************************************************/
896 /* Loop through the field names */
898 for (var i = 0; i < g.field_names.length; i++) {
900 var field_name = g.field_names[i][0];
901 var render = g.field_names[i][1].render;
902 g.summary[ field_name ] = {};
904 /******************************************************************************************************/
905 /* Loop through the copies */
907 for (var j = 0; j < copies.length; j++) {
910 var cmd = render || ('fm.' + field_name + '();');
913 /**********************************************************************************************/
914 /* Try to retrieve the value for this field for this copy */
919 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
921 if (typeof value == 'object' && value != null) {
922 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
925 /**********************************************************************************************/
926 /* Tally the count */
928 if (g.summary[ field_name ][ value ]) {
929 g.summary[ field_name ][ value ]++;
931 g.summary[ field_name ][ value ] = 1;
935 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
938 /******************************************************************************************************/
939 /* Display the summarized data and inputs for editing */
941 g.render = function() {
943 /******************************************************************************************************/
944 /* Library setup and clear any existing interface */
946 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
948 for (var i in g.panes_and_field_names) {
949 var p = document.getElementById(i);
950 if (p) util.widgets.remove_children(p);
953 /******************************************************************************************************/
954 /* Prepare the panes */
956 var groupbox; var caption; var vbox; var grid; var rows;
958 /******************************************************************************************************/
959 /* Loop through the field names */
961 for (h in g.panes_and_field_names) {
962 if (!document.getElementById(h)) continue;
963 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
965 var f = g.panes_and_field_names[h][i]; var fn = f[0];
966 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
967 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
968 caption = document.createElement('caption'); groupbox.appendChild(caption);
969 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
970 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
971 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
972 grid.setAttribute('flex','1');
973 rows = grid.lastChild;
976 /**************************************************************************************/
977 /* Loop through each value for the field */
979 for (var j in g.summary[fn]) {
980 var value = j; var count = g.summary[fn][j];
981 row = document.createElement('row'); rows.appendChild(row);
982 var label1 = document.createElement('description'); row.appendChild(label1);
983 if (g.special_exception[ fn ]) {
984 g.special_exception[ fn ]( label1, value );
986 label1.appendChild( document.createTextNode(value) );
988 var label2 = document.createElement('description'); row.appendChild(label2);
989 var unit = count == 1 ? 'copy' : 'copies';
990 label2.appendChild( document.createTextNode(count + ' ' + unit) );
992 var hbox = document.createElement('hbox');
993 hbox.setAttribute('id',fn);
994 groupbox.appendChild(hbox);
995 var hbox2 = document.createElement('hbox');
996 groupbox.appendChild(hbox2);
998 /**************************************************************************************/
999 /* Render the input widget */
1001 if (f[1].input && g.edit) {
1002 g.render_input(hbox,f[1]);
1006 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1012 /******************************************************************************************************/
1013 /* This actually draws the change button and input widget for a given field */
1014 g.render_input = function(node,blob) {
1016 // node = hbox ; groupbox -> hbox, hbox
1018 var groupbox = node.parentNode;
1019 var caption = groupbox.firstChild;
1020 var vbox = node.previousSibling;
1022 var hbox2 = node.nextSibling;
1024 var input_cmd = blob.input;
1025 var render_cmd = blob.render;
1027 var block = false; var first = true;
1029 function on_mouseover(ev) {
1030 groupbox.setAttribute('style','background: white');
1033 function on_mouseout(ev) {
1034 groupbox.setAttribute('style','');
1037 vbox.addEventListener('mouseover',on_mouseover,false);
1038 vbox.addEventListener('mouseout',on_mouseout,false);
1039 groupbox.addEventListener('mouseover',on_mouseover,false);
1040 groupbox.addEventListener('mouseout',on_mouseout,false);
1041 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1042 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1044 function on_click(ev){
1046 if (block) return; block = true;
1048 function post_c(v) {
1050 /* FIXME - kludgy */
1051 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1055 f = input_cmd.match(/apply\("(.+?)",/)[1];
1058 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1064 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1068 g.summarize( g.copies );
1070 document.getElementById(caption.id).focus();
1074 g.error.standard_unexpected_error_alert('post_c',E);
1077 var x; var c; eval( input_cmd );
1079 util.widgets.remove_children(vbox);
1080 util.widgets.remove_children(hbox);
1081 util.widgets.remove_children(hbox2);
1082 hbox.appendChild(x);
1083 var apply = document.createElement('button');
1084 apply.setAttribute('label','Apply');
1085 apply.setAttribute('accesskey','A');
1086 hbox2.appendChild(apply);
1087 apply.addEventListener('command',function() { c(x.value); },false);
1088 var cancel = document.createElement('button');
1089 cancel.setAttribute('label','Cancel');
1090 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1091 hbox2.appendChild(cancel);
1092 setTimeout( function() { x.focus(); }, 0 );
1095 g.error.standard_unexpected_error_alert('render_input',E);
1098 vbox.addEventListener('click',on_click, false);
1099 hbox.addEventListener('click',on_click, false);
1100 caption.addEventListener('click',on_click, false);
1101 caption.addEventListener('keypress',function(ev) {
1102 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1104 caption.setAttribute('style','-moz-user-focus: normal');
1105 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1106 caption.setAttribute('onblur','this.setAttribute("class","")');
1109 g.error.sdump('D_ERROR',E + '\n');
1113 /******************************************************************************************************/
1114 /* store the copies in the global xpcom stash */
1116 g.stash_and_close = function() {
1117 if (g.handle_update) {
1119 var r = g.network.request(
1120 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1121 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1122 [ ses(), g.copies, true ]
1124 if (typeof r.ilsevent != 'undefined') {
1125 g.error.standard_unexpected_error_alert('copy update',r);
1127 alert('Items added/modified.');
1129 /* FIXME -- revisit the return value here */
1131 alert('copy update error: ' + js2JSON(E));
1134 g.data.temp_copies = js2JSON( g.copies );
1135 g.data.stash('temp_copies');
1136 g.error.sdump('D_CAT','in modal window, g.data.temp_copies = \n' + g.data.temp_copies + '\n');
1140 /******************************************************************************************************/
1141 /* spawn copy notes interface */
1143 g.copy_notes = function() {
1144 JSAN.use('util.window'); var win = new util.window();
1145 win.open(urls.XUL_COPY_NOTES + '?copy_id=' + window.escape(g.copies[0].id()),'Copy Notes','chrome,resizable,modal');