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});
47 /******************************************************************************************************/
48 /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
50 if (xul_param('edit',{'modal_xulG':true}) == '1') {
52 document.getElementById('caption').setAttribute('label','Copy Editor');
53 document.getElementById('save').setAttribute('hidden','false');
54 g.retrieve_templates();
56 $('top_nav').setAttribute('hidden','true');
59 if (g.copies.length > 0 && g.copies[0].id() < 0) {
60 document.getElementById('copy_notes').setAttribute('hidden','true');
61 g.apply("status",5 /* In Process */);
62 $('save').setAttribute('label','Create Copies');
64 g.panes_and_field_names.left_pane =
69 render: 'typeof fm.status() == "object" ? fm.status().name() : g.data.hash.ccs[ fm.status() ].name()',
70 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,
71 //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);',
74 ].concat(g.panes_and_field_names.left_pane);
77 if (g.copies.length != 1) {
78 document.getElementById('copy_notes').setAttribute('hidden','true');
81 /******************************************************************************************************/
82 /* Show the Record Details? */
85 document.getElementById('brief_display').setAttribute(
87 urls.XUL_BIB_BRIEF + '?docid=' + g.docid
90 document.getElementById('brief_display').setAttribute('hidden','true');
93 /******************************************************************************************************/
94 /* Add stat cats to the panes_and_field_names.right_pane4 */
98 function add_stat_cat(sc) {
100 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; g.data.stash('hash'); }
104 if (typeof sc == 'object') {
109 if (typeof g.stat_cat_seen[sc_id] != 'undefined') { return; }
111 g.stat_cat_seen[ sc_id ] = 1;
113 if (typeof sc != 'object') {
115 sc = g.network.simple_request(
116 'FM_ASC_BATCH_RETRIEVE',
122 g.data.hash.asc[ sc.id() ] = sc; g.data.stash('hash');
124 var label_name = g.data.hash.aou[ sc.owner() ].shortname() + " : " + sc.name();
129 render: 'var l = util.functional.find_list( fm.stat_cat_entries(), function(e){ return e.stat_cat() == '
130 + sc.id() + '; } ); l ? l.value() : "<Unset>";',
131 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()
132 + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ) ).sort() ); '
133 //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()
134 // + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ).sort() ) ); '
135 + 'x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c),false);',
139 dump('temp_array = ' + js2JSON(temp_array) + '\n');
141 g.panes_and_field_names.right_pane4.push( temp_array );
144 /* The stat cats for the pertinent library */
145 for (var i = 0; i < g.data.list.my_asc.length; i++) {
146 add_stat_cat( g.data.list.my_asc[i] );
149 /* Other stat cats present on these copies */
150 for (var i = 0; i < g.copies.length; i++) {
151 var entries = g.copies[i].stat_cat_entries();
152 if (!entries) entries = [];
153 for (var j = 0; j < entries.length; j++) {
154 var sc_id = entries[j].stat_cat();
155 add_stat_cat( sc_id );
159 /******************************************************************************************************/
160 /* Backup copies :) */
162 g.original_copies = js2JSON( g.copies );
164 /******************************************************************************************************/
167 g.summarize( g.copies );
171 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
172 "system administrator or software developer the following:\ncat/copy_editor.xul\n" + E + '\n';
173 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
178 /******************************************************************************************************/
179 /* File picker for template export/import */
181 function pick_file(mode) {
182 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
183 var nsIFilePicker = Components.interfaces.nsIFilePicker;
184 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance( nsIFilePicker );
187 mode == 'open' ? "Import Templates File" : "Save Templates File As",
188 mode == 'open' ? nsIFilePicker.modeOpen : nsIFilePicker.modeSave
190 fp.appendFilters( nsIFilePicker.filterAll );
191 var fp_result = fp.show();
192 if ( ( fp_result == nsIFilePicker.returnOK || fp_result == nsIFilePicker.returnReplace ) && fp.file ) {
199 /******************************************************************************************************/
200 /* Retrieve Templates */
202 g.retrieve_templates = function() {
204 JSAN.use('util.widgets'); JSAN.use('util.functional');
206 var robj = g.network.simple_request('FM_AUS_RETRIEVE',[ses(),g.data.list.au[0].id()]);
207 if (typeof robj['staff_client.copy_editor.templates'] != 'undefined') {
208 g.templates = robj['staff_client.copy_editor.templates'];
210 util.widgets.remove_children('template_placeholder');
211 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
213 g.template_menu = util.widgets.make_menulist( list );
214 $('template_placeholder').appendChild(g.template_menu);
216 g.error.standard_unexpected_error_alert('Error retrieving templates',E);
220 /******************************************************************************************************/
223 g.apply_template = function() {
225 var name = g.template_menu.value;
226 if (g.templates[ name ] != 'undefined') {
227 var template = g.templates[ name ];
228 for (var i in template) {
229 g.changed[ i ] = template[ i ];
230 switch( template[i].type ) {
232 g.apply(template[i].field,template[i].value);
235 if (g.stat_cat_seen[ template[i].field ]) g.apply_stat_cat(template[i].field,template[i].value);
238 g.apply_owning_lib(template[i].value);
242 g.summarize( g.copies );
246 g.error.standard_unexpected_error_alert('Error applying template',E);
250 /******************************************************************************************************/
251 /* Save as Template */
253 g.save_template = function() {
255 var name = window.prompt('Enter template name:','','Save As Template');
257 g.templates[name] = g.changed;
258 var robj = g.network.simple_request(
259 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
261 if (typeof robj.ilsevent != 'undefined') {
264 alert('Template "' + name + '" saved.');
268 g.retrieve_templates();
270 g.error.standard_unexpected_error_alert('Error saving template',E);
276 g.error.standard_unexpected_error_alert('Error saving template',E);
280 /******************************************************************************************************/
281 /* Delete Template */
283 g.delete_template = function() {
285 var name = g.template_menu.value;
287 if (! window.confirm('Delete template "' + name + '"?') ) return;
288 delete(g.templates[name]);
289 var robj = g.network.simple_request(
290 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
292 if (typeof robj.ilsevent != 'undefined') {
295 alert('Template "' + name + '" deleted.');
299 g.retrieve_templates();
301 g.error.standard_unexpected_error_alert('Error deleting template',E);
307 g.error.standard_unexpected_error_alert('Error deleting template',E);
311 /******************************************************************************************************/
312 /* Export Templates */
314 g.export_templates = function() {
316 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
317 JSAN.use('util.file');
318 var f = pick_file('save');
321 var r = G.error.yns_alert(
322 'Would you like to overwrite the existing file ' + f.leafName + '?',
323 'Templates Export Warning',
327 'Check here to confirm this message'
329 if (r != 0) { file.close(); alert('Not overwriting file.'); return; }
331 var e_file = new util.file(''); e_file._file = f;
332 e_file.write_content( 'truncate', js2JSON( g.templates ) );
334 alert('Templates exported as file ' + f.leafName);
336 alert('File not chosen for export.');
340 g.error.standard_unexpected_error_alert('Error exporting templates',E);
344 /******************************************************************************************************/
345 /* Import Templates */
347 g.import_templates = function() {
349 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
350 JSAN.use('util.file');
351 var f = pick_file('open');
352 if (f && f.exists()) {
353 var i_file = new util.file(''); i_file._file = f;
354 var temp = JSON2js( i_file.get_content() );
356 for (var i in temp) {
358 if (g.templates[i]) {
360 var r = g.error.yns_alert(
361 'Replace the existing template with the imported template?\n' + g.error.pretty_print( js2JSON( temp[i] ) ),
362 'Template ' + i + ' already exists.','Yes','No',null,'Click here'
365 if (r == 0 /* Yes */) g.templates[i] = temp[i];
369 g.templates[i] = temp[i];
375 var r = g.error.yns_alert(
376 'Save all of these imported templates permanently to this account?',
377 'Final Warning', 'Yes', 'No', null, 'Click here'
380 if (r == 0 /* Yes */) {
381 var robj = g.network.simple_request(
382 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
384 if (typeof robj.ilsevent != 'undefined') {
387 alert('All templates saved.');
391 g.retrieve_templates();
393 g.error.standard_unexpected_error_alert('Error saving templates',E);
399 util.widgets.remove_children('template_placeholder');
400 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
401 g.template_menu = util.widgets.make_menulist( list );
402 $('template_placeholder').appendChild(g.template_menu);
403 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.");
407 alert('File not chosen for import.');
410 g.error.standard_unexpected_error_alert('Error importing templates',E);
415 /******************************************************************************************************/
416 /* Restore backup copies */
418 g.reset = function() {
420 g.copies = JSON2js( g.original_copies );
421 g.summarize( g.copies );
425 /******************************************************************************************************/
426 /* Apply a value to a specific field on all the copies being edited */
428 g.apply = function(field,value) {
429 g.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
430 if (value == '<HACK:KLUDGE:NULL>') value = null;
431 if (field == 'alert_message') { value = value.replace(/^\W+$/g,''); }
432 if (field == 'price' || field == 'deposit_amount') {
433 if (value == '') { value = null; } else { JSAN.use('util.money'); value = util.money.sanitize( value ); }
435 for (var i = 0; i < g.copies.length; i++) {
436 var copy = g.copies[i];
438 copy[field]( value ); copy.ischanged('1');
445 /******************************************************************************************************/
446 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
448 g.apply_stat_cat = function(sc_id,entry_id) {
449 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
450 for (var i = 0; i < g.copies.length; i++) {
451 var copy = g.copies[i];
454 var temp = copy.stat_cat_entries();
455 if (!temp) temp = [];
456 temp = util.functional.filter_list(
459 return (obj.stat_cat() != sc_id);
462 if (entry_id > -1) temp.push(
463 util.functional.find_id_object_in_list(
464 g.data.hash.asc[sc_id].entries(),
468 copy.stat_cat_entries( temp );
471 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
476 /******************************************************************************************************/
477 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
479 g.apply_owning_lib = function(ou_id) {
480 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
482 for (var i = 0; i < g.copies.length; i++) {
483 var copy = g.copies[i];
485 if (!map_acn[copy.call_number()]) {
486 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
487 if (typeof volume.ilsevent != 'undefined') {
488 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);
491 map_acn[copy.call_number()] = volume;
493 var old_volume = map_acn[copy.call_number()];
494 var acn_id = g.network.simple_request(
495 'FM_ACN_FIND_OR_CREATE',
496 [ses(),old_volume.label(),old_volume.record(),ou_id]
498 if (typeof acn_id.ilsevent != 'undefined') {
499 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);
502 copy.call_number(acn_id);
505 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
510 /******************************************************************************************************/
511 /* This returns true if none of the copies being edited are pre-cats */
513 g.safe_to_change_owning_lib = function() {
516 for (var i = 0; i < g.copies.length; i++) {
517 var cn = g.copies[i].call_number();
518 if (typeof cn == 'object') { cn = cn.id(); }
519 if (cn == -1) { safe = false; }
523 g.error.standard_unexpected_error_alert('safe_to_change_owning_lib?',E);
528 /******************************************************************************************************/
529 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
531 g.safe_to_edit_copy_status = function() {
534 for (var i = 0; i < g.copies.length; i++) {
535 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
536 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
540 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
545 /******************************************************************************************************/
546 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
548 g.populate_alert_message_input = function(tb) {
550 var seen = {}; var s = '';
551 for (var i = 0; i < g.copies.length; i++) {
552 var msg = g.copies[i].alert_message();
554 if (typeof seen[msg] == 'undefined') {
560 tb.setAttribute('value',s);
562 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
566 /******************************************************************************************************/
567 /* This returns a list of acpl's appropriate for the copies being edited */
569 g.get_acpl_list = function() {
572 JSAN.use('util.functional');
574 function get(lib_id,only_these) {
575 g.data.stash_retrieve();
576 var label = 'acpl_list_for_lib_'+lib_id;
577 if (typeof g.data[label] == 'undefined') {
578 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
579 if (typeof robj.ilsevent != 'undefined') throw(robj);
581 for (var j = 0; j < robj.length; j++) {
582 var my_acpl = robj[j];
583 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
584 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
585 g.data.list.acpl.push( my_acpl );
587 if (only_these.indexOf( String( my_acpl.owning_lib() ) ) != -1) {
588 temp_list.push( my_acpl );
591 g.data[label] = temp_list; g.data.stash(label,'hash','list');
593 return g.data[label];
596 var libs = []; var map_acn = {};
597 for (var i = 0; i < g.copies.length; i++) {
598 var cn_id = g.copies[i].call_number();
600 if (! map_acn[ cn_id ]) {
601 map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
602 libs.push( map_acn[ cn_id ].owning_lib() );
607 for (var i in g.callnumbers) {
608 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 ); }
611 JSAN.use('util.fm_utils');
612 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
613 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
615 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
618 return get(ancestor, ancestors);
624 g.error.standard_unexpected_error_alert('get_acpl_list',E);
630 /******************************************************************************************************/
631 /* This keeps track of what fields have been edited for styling purposes */
635 /******************************************************************************************************/
636 /* These need data from the middle layer to render */
638 g.special_exception = {
639 'Owning Lib : Call Number' : function(label,value) {
640 JSAN.use('util.widgets');
641 if (value>0) { /* an existing call number */
643 api.FM_ACN_RETRIEVE.app,
644 api.FM_ACN_RETRIEVE.method,
647 var cn = '??? id = ' + value;
649 cn = req.getResultObject();
651 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
653 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
656 } else { /* a yet to be created call number */
658 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
662 'Creator' : function(label,value) {
663 if (value == null || value == '' || value == 'null') return;
664 g.network.simple_request(
665 'FM_AU_RETRIEVE_VIA_ID',
668 var p = '??? id = ' + value;
670 p = req.getResultObject();
674 g.error.sdump('D_ERROR','patron retrieve: ' + E);
676 JSAN.use('util.widgets');
677 util.widgets.set_text(label,p);
681 'Last Editor' : function(label,value) {
682 if (value == null || value == '' || value == 'null') return;
683 g.network.simple_request(
684 'FM_AU_RETRIEVE_VIA_ID',
687 var p = '??? id = ' + value;
689 p = req.getResultObject();
693 g.error.sdump('D_ERROR','patron retrieve: ' + E);
695 util.widgets.set_text(label,p);
702 /******************************************************************************************************/
703 g.readonly_stat_cat_names = [];
704 g.editable_stat_cat_names = [];
706 /******************************************************************************************************/
707 /* These get show in the left panel */
709 g.panes_and_field_names = {
716 render: 'fm.barcode();',
722 render: 'util.date.formatted_date( fm.create_date(), "%F");',
728 render: 'fm.creator();',
734 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
740 render: 'fm.editor();',
751 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
752 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);',
757 "Circulation Library",
759 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
760 //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);',
761 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);',
765 "Owning Lib : Call Number",
767 render: 'fm.call_number();',
768 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,
774 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
775 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);',
787 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
788 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);',
794 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
795 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);',
801 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
802 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);',
809 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
810 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);',
817 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
818 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);',
825 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
826 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);',
830 "Circulation Modifier",
832 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
833 /*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);',*/
834 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);',
843 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
844 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);',
851 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
852 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);',
858 render: 'if (fm.deposit_amount() == null) { "<Unset>"; } else { util.money.sanitize( fm.deposit_amount() ); }',
859 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);',
865 render: 'if (fm.price() == null) { "<Unset>"; } else { util.money.sanitize( fm.price() ); }',
866 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);',
873 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
874 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);',
880 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
881 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);',
892 /******************************************************************************************************/
893 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
895 g.summarize = function( copies ) {
896 /******************************************************************************************************/
899 JSAN.use('util.date'); JSAN.use('util.money');
902 for (var i in g.panes_and_field_names) {
903 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
905 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
906 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
908 /******************************************************************************************************/
909 /* Loop through the field names */
911 for (var i = 0; i < g.field_names.length; i++) {
913 var field_name = g.field_names[i][0];
914 var render = g.field_names[i][1].render;
915 g.summary[ field_name ] = {};
917 /******************************************************************************************************/
918 /* Loop through the copies */
920 for (var j = 0; j < copies.length; j++) {
923 var cmd = render || ('fm.' + field_name + '();');
926 /**********************************************************************************************/
927 /* Try to retrieve the value for this field for this copy */
932 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
934 if (typeof value == 'object' && value != null) {
935 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
938 /**********************************************************************************************/
939 /* Tally the count */
941 if (g.summary[ field_name ][ value ]) {
942 g.summary[ field_name ][ value ]++;
944 g.summary[ field_name ][ value ] = 1;
948 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
951 /******************************************************************************************************/
952 /* Display the summarized data and inputs for editing */
954 g.render = function() {
956 /******************************************************************************************************/
957 /* Library setup and clear any existing interface */
959 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
961 for (var i in g.panes_and_field_names) {
962 var p = document.getElementById(i);
963 if (p) util.widgets.remove_children(p);
966 /******************************************************************************************************/
967 /* Prepare the panes */
969 var groupbox; var caption; var vbox; var grid; var rows;
971 /******************************************************************************************************/
972 /* Loop through the field names */
974 for (h in g.panes_and_field_names) {
975 if (!document.getElementById(h)) continue;
976 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
978 var f = g.panes_and_field_names[h][i]; var fn = f[0];
979 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
980 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
981 caption = document.createElement('caption'); groupbox.appendChild(caption);
982 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
983 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
984 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
985 grid.setAttribute('flex','1');
986 rows = grid.lastChild;
989 /**************************************************************************************/
990 /* Loop through each value for the field */
992 for (var j in g.summary[fn]) {
993 var value = j; var count = g.summary[fn][j];
994 row = document.createElement('row'); rows.appendChild(row);
995 var label1 = document.createElement('description'); row.appendChild(label1);
996 if (g.special_exception[ fn ]) {
997 g.special_exception[ fn ]( label1, value );
999 label1.appendChild( document.createTextNode(value) );
1001 var label2 = document.createElement('description'); row.appendChild(label2);
1002 var unit = count == 1 ? 'copy' : 'copies';
1003 label2.appendChild( document.createTextNode(count + ' ' + unit) );
1005 var hbox = document.createElement('hbox');
1006 hbox.setAttribute('id',fn);
1007 groupbox.appendChild(hbox);
1008 var hbox2 = document.createElement('hbox');
1009 groupbox.appendChild(hbox2);
1011 /**************************************************************************************/
1012 /* Render the input widget */
1014 if (f[1].input && g.edit) {
1015 g.render_input(hbox,f[1]);
1019 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1025 /******************************************************************************************************/
1026 /* This actually draws the change button and input widget for a given field */
1027 g.render_input = function(node,blob) {
1029 // node = hbox ; groupbox -> hbox, hbox
1031 var groupbox = node.parentNode;
1032 var caption = groupbox.firstChild;
1033 var vbox = node.previousSibling;
1035 var hbox2 = node.nextSibling;
1037 var input_cmd = blob.input;
1038 var render_cmd = blob.render;
1040 var block = false; var first = true;
1042 function on_mouseover(ev) {
1043 groupbox.setAttribute('style','background: white');
1046 function on_mouseout(ev) {
1047 groupbox.setAttribute('style','');
1050 vbox.addEventListener('mouseover',on_mouseover,false);
1051 vbox.addEventListener('mouseout',on_mouseout,false);
1052 groupbox.addEventListener('mouseover',on_mouseover,false);
1053 groupbox.addEventListener('mouseout',on_mouseout,false);
1054 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1055 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1057 function on_click(ev){
1059 if (block) return; block = true;
1061 function post_c(v) {
1063 /* FIXME - kludgy */
1064 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1068 f = input_cmd.match(/apply\("(.+?)",/)[1];
1071 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1077 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1081 g.summarize( g.copies );
1083 document.getElementById(caption.id).focus();
1087 g.error.standard_unexpected_error_alert('post_c',E);
1090 var x; var c; eval( input_cmd );
1092 util.widgets.remove_children(vbox);
1093 util.widgets.remove_children(hbox);
1094 util.widgets.remove_children(hbox2);
1095 hbox.appendChild(x);
1096 var apply = document.createElement('button');
1097 apply.setAttribute('label','Apply');
1098 apply.setAttribute('accesskey','A');
1099 hbox2.appendChild(apply);
1100 apply.addEventListener('command',function() { c(x.value); },false);
1101 var cancel = document.createElement('button');
1102 cancel.setAttribute('label','Cancel');
1103 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1104 hbox2.appendChild(cancel);
1105 setTimeout( function() { x.focus(); }, 0 );
1108 g.error.standard_unexpected_error_alert('render_input',E);
1111 vbox.addEventListener('click',on_click, false);
1112 hbox.addEventListener('click',on_click, false);
1113 caption.addEventListener('click',on_click, false);
1114 caption.addEventListener('keypress',function(ev) {
1115 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1117 caption.setAttribute('style','-moz-user-focus: normal');
1118 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1119 caption.setAttribute('onblur','this.setAttribute("class","")');
1122 g.error.sdump('D_ERROR',E + '\n');
1126 /******************************************************************************************************/
1127 /* store the copies in the global xpcom stash */
1129 g.stash_and_close = function() {
1131 if (g.handle_update) {
1133 var r = g.network.request(
1134 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1135 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1136 [ ses(), g.copies, true ]
1138 if (typeof r.ilsevent != 'undefined') {
1139 g.error.standard_unexpected_error_alert('copy update',r);
1141 alert('Items added/modified.');
1143 /* FIXME -- revisit the return value here */
1145 alert('copy update error: ' + js2JSON(E));
1148 //g.data.temp_copies = js2JSON( g.copies );
1149 //g.data.stash('temp_copies');
1150 xulG.copies = g.copies;
1151 update_modal_xulG(xulG);
1154 g.error.standard_unexpected_error_alert('stash and close',E);
1158 /******************************************************************************************************/
1159 /* spawn copy notes interface */
1161 g.copy_notes = function() {
1162 JSAN.use('util.window'); var win = new util.window();
1164 urls.XUL_COPY_NOTES,
1165 //+ '?copy_id=' + window.escape(g.copies[0].id()),
1166 'Copy Notes','chrome,resizable,modal',
1167 { 'copy_id' : g.copies[0].id() }