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 if (field == 'price' || field == 'deposit_amount') {
440 if (value == '') { value = null; } else { JSAN.use('util.money'); value = util.money.sanitize( value ); }
442 for (var i = 0; i < g.copies.length; i++) {
443 var copy = g.copies[i];
445 copy[field]( value ); copy.ischanged('1');
452 /******************************************************************************************************/
453 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
455 g.apply_stat_cat = function(sc_id,entry_id) {
456 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
457 for (var i = 0; i < g.copies.length; i++) {
458 var copy = g.copies[i];
461 var temp = copy.stat_cat_entries();
462 if (!temp) temp = [];
463 temp = util.functional.filter_list(
466 return (obj.stat_cat() != sc_id);
469 if (entry_id > -1) temp.push(
470 util.functional.find_id_object_in_list(
471 g.data.hash.asc[sc_id].entries(),
475 copy.stat_cat_entries( temp );
478 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
483 /******************************************************************************************************/
484 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
486 g.apply_owning_lib = function(ou_id) {
487 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
489 for (var i = 0; i < g.copies.length; i++) {
490 var copy = g.copies[i];
492 if (!map_acn[copy.call_number()]) {
493 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
494 if (typeof volume.ilsevent != 'undefined') {
495 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);
498 map_acn[copy.call_number()] = volume;
500 var old_volume = map_acn[copy.call_number()];
501 var acn_id = g.network.simple_request(
502 'FM_ACN_FIND_OR_CREATE',
503 [ses(),old_volume.label(),old_volume.record(),ou_id]
505 if (typeof acn_id.ilsevent != 'undefined') {
506 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);
509 copy.call_number(acn_id);
512 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
518 /******************************************************************************************************/
519 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
521 g.safe_to_edit_copy_status = function() {
524 for (var i = 0; i < g.copies.length; i++) {
525 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
526 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
530 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
535 /******************************************************************************************************/
536 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
538 g.populate_alert_message_input = function(tb) {
540 var seen = {}; var s = '';
541 for (var i = 0; i < g.copies.length; i++) {
542 var msg = g.copies[i].alert_message();
544 if (typeof seen[msg] == 'undefined') {
550 tb.setAttribute('value',s);
552 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
556 /******************************************************************************************************/
557 /* This returns a list of acpl's appropriate for the copies being edited */
559 g.get_acpl_list = function() {
562 JSAN.use('util.functional');
564 function get(lib_id,only_these) {
565 g.data.stash_retrieve();
566 var label = 'acpl_list_for_lib_'+lib_id;
567 if (typeof g.data[label] == 'undefined') {
568 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
569 if (typeof robj.ilsevent != 'undefined') throw(robj);
571 for (var j = 0; j < robj.length; j++) {
572 var my_acpl = robj[j];
573 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
574 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
575 g.data.list.acpl.push( my_acpl );
577 if (only_these.indexOf( String( my_acpl.owning_lib() ) ) != -1) {
578 temp_list.push( my_acpl );
581 g.data[label] = temp_list; g.data.stash(label,'hash','list');
583 return g.data[label];
586 var libs = []; var map_acn = {};
587 for (var i = 0; i < g.copies.length; i++) {
588 var cn_id = g.copies[i].call_number();
590 if (! map_acn[ cn_id ]) {
591 map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
592 libs.push( map_acn[ cn_id ].owning_lib() );
597 for (var i in g.callnumbers) {
598 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 ); }
601 JSAN.use('util.fm_utils');
602 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
603 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
605 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
608 return get(ancestor, ancestors);
614 g.error.standard_unexpected_error_alert('get_acpl_list',E);
620 /******************************************************************************************************/
621 /* This keeps track of what fields have been edited for styling purposes */
625 /******************************************************************************************************/
626 /* These need data from the middle layer to render */
628 g.special_exception = {
629 'Owning Lib : Call Number' : function(label,value) {
630 JSAN.use('util.widgets');
631 if (value>0) { /* an existing call number */
633 api.FM_ACN_RETRIEVE.app,
634 api.FM_ACN_RETRIEVE.method,
637 var cn = '??? id = ' + value;
639 cn = req.getResultObject();
641 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
643 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
646 } else { /* a yet to be created call number */
648 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
652 'Creator' : function(label,value) {
653 if (value == null || value == '' || value == 'null') return;
654 g.network.simple_request(
655 'FM_AU_RETRIEVE_VIA_ID',
658 var p = '??? id = ' + value;
660 p = req.getResultObject();
664 g.error.sdump('D_ERROR','patron retrieve: ' + E);
666 JSAN.use('util.widgets');
667 util.widgets.set_text(label,p);
671 'Last Editor' : function(label,value) {
672 if (value == null || value == '' || value == 'null') return;
673 g.network.simple_request(
674 'FM_AU_RETRIEVE_VIA_ID',
677 var p = '??? id = ' + value;
679 p = req.getResultObject();
683 g.error.sdump('D_ERROR','patron retrieve: ' + E);
685 util.widgets.set_text(label,p);
692 /******************************************************************************************************/
693 g.readonly_stat_cat_names = [];
694 g.editable_stat_cat_names = [];
696 /******************************************************************************************************/
697 /* These get show in the left panel */
699 g.panes_and_field_names = {
706 render: 'fm.barcode();',
712 render: 'util.date.formatted_date( fm.create_date(), "%F");',
718 render: 'fm.creator();',
724 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
730 render: 'fm.editor();',
741 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
742 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);',
747 "Circulation Library",
749 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
750 //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);',
751 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);',
755 "Owning Lib : Call Number",
757 render: 'fm.call_number();',
758 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);',
764 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
765 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);',
777 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
778 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);',
784 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
785 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);',
791 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
792 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);',
799 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
800 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);',
807 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
808 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);',
815 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
816 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);',
820 "Circulation Modifier",
822 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
823 /*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);',*/
824 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);',
833 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
834 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);',
841 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
842 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);',
848 render: 'if (fm.deposit_amount() == null) { "<Unset>"; } else { util.money.sanitize( fm.deposit_amount() ); }',
849 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);',
855 render: 'if (fm.price() == null) { "<Unset>"; } else { util.money.sanitize( fm.price() ); }',
856 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);',
863 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
864 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);',
870 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
871 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);',
882 /******************************************************************************************************/
883 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
885 g.summarize = function( copies ) {
886 /******************************************************************************************************/
889 JSAN.use('util.date'); JSAN.use('util.money');
892 for (var i in g.panes_and_field_names) {
893 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
895 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
896 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
898 /******************************************************************************************************/
899 /* Loop through the field names */
901 for (var i = 0; i < g.field_names.length; i++) {
903 var field_name = g.field_names[i][0];
904 var render = g.field_names[i][1].render;
905 g.summary[ field_name ] = {};
907 /******************************************************************************************************/
908 /* Loop through the copies */
910 for (var j = 0; j < copies.length; j++) {
913 var cmd = render || ('fm.' + field_name + '();');
916 /**********************************************************************************************/
917 /* Try to retrieve the value for this field for this copy */
922 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
924 if (typeof value == 'object' && value != null) {
925 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
928 /**********************************************************************************************/
929 /* Tally the count */
931 if (g.summary[ field_name ][ value ]) {
932 g.summary[ field_name ][ value ]++;
934 g.summary[ field_name ][ value ] = 1;
938 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
941 /******************************************************************************************************/
942 /* Display the summarized data and inputs for editing */
944 g.render = function() {
946 /******************************************************************************************************/
947 /* Library setup and clear any existing interface */
949 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
951 for (var i in g.panes_and_field_names) {
952 var p = document.getElementById(i);
953 if (p) util.widgets.remove_children(p);
956 /******************************************************************************************************/
957 /* Prepare the panes */
959 var groupbox; var caption; var vbox; var grid; var rows;
961 /******************************************************************************************************/
962 /* Loop through the field names */
964 for (h in g.panes_and_field_names) {
965 if (!document.getElementById(h)) continue;
966 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
968 var f = g.panes_and_field_names[h][i]; var fn = f[0];
969 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
970 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
971 caption = document.createElement('caption'); groupbox.appendChild(caption);
972 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
973 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
974 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
975 grid.setAttribute('flex','1');
976 rows = grid.lastChild;
979 /**************************************************************************************/
980 /* Loop through each value for the field */
982 for (var j in g.summary[fn]) {
983 var value = j; var count = g.summary[fn][j];
984 row = document.createElement('row'); rows.appendChild(row);
985 var label1 = document.createElement('description'); row.appendChild(label1);
986 if (g.special_exception[ fn ]) {
987 g.special_exception[ fn ]( label1, value );
989 label1.appendChild( document.createTextNode(value) );
991 var label2 = document.createElement('description'); row.appendChild(label2);
992 var unit = count == 1 ? 'copy' : 'copies';
993 label2.appendChild( document.createTextNode(count + ' ' + unit) );
995 var hbox = document.createElement('hbox');
996 hbox.setAttribute('id',fn);
997 groupbox.appendChild(hbox);
998 var hbox2 = document.createElement('hbox');
999 groupbox.appendChild(hbox2);
1001 /**************************************************************************************/
1002 /* Render the input widget */
1004 if (f[1].input && g.edit) {
1005 g.render_input(hbox,f[1]);
1009 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1015 /******************************************************************************************************/
1016 /* This actually draws the change button and input widget for a given field */
1017 g.render_input = function(node,blob) {
1019 // node = hbox ; groupbox -> hbox, hbox
1021 var groupbox = node.parentNode;
1022 var caption = groupbox.firstChild;
1023 var vbox = node.previousSibling;
1025 var hbox2 = node.nextSibling;
1027 var input_cmd = blob.input;
1028 var render_cmd = blob.render;
1030 var block = false; var first = true;
1032 function on_mouseover(ev) {
1033 groupbox.setAttribute('style','background: white');
1036 function on_mouseout(ev) {
1037 groupbox.setAttribute('style','');
1040 vbox.addEventListener('mouseover',on_mouseover,false);
1041 vbox.addEventListener('mouseout',on_mouseout,false);
1042 groupbox.addEventListener('mouseover',on_mouseover,false);
1043 groupbox.addEventListener('mouseout',on_mouseout,false);
1044 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1045 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1047 function on_click(ev){
1049 if (block) return; block = true;
1051 function post_c(v) {
1053 /* FIXME - kludgy */
1054 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1058 f = input_cmd.match(/apply\("(.+?)",/)[1];
1061 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1067 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1071 g.summarize( g.copies );
1073 document.getElementById(caption.id).focus();
1077 g.error.standard_unexpected_error_alert('post_c',E);
1080 var x; var c; eval( input_cmd );
1082 util.widgets.remove_children(vbox);
1083 util.widgets.remove_children(hbox);
1084 util.widgets.remove_children(hbox2);
1085 hbox.appendChild(x);
1086 var apply = document.createElement('button');
1087 apply.setAttribute('label','Apply');
1088 apply.setAttribute('accesskey','A');
1089 hbox2.appendChild(apply);
1090 apply.addEventListener('command',function() { c(x.value); },false);
1091 var cancel = document.createElement('button');
1092 cancel.setAttribute('label','Cancel');
1093 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1094 hbox2.appendChild(cancel);
1095 setTimeout( function() { x.focus(); }, 0 );
1098 g.error.standard_unexpected_error_alert('render_input',E);
1101 vbox.addEventListener('click',on_click, false);
1102 hbox.addEventListener('click',on_click, false);
1103 caption.addEventListener('click',on_click, false);
1104 caption.addEventListener('keypress',function(ev) {
1105 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1107 caption.setAttribute('style','-moz-user-focus: normal');
1108 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1109 caption.setAttribute('onblur','this.setAttribute("class","")');
1112 g.error.sdump('D_ERROR',E + '\n');
1116 /******************************************************************************************************/
1117 /* store the copies in the global xpcom stash */
1119 g.stash_and_close = function() {
1120 if (g.handle_update) {
1122 var r = g.network.request(
1123 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1124 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1125 [ ses(), g.copies, true ]
1127 if (typeof r.ilsevent != 'undefined') {
1128 g.error.standard_unexpected_error_alert('copy update',r);
1130 alert('Items added/modified.');
1132 /* FIXME -- revisit the return value here */
1134 alert('copy update error: ' + js2JSON(E));
1137 g.data.temp_copies = js2JSON( g.copies );
1138 g.data.stash('temp_copies');
1139 g.error.sdump('D_CAT','in modal window, g.data.temp_copies = \n' + g.data.temp_copies + '\n');
1143 /******************************************************************************************************/
1144 /* spawn copy notes interface */
1146 g.copy_notes = function() {
1147 JSAN.use('util.window'); var win = new util.window();
1148 win.open(urls.XUL_COPY_NOTES + '?copy_id=' + window.escape(g.copies[0].id()),'Copy Notes','chrome,resizable,modal');