7 /******************************************************************************************************/
8 /* setup JSAN and some initial libraries */
10 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
11 if (typeof JSAN == 'undefined') { throw( "The JSAN library object is missing."); }
12 JSAN.errorLevel = "die"; // none, warn, or die
13 JSAN.addRepository('/xul/server/');
14 JSAN.use('util.error'); g.error = new util.error();
15 g.error.sdump('D_TRACE','my_init() for cat/copy_editor.xul');
17 JSAN.use('util.functional');
18 JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
19 JSAN.use('util.network'); g.network = new util.network();
21 g.docid = xul_param('docid',{'modal_xulG':true});
22 g.handle_update = xul_param('handle_update',{'modal_xulG':true});
24 /******************************************************************************************************/
25 /* Get the copy ids from various sources and flesh them */
27 var copy_ids = xul_param('copy_ids',{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xulG':true,'JSON2js_if_xpcom':true,'stash_name':'temp_copy_ids','clear_xpcom':true,'modal_xulG':true});
28 if (!copy_ids) copy_ids = [];
30 if (copy_ids.length > 0) g.copies = g.network.simple_request(
31 'FM_ACP_FLESHED_BATCH_RETRIEVE',
35 /******************************************************************************************************/
36 /* And other fleshed copies if any */
38 if (!g.copies) g.copies = [];
39 var c = xul_param('copies',{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xpcom':true,'stash_name':'temp_copies','clear_xpcom':true,'modal_xulG':true})
40 if (c) g.copies = g.copies.concat(c);
42 /******************************************************************************************************/
43 /* We try to retrieve callnumbers for existing copies, but for new copies, we rely on this */
45 g.callnumbers = xul_param('callnumbers',{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xpcom':true,'stash_name':'temp_callnumbers','clear_xpcom':true,'modal_xulG':true});
48 /******************************************************************************************************/
49 /* Quick fix, this was defined inline in the global scope but now needs g.error and g.copies from my_init */
53 /******************************************************************************************************/
54 /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
56 if (xul_param('edit',{'modal_xulG':true}) == '1') {
58 document.getElementById('caption').setAttribute('label','Copy Editor');
59 document.getElementById('save').setAttribute('hidden','false');
60 g.retrieve_templates();
62 $('top_nav').setAttribute('hidden','true');
65 if (g.copies.length > 0 && g.copies[0].id() < 0) {
66 document.getElementById('copy_notes').setAttribute('hidden','true');
67 g.apply("status",5 /* In Process */);
68 $('save').setAttribute('label','Create Copies');
70 g.panes_and_field_names.left_pane =
75 render: 'typeof fm.status() == "object" ? fm.status().name() : g.data.hash.ccs[ fm.status() ].name()',
76 input: g.safe_to_edit_copy_status() ? 'c = function(v){ g.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.ccs, function(obj) { return [ obj.name(), obj.id(), typeof my_constants.magical_statuses[obj.id()] != "undefined" ? true : false ]; } ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);' : undefined,
77 //input: 'c = function(v){ g.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( util.functional.filter_list( g.data.list.ccs, function(obj) { return typeof my_constants.magical_statuses[obj.id()] == "undefined"; } ), function(obj) { return [ obj.name(), obj.id() ]; } ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
80 ].concat(g.panes_and_field_names.left_pane);
83 if (g.copies.length != 1) {
84 document.getElementById('copy_notes').setAttribute('hidden','true');
87 /******************************************************************************************************/
88 /* Show the Record Details? */
91 document.getElementById('brief_display').setAttribute(
93 urls.XUL_BIB_BRIEF + '?docid=' + g.docid
96 document.getElementById('brief_display').setAttribute('hidden','true');
99 /******************************************************************************************************/
100 /* Add stat cats to the panes_and_field_names.right_pane4 */
102 g.stat_cat_seen = {};
104 function add_stat_cat(sc) {
106 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; g.data.stash('hash'); }
110 if (typeof sc == 'object') {
115 if (typeof g.stat_cat_seen[sc_id] != 'undefined') { return; }
117 g.stat_cat_seen[ sc_id ] = 1;
119 if (typeof sc != 'object') {
121 sc = g.network.simple_request(
122 'FM_ASC_BATCH_RETRIEVE',
128 g.data.hash.asc[ sc.id() ] = sc; g.data.stash('hash');
130 var label_name = g.data.hash.aou[ sc.owner() ].shortname() + " : " + sc.name();
135 render: 'var l = util.functional.find_list( fm.stat_cat_entries(), function(e){ return e.stat_cat() == '
136 + sc.id() + '; } ); l ? l.value() : "<Unset>";',
137 input: 'c = function(v){ g.apply_stat_cat(' + sc.id() + ',v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "<Remove Stat Cat>", -1 ] ].concat( util.functional.map_list( g.data.hash.asc[' + sc.id()
138 + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ) ).sort() ); '
139 //input: 'c = function(v){ g.apply_stat_cat(' + sc.id() + ',v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "<Remove Stat Cat>", null ] ].concat( util.functional.map_list( g.data.hash.asc[' + sc.id()
140 // + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ).sort() ) ); '
141 + 'x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c),false);',
145 dump('temp_array = ' + js2JSON(temp_array) + '\n');
147 g.panes_and_field_names.right_pane4.push( temp_array );
150 /* The stat cats for the pertinent library */
151 for (var i = 0; i < g.data.list.my_asc.length; i++) {
152 add_stat_cat( g.data.list.my_asc[i] );
155 /* Other stat cats present on these copies */
156 for (var i = 0; i < g.copies.length; i++) {
157 var entries = g.copies[i].stat_cat_entries();
158 if (!entries) entries = [];
159 for (var j = 0; j < entries.length; j++) {
160 var sc_id = entries[j].stat_cat();
161 add_stat_cat( sc_id );
165 /******************************************************************************************************/
166 /* Backup copies :) */
168 g.original_copies = js2JSON( g.copies );
170 /******************************************************************************************************/
173 g.summarize( g.copies );
177 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
178 "system administrator or software developer the following:\ncat/copy_editor.xul\n" + E + '\n';
179 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
184 /******************************************************************************************************/
185 /* File picker for template export/import */
187 function pick_file(mode) {
188 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
189 var nsIFilePicker = Components.interfaces.nsIFilePicker;
190 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance( nsIFilePicker );
193 mode == 'open' ? "Import Templates File" : "Save Templates File As",
194 mode == 'open' ? nsIFilePicker.modeOpen : nsIFilePicker.modeSave
196 fp.appendFilters( nsIFilePicker.filterAll );
197 var fp_result = fp.show();
198 if ( ( fp_result == nsIFilePicker.returnOK || fp_result == nsIFilePicker.returnReplace ) && fp.file ) {
205 /******************************************************************************************************/
206 /* Retrieve Templates */
208 g.retrieve_templates = function() {
210 JSAN.use('util.widgets'); JSAN.use('util.functional');
212 var robj = g.network.simple_request('FM_AUS_RETRIEVE',[ses(),g.data.list.au[0].id()]);
213 if (typeof robj['staff_client.copy_editor.templates'] != 'undefined') {
214 g.templates = robj['staff_client.copy_editor.templates'];
216 util.widgets.remove_children('template_placeholder');
217 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
219 g.template_menu = util.widgets.make_menulist( list );
220 $('template_placeholder').appendChild(g.template_menu);
222 g.error.standard_unexpected_error_alert('Error retrieving templates',E);
226 /******************************************************************************************************/
229 g.apply_template = function() {
231 var name = g.template_menu.value;
232 if (g.templates[ name ] != 'undefined') {
233 var template = g.templates[ name ];
234 for (var i in template) {
235 g.changed[ i ] = template[ i ];
236 switch( template[i].type ) {
238 g.apply(template[i].field,template[i].value);
241 if (g.stat_cat_seen[ template[i].field ]) g.apply_stat_cat(template[i].field,template[i].value);
244 g.apply_owning_lib(template[i].value);
248 g.summarize( g.copies );
252 g.error.standard_unexpected_error_alert('Error applying template',E);
256 /******************************************************************************************************/
257 /* Save as Template */
259 g.save_template = function() {
261 var name = window.prompt('Enter template name:','','Save As Template');
263 g.templates[name] = g.changed;
264 var robj = g.network.simple_request(
265 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
267 if (typeof robj.ilsevent != 'undefined') {
270 alert('Template "' + name + '" saved.');
274 g.retrieve_templates();
276 g.error.standard_unexpected_error_alert('Error saving template',E);
282 g.error.standard_unexpected_error_alert('Error saving template',E);
286 /******************************************************************************************************/
287 /* Delete Template */
289 g.delete_template = function() {
291 var name = g.template_menu.value;
293 if (! window.confirm('Delete template "' + name + '"?') ) return;
294 delete(g.templates[name]);
295 var robj = g.network.simple_request(
296 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
298 if (typeof robj.ilsevent != 'undefined') {
301 alert('Template "' + name + '" deleted.');
305 g.retrieve_templates();
307 g.error.standard_unexpected_error_alert('Error deleting template',E);
313 g.error.standard_unexpected_error_alert('Error deleting template',E);
317 /******************************************************************************************************/
318 /* Export Templates */
320 g.export_templates = function() {
322 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
323 JSAN.use('util.file');
324 var f = pick_file('save');
327 var r = G.error.yns_alert(
328 'Would you like to overwrite the existing file ' + f.leafName + '?',
329 'Templates Export Warning',
333 'Check here to confirm this message'
335 if (r != 0) { file.close(); alert('Not overwriting file.'); return; }
337 var e_file = new util.file(''); e_file._file = f;
338 e_file.write_content( 'truncate', js2JSON( g.templates ) );
340 alert('Templates exported as file ' + f.leafName);
342 alert('File not chosen for export.');
346 g.error.standard_unexpected_error_alert('Error exporting templates',E);
350 /******************************************************************************************************/
351 /* Import Templates */
353 g.import_templates = function() {
355 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
356 JSAN.use('util.file');
357 var f = pick_file('open');
358 if (f && f.exists()) {
359 var i_file = new util.file(''); i_file._file = f;
360 var temp = JSON2js( i_file.get_content() );
362 for (var i in temp) {
364 if (g.templates[i]) {
366 var r = g.error.yns_alert(
367 'Replace the existing template with the imported template?\n' + g.error.pretty_print( js2JSON( temp[i] ) ),
368 'Template ' + i + ' already exists.','Yes','No',null,'Click here'
371 if (r == 0 /* Yes */) g.templates[i] = temp[i];
375 g.templates[i] = temp[i];
381 var r = g.error.yns_alert(
382 'Save all of these imported templates permanently to this account?',
383 'Final Warning', 'Yes', 'No', null, 'Click here'
386 if (r == 0 /* Yes */) {
387 var robj = g.network.simple_request(
388 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
390 if (typeof robj.ilsevent != 'undefined') {
393 alert('All templates saved.');
397 g.retrieve_templates();
399 g.error.standard_unexpected_error_alert('Error saving templates',E);
405 util.widgets.remove_children('template_placeholder');
406 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
407 g.template_menu = util.widgets.make_menulist( list );
408 $('template_placeholder').appendChild(g.template_menu);
409 alert("Note: These imported templates will get saved along with any new template you try to create, but if that doesn't happen, then these templates will dissappear with the next invocation of the item attribute editor.");
413 alert('File not chosen for import.');
416 g.error.standard_unexpected_error_alert('Error importing templates',E);
421 /******************************************************************************************************/
422 /* Restore backup copies */
424 g.reset = function() {
426 g.copies = JSON2js( g.original_copies );
427 g.summarize( g.copies );
431 /******************************************************************************************************/
432 /* Apply a value to a specific field on all the copies being edited */
434 g.apply = function(field,value) {
435 g.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
436 if (value == '<HACK:KLUDGE:NULL>') value = null;
437 if (field == 'alert_message') { value = value.replace(/^\W+$/g,''); }
438 if (field == 'price' || field == 'deposit_amount') {
439 if (value == '') { value = null; } else { JSAN.use('util.money'); value = util.money.sanitize( value ); }
441 for (var i = 0; i < g.copies.length; i++) {
442 var copy = g.copies[i];
444 copy[field]( value ); copy.ischanged('1');
451 /******************************************************************************************************/
452 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
454 g.apply_stat_cat = function(sc_id,entry_id) {
455 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
456 for (var i = 0; i < g.copies.length; i++) {
457 var copy = g.copies[i];
460 var temp = copy.stat_cat_entries();
461 if (!temp) temp = [];
462 temp = util.functional.filter_list(
465 return (obj.stat_cat() != sc_id);
468 if (entry_id > -1) temp.push(
469 util.functional.find_id_object_in_list(
470 g.data.hash.asc[sc_id].entries(),
474 copy.stat_cat_entries( temp );
477 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
482 /******************************************************************************************************/
483 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
485 g.apply_owning_lib = function(ou_id) {
486 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
488 for (var i = 0; i < g.copies.length; i++) {
489 var copy = g.copies[i];
491 if (!map_acn[copy.call_number()]) {
492 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
493 if (typeof volume.ilsevent != 'undefined') {
494 g.error.standard_unexpected_error_alert('Error retrieving Volume information for copy ' + copy.barcode() + ". The owning library for this copy won't be changed.",volume);
497 map_acn[copy.call_number()] = volume;
499 var old_volume = map_acn[copy.call_number()];
500 var acn_id = g.network.simple_request(
501 'FM_ACN_FIND_OR_CREATE',
502 [ses(),old_volume.label(),old_volume.record(),ou_id]
504 if (typeof acn_id.ilsevent != 'undefined') {
505 g.error.standard_unexpected_error_alert('Error changing owning lib for copy ' + copy.barcode() + ". The owning library for this copy won't be changed.",acn_id);
508 copy.call_number(acn_id);
511 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
516 /******************************************************************************************************/
517 /* This returns true if none of the copies being edited are pre-cats */
519 g.safe_to_change_owning_lib = function() {
522 for (var i = 0; i < g.copies.length; i++) {
523 var cn = g.copies[i].call_number();
524 if (typeof cn == 'object') { cn = cn.id(); }
525 if (cn == -1) { safe = false; }
529 g.error.standard_unexpected_error_alert('safe_to_change_owning_lib?',E);
534 /******************************************************************************************************/
535 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
537 g.safe_to_edit_copy_status = function() {
540 for (var i = 0; i < g.copies.length; i++) {
541 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
542 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
546 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
551 /******************************************************************************************************/
552 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
554 g.populate_alert_message_input = function(tb) {
556 var seen = {}; var s = '';
557 for (var i = 0; i < g.copies.length; i++) {
558 var msg = g.copies[i].alert_message();
560 if (typeof seen[msg] == 'undefined') {
566 tb.setAttribute('value',s);
568 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
572 /******************************************************************************************************/
573 /* This returns a list of acpl's appropriate for the copies being edited */
575 g.get_acpl_list = function() {
578 JSAN.use('util.functional');
580 function get(lib_id,only_these) {
581 g.data.stash_retrieve();
582 var label = 'acpl_list_for_lib_'+lib_id;
583 if (typeof g.data[label] == 'undefined') {
584 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
585 if (typeof robj.ilsevent != 'undefined') throw(robj);
587 for (var j = 0; j < robj.length; j++) {
588 var my_acpl = robj[j];
589 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
590 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
591 g.data.list.acpl.push( my_acpl );
593 if (only_these.indexOf( String( my_acpl.owning_lib() ) ) != -1) {
594 temp_list.push( my_acpl );
597 g.data[label] = temp_list; g.data.stash(label,'hash','list');
599 return g.data[label];
602 var libs = []; var map_acn = {};
603 for (var i = 0; i < g.copies.length; i++) {
604 var cn_id = g.copies[i].call_number();
606 if (! map_acn[ cn_id ]) {
607 map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
608 libs.push( map_acn[ cn_id ].owning_lib() );
613 for (var i in g.callnumbers) {
614 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 ); }
617 JSAN.use('util.fm_utils');
618 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
619 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
621 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
624 return get(ancestor, ancestors);
630 g.error.standard_unexpected_error_alert('get_acpl_list',E);
636 /******************************************************************************************************/
637 /* This keeps track of what fields have been edited for styling purposes */
641 /******************************************************************************************************/
642 /* These need data from the middle layer to render */
644 g.special_exception = {
645 'Owning Lib : Call Number' : function(label,value) {
646 JSAN.use('util.widgets');
647 if (value>0) { /* an existing call number */
649 api.FM_ACN_RETRIEVE.app,
650 api.FM_ACN_RETRIEVE.method,
653 var cn = '??? id = ' + value;
655 cn = req.getResultObject();
657 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
659 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
662 } else { /* a yet to be created call number */
664 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
668 'Creator' : 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 JSAN.use('util.widgets');
683 util.widgets.set_text(label,p);
687 'Last Editor' : function(label,value) {
688 if (value == null || value == '' || value == 'null') return;
689 g.network.simple_request(
690 'FM_AU_RETRIEVE_VIA_ID',
693 var p = '??? id = ' + value;
695 p = req.getResultObject();
699 g.error.sdump('D_ERROR','patron retrieve: ' + E);
701 util.widgets.set_text(label,p);
708 /******************************************************************************************************/
709 g.readonly_stat_cat_names = [];
710 g.editable_stat_cat_names = [];
712 /******************************************************************************************************/
713 /* These get show in the left panel */
715 function init_panes() {
716 g.panes_and_field_names = {
723 render: 'fm.barcode();',
729 render: 'util.date.formatted_date( fm.create_date(), "%F");',
735 render: 'fm.creator();',
741 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
747 render: 'fm.editor();',
758 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
759 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);',
764 "Circulation Library",
766 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
767 //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);',
768 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);',
772 "Owning Lib : Call Number",
774 render: 'fm.call_number();',
775 input: g.safe_to_change_owning_lib() ? 'c = function(v){ g.apply_owning_lib(v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.aou, function(obj) { var sname = obj.shortname(); for (i = sname.length; i < 20; i++) sname += " "; return [ obj.name() ? sname + " " + obj.name() : obj.shortname(), obj.id(), ( ! get_bool( g.data.hash.aout[ obj.ou_type() ].can_have_vols() ) ), ( g.data.hash.aout[ obj.ou_type() ].depth() * 2), ]; }), g.data.list.au[0].ws_ou()); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);' : undefined,
781 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
782 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);',
794 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
795 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);',
801 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
802 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);',
808 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
809 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);',
816 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
817 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);',
824 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
825 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);',
832 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
833 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);',
837 "Circulation Modifier",
839 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
840 /*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);',*/
841 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);',
850 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
851 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);',
858 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
859 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);',
865 render: 'if (fm.deposit_amount() == null) { "<Unset>"; } else { util.money.sanitize( fm.deposit_amount() ); }',
866 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);',
872 render: 'if (fm.price() == null) { "<Unset>"; } else { util.money.sanitize( fm.price() ); }',
873 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);',
880 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
881 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);',
887 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
888 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);',
900 /******************************************************************************************************/
901 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
903 g.summarize = function( copies ) {
904 /******************************************************************************************************/
907 JSAN.use('util.date'); JSAN.use('util.money');
910 for (var i in g.panes_and_field_names) {
911 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
913 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
914 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
916 /******************************************************************************************************/
917 /* Loop through the field names */
919 for (var i = 0; i < g.field_names.length; i++) {
921 var field_name = g.field_names[i][0];
922 var render = g.field_names[i][1].render;
923 g.summary[ field_name ] = {};
925 /******************************************************************************************************/
926 /* Loop through the copies */
928 for (var j = 0; j < copies.length; j++) {
931 var cmd = render || ('fm.' + field_name + '();');
934 /**********************************************************************************************/
935 /* Try to retrieve the value for this field for this copy */
940 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
942 if (typeof value == 'object' && value != null) {
943 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
946 /**********************************************************************************************/
947 /* Tally the count */
949 if (g.summary[ field_name ][ value ]) {
950 g.summary[ field_name ][ value ]++;
952 g.summary[ field_name ][ value ] = 1;
956 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
959 /******************************************************************************************************/
960 /* Display the summarized data and inputs for editing */
962 g.render = function() {
964 /******************************************************************************************************/
965 /* Library setup and clear any existing interface */
967 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
969 for (var i in g.panes_and_field_names) {
970 var p = document.getElementById(i);
971 if (p) util.widgets.remove_children(p);
974 /******************************************************************************************************/
975 /* Prepare the panes */
977 var groupbox; var caption; var vbox; var grid; var rows;
979 /******************************************************************************************************/
980 /* Loop through the field names */
982 for (h in g.panes_and_field_names) {
983 if (!document.getElementById(h)) continue;
984 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
986 var f = g.panes_and_field_names[h][i]; var fn = f[0];
987 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
988 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
989 caption = document.createElement('caption'); groupbox.appendChild(caption);
990 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
991 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
992 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
993 grid.setAttribute('flex','1');
994 rows = grid.lastChild;
997 /**************************************************************************************/
998 /* Loop through each value for the field */
1000 for (var j in g.summary[fn]) {
1001 var value = j; var count = g.summary[fn][j];
1002 row = document.createElement('row'); rows.appendChild(row);
1003 var label1 = document.createElement('description'); row.appendChild(label1);
1004 if (g.special_exception[ fn ]) {
1005 g.special_exception[ fn ]( label1, value );
1007 label1.appendChild( document.createTextNode(value) );
1009 var label2 = document.createElement('description'); row.appendChild(label2);
1010 var unit = count == 1 ? 'copy' : 'copies';
1011 label2.appendChild( document.createTextNode(count + ' ' + unit) );
1013 var hbox = document.createElement('hbox');
1014 hbox.setAttribute('id',fn);
1015 groupbox.appendChild(hbox);
1016 var hbox2 = document.createElement('hbox');
1017 groupbox.appendChild(hbox2);
1019 /**************************************************************************************/
1020 /* Render the input widget */
1022 if (f[1].input && g.edit) {
1023 g.render_input(hbox,f[1]);
1027 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1033 /******************************************************************************************************/
1034 /* This actually draws the change button and input widget for a given field */
1035 g.render_input = function(node,blob) {
1037 // node = hbox ; groupbox -> hbox, hbox
1039 var groupbox = node.parentNode;
1040 var caption = groupbox.firstChild;
1041 var vbox = node.previousSibling;
1043 var hbox2 = node.nextSibling;
1045 var input_cmd = blob.input;
1046 var render_cmd = blob.render;
1048 var block = false; var first = true;
1050 function on_mouseover(ev) {
1051 groupbox.setAttribute('style','background: white');
1054 function on_mouseout(ev) {
1055 groupbox.setAttribute('style','');
1058 vbox.addEventListener('mouseover',on_mouseover,false);
1059 vbox.addEventListener('mouseout',on_mouseout,false);
1060 groupbox.addEventListener('mouseover',on_mouseover,false);
1061 groupbox.addEventListener('mouseout',on_mouseout,false);
1062 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1063 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1065 function on_click(ev){
1067 if (block) return; block = true;
1069 function post_c(v) {
1071 /* FIXME - kludgy */
1072 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1076 f = input_cmd.match(/apply\("(.+?)",/)[1];
1079 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1085 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1089 g.summarize( g.copies );
1091 document.getElementById(caption.id).focus();
1095 g.error.standard_unexpected_error_alert('post_c',E);
1098 var x; var c; eval( input_cmd );
1100 util.widgets.remove_children(vbox);
1101 util.widgets.remove_children(hbox);
1102 util.widgets.remove_children(hbox2);
1103 hbox.appendChild(x);
1104 var apply = document.createElement('button');
1105 apply.setAttribute('label','Apply');
1106 apply.setAttribute('accesskey','A');
1107 hbox2.appendChild(apply);
1108 apply.addEventListener('command',function() { c(x.value); },false);
1109 var cancel = document.createElement('button');
1110 cancel.setAttribute('label','Cancel');
1111 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1112 hbox2.appendChild(cancel);
1113 setTimeout( function() { x.focus(); }, 0 );
1116 g.error.standard_unexpected_error_alert('render_input',E);
1119 vbox.addEventListener('click',on_click, false);
1120 hbox.addEventListener('click',on_click, false);
1121 caption.addEventListener('click',on_click, false);
1122 caption.addEventListener('keypress',function(ev) {
1123 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1125 caption.setAttribute('style','-moz-user-focus: normal');
1126 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1127 caption.setAttribute('onblur','this.setAttribute("class","")');
1130 g.error.sdump('D_ERROR',E + '\n');
1134 /******************************************************************************************************/
1135 /* store the copies in the global xpcom stash */
1137 g.stash_and_close = function() {
1139 if (g.handle_update) {
1141 var r = g.network.request(
1142 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1143 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1144 [ ses(), g.copies, true ]
1146 if (typeof r.ilsevent != 'undefined') {
1147 g.error.standard_unexpected_error_alert('copy update',r);
1149 alert('Items added/modified.');
1151 /* FIXME -- revisit the return value here */
1153 alert('copy update error: ' + js2JSON(E));
1156 //g.data.temp_copies = js2JSON( g.copies );
1157 //g.data.stash('temp_copies');
1158 xulG.copies = g.copies;
1159 update_modal_xulG(xulG);
1162 g.error.standard_unexpected_error_alert('stash and close',E);
1166 /******************************************************************************************************/
1167 /* spawn copy notes interface */
1169 g.copy_notes = function() {
1170 JSAN.use('util.window'); var win = new util.window();
1172 urls.XUL_COPY_NOTES,
1173 //+ '?copy_id=' + window.escape(g.copies[0].id()),
1174 'Copy Notes','chrome,resizable,modal',
1175 { 'copy_id' : g.copies[0].id() }