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);
511 /******************************************************************************************************/
512 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
514 g.safe_to_edit_copy_status = function() {
517 for (var i = 0; i < g.copies.length; i++) {
518 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
519 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
523 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
528 /******************************************************************************************************/
529 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
531 g.populate_alert_message_input = function(tb) {
533 var seen = {}; var s = '';
534 for (var i = 0; i < g.copies.length; i++) {
535 var msg = g.copies[i].alert_message();
537 if (typeof seen[msg] == 'undefined') {
543 tb.setAttribute('value',s);
545 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
549 /******************************************************************************************************/
550 /* This returns a list of acpl's appropriate for the copies being edited */
552 g.get_acpl_list = function() {
555 JSAN.use('util.functional');
557 function get(lib_id,only_these) {
558 g.data.stash_retrieve();
559 var label = 'acpl_list_for_lib_'+lib_id;
560 if (typeof g.data[label] == 'undefined') {
561 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
562 if (typeof robj.ilsevent != 'undefined') throw(robj);
564 for (var j = 0; j < robj.length; j++) {
565 var my_acpl = robj[j];
566 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
567 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
568 g.data.list.acpl.push( my_acpl );
570 if (only_these.indexOf( String( my_acpl.owning_lib() ) ) != -1) {
571 temp_list.push( my_acpl );
574 g.data[label] = temp_list; g.data.stash(label,'hash','list');
576 return g.data[label];
579 var libs = []; var map_acn = {};
580 for (var i = 0; i < g.copies.length; i++) {
581 var cn_id = g.copies[i].call_number();
583 if (! map_acn[ cn_id ]) {
584 map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
585 libs.push( map_acn[ cn_id ].owning_lib() );
590 for (var i in g.callnumbers) {
591 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 ); }
594 JSAN.use('util.fm_utils');
595 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
596 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
598 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
601 return get(ancestor, ancestors);
607 g.error.standard_unexpected_error_alert('get_acpl_list',E);
613 /******************************************************************************************************/
614 /* This keeps track of what fields have been edited for styling purposes */
618 /******************************************************************************************************/
619 /* These need data from the middle layer to render */
621 g.special_exception = {
622 'Owning Lib : Call Number' : function(label,value) {
623 JSAN.use('util.widgets');
624 if (value>0) { /* an existing call number */
626 api.FM_ACN_RETRIEVE.app,
627 api.FM_ACN_RETRIEVE.method,
630 var cn = '??? id = ' + value;
632 cn = req.getResultObject();
634 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
636 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
639 } else { /* a yet to be created call number */
641 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
645 'Creator' : function(label,value) {
646 if (value == null || value == '' || value == 'null') return;
647 g.network.simple_request(
648 'FM_AU_RETRIEVE_VIA_ID',
651 var p = '??? id = ' + value;
653 p = req.getResultObject();
657 g.error.sdump('D_ERROR','patron retrieve: ' + E);
659 JSAN.use('util.widgets');
660 util.widgets.set_text(label,p);
664 'Last Editor' : function(label,value) {
665 if (value == null || value == '' || value == 'null') return;
666 g.network.simple_request(
667 'FM_AU_RETRIEVE_VIA_ID',
670 var p = '??? id = ' + value;
672 p = req.getResultObject();
676 g.error.sdump('D_ERROR','patron retrieve: ' + E);
678 util.widgets.set_text(label,p);
685 /******************************************************************************************************/
686 g.readonly_stat_cat_names = [];
687 g.editable_stat_cat_names = [];
689 /******************************************************************************************************/
690 /* These get show in the left panel */
692 g.panes_and_field_names = {
699 render: 'fm.barcode();',
705 render: 'util.date.formatted_date( fm.create_date(), "%F");',
711 render: 'fm.creator();',
717 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
723 render: 'fm.editor();',
734 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
735 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);',
740 "Circulation Library",
742 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
743 //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);',
744 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);',
748 "Owning Lib : Call Number",
750 render: 'fm.call_number();',
751 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);',
757 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
758 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);',
770 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
771 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);',
777 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
778 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);',
784 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
785 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);',
792 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
793 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);',
800 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
801 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);',
808 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
809 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);',
813 "Circulation Modifier",
815 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
816 /*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);',*/
817 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);',
826 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
827 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);',
834 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
835 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);',
841 render: 'if (fm.deposit_amount() == null) { "<Unset>"; } else { util.money.sanitize( fm.deposit_amount() ); }',
842 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);',
848 render: 'if (fm.price() == null) { "<Unset>"; } else { util.money.sanitize( fm.price() ); }',
849 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);',
856 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
857 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);',
863 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
864 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);',
875 /******************************************************************************************************/
876 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
878 g.summarize = function( copies ) {
879 /******************************************************************************************************/
882 JSAN.use('util.date'); JSAN.use('util.money');
885 for (var i in g.panes_and_field_names) {
886 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
888 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
889 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
891 /******************************************************************************************************/
892 /* Loop through the field names */
894 for (var i = 0; i < g.field_names.length; i++) {
896 var field_name = g.field_names[i][0];
897 var render = g.field_names[i][1].render;
898 g.summary[ field_name ] = {};
900 /******************************************************************************************************/
901 /* Loop through the copies */
903 for (var j = 0; j < copies.length; j++) {
906 var cmd = render || ('fm.' + field_name + '();');
909 /**********************************************************************************************/
910 /* Try to retrieve the value for this field for this copy */
915 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
917 if (typeof value == 'object' && value != null) {
918 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
921 /**********************************************************************************************/
922 /* Tally the count */
924 if (g.summary[ field_name ][ value ]) {
925 g.summary[ field_name ][ value ]++;
927 g.summary[ field_name ][ value ] = 1;
931 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
934 /******************************************************************************************************/
935 /* Display the summarized data and inputs for editing */
937 g.render = function() {
939 /******************************************************************************************************/
940 /* Library setup and clear any existing interface */
942 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
944 for (var i in g.panes_and_field_names) {
945 var p = document.getElementById(i);
946 if (p) util.widgets.remove_children(p);
949 /******************************************************************************************************/
950 /* Prepare the panes */
952 var groupbox; var caption; var vbox; var grid; var rows;
954 /******************************************************************************************************/
955 /* Loop through the field names */
957 for (h in g.panes_and_field_names) {
958 if (!document.getElementById(h)) continue;
959 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
961 var f = g.panes_and_field_names[h][i]; var fn = f[0];
962 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
963 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
964 caption = document.createElement('caption'); groupbox.appendChild(caption);
965 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
966 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
967 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
968 grid.setAttribute('flex','1');
969 rows = grid.lastChild;
972 /**************************************************************************************/
973 /* Loop through each value for the field */
975 for (var j in g.summary[fn]) {
976 var value = j; var count = g.summary[fn][j];
977 row = document.createElement('row'); rows.appendChild(row);
978 var label1 = document.createElement('description'); row.appendChild(label1);
979 if (g.special_exception[ fn ]) {
980 g.special_exception[ fn ]( label1, value );
982 label1.appendChild( document.createTextNode(value) );
984 var label2 = document.createElement('description'); row.appendChild(label2);
985 var unit = count == 1 ? 'copy' : 'copies';
986 label2.appendChild( document.createTextNode(count + ' ' + unit) );
988 var hbox = document.createElement('hbox');
989 hbox.setAttribute('id',fn);
990 groupbox.appendChild(hbox);
991 var hbox2 = document.createElement('hbox');
992 groupbox.appendChild(hbox2);
994 /**************************************************************************************/
995 /* Render the input widget */
997 if (f[1].input && g.edit) {
998 g.render_input(hbox,f[1]);
1002 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1008 /******************************************************************************************************/
1009 /* This actually draws the change button and input widget for a given field */
1010 g.render_input = function(node,blob) {
1012 // node = hbox ; groupbox -> hbox, hbox
1014 var groupbox = node.parentNode;
1015 var caption = groupbox.firstChild;
1016 var vbox = node.previousSibling;
1018 var hbox2 = node.nextSibling;
1020 var input_cmd = blob.input;
1021 var render_cmd = blob.render;
1023 var block = false; var first = true;
1025 function on_mouseover(ev) {
1026 groupbox.setAttribute('style','background: white');
1029 function on_mouseout(ev) {
1030 groupbox.setAttribute('style','');
1033 vbox.addEventListener('mouseover',on_mouseover,false);
1034 vbox.addEventListener('mouseout',on_mouseout,false);
1035 groupbox.addEventListener('mouseover',on_mouseover,false);
1036 groupbox.addEventListener('mouseout',on_mouseout,false);
1037 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1038 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1040 function on_click(ev){
1042 if (block) return; block = true;
1044 function post_c(v) {
1046 /* FIXME - kludgy */
1047 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1051 f = input_cmd.match(/apply\("(.+?)",/)[1];
1054 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1060 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1064 g.summarize( g.copies );
1066 document.getElementById(caption.id).focus();
1070 g.error.standard_unexpected_error_alert('post_c',E);
1073 var x; var c; eval( input_cmd );
1075 util.widgets.remove_children(vbox);
1076 util.widgets.remove_children(hbox);
1077 util.widgets.remove_children(hbox2);
1078 hbox.appendChild(x);
1079 var apply = document.createElement('button');
1080 apply.setAttribute('label','Apply');
1081 apply.setAttribute('accesskey','A');
1082 hbox2.appendChild(apply);
1083 apply.addEventListener('command',function() { c(x.value); },false);
1084 var cancel = document.createElement('button');
1085 cancel.setAttribute('label','Cancel');
1086 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1087 hbox2.appendChild(cancel);
1088 setTimeout( function() { x.focus(); }, 0 );
1091 g.error.standard_unexpected_error_alert('render_input',E);
1094 vbox.addEventListener('click',on_click, false);
1095 hbox.addEventListener('click',on_click, false);
1096 caption.addEventListener('click',on_click, false);
1097 caption.addEventListener('keypress',function(ev) {
1098 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1100 caption.setAttribute('style','-moz-user-focus: normal');
1101 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1102 caption.setAttribute('onblur','this.setAttribute("class","")');
1105 g.error.sdump('D_ERROR',E + '\n');
1109 /******************************************************************************************************/
1110 /* store the copies in the global xpcom stash */
1112 g.stash_and_close = function() {
1114 if (g.handle_update) {
1116 var r = g.network.request(
1117 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1118 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1119 [ ses(), g.copies, true ]
1121 if (typeof r.ilsevent != 'undefined') {
1122 g.error.standard_unexpected_error_alert('copy update',r);
1124 alert('Items added/modified.');
1126 /* FIXME -- revisit the return value here */
1128 alert('copy update error: ' + js2JSON(E));
1131 //g.data.temp_copies = js2JSON( g.copies );
1132 //g.data.stash('temp_copies');
1133 xulG.copies = g.copies;
1134 update_modal_xulG(xulG);
1137 g.error.standard_unexpected_error_alert('stash and close',E);
1141 /******************************************************************************************************/
1142 /* spawn copy notes interface */
1144 g.copy_notes = function() {
1145 JSAN.use('util.window'); var win = new util.window();
1147 urls.XUL_COPY_NOTES,
1148 //+ '?copy_id=' + window.escape(g.copies[0].id()),
1149 'Copy Notes','chrome,resizable,modal',
1150 { 'copy_id' : g.copies[0].id() }