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.populate_stat_cats();
104 /******************************************************************************************************/
105 /* Backup copies :) */
107 g.original_copies = js2JSON( g.copies );
109 /******************************************************************************************************/
112 g.summarize( g.copies );
116 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
117 "system administrator or software developer the following:\ncat/copy_editor.xul\n" + E + '\n';
118 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
123 /******************************************************************************************************/
124 /* File picker for template export/import */
126 function pick_file(mode) {
127 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
128 var nsIFilePicker = Components.interfaces.nsIFilePicker;
129 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance( nsIFilePicker );
132 mode == 'open' ? "Import Templates File" : "Save Templates File As",
133 mode == 'open' ? nsIFilePicker.modeOpen : nsIFilePicker.modeSave
135 fp.appendFilters( nsIFilePicker.filterAll );
136 var fp_result = fp.show();
137 if ( ( fp_result == nsIFilePicker.returnOK || fp_result == nsIFilePicker.returnReplace ) && fp.file ) {
144 /******************************************************************************************************/
145 /* Retrieve Templates */
147 g.retrieve_templates = function() {
149 JSAN.use('util.widgets'); JSAN.use('util.functional');
151 var robj = g.network.simple_request('FM_AUS_RETRIEVE',[ses(),g.data.list.au[0].id()]);
152 if (typeof robj['staff_client.copy_editor.templates'] != 'undefined') {
153 g.templates = robj['staff_client.copy_editor.templates'];
155 util.widgets.remove_children('template_placeholder');
156 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
158 g.template_menu = util.widgets.make_menulist( list );
159 $('template_placeholder').appendChild(g.template_menu);
161 g.error.standard_unexpected_error_alert('Error retrieving templates',E);
165 /******************************************************************************************************/
168 g.apply_template = function() {
170 var name = g.template_menu.value;
171 if (g.templates[ name ] != 'undefined') {
172 var template = g.templates[ name ];
173 for (var i in template) {
174 g.changed[ i ] = template[ i ];
175 switch( template[i].type ) {
177 g.apply(template[i].field,template[i].value);
180 if (g.stat_cat_seen[ template[i].field ]) g.apply_stat_cat(template[i].field,template[i].value);
183 g.apply_owning_lib(template[i].value);
187 g.summarize( g.copies );
191 g.error.standard_unexpected_error_alert('Error applying template',E);
195 /******************************************************************************************************/
196 /* Save as Template */
198 g.save_template = function() {
200 var name = window.prompt('Enter template name:','','Save As Template');
202 g.templates[name] = g.changed;
203 var robj = g.network.simple_request(
204 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
206 if (typeof robj.ilsevent != 'undefined') {
209 alert('Template "' + name + '" saved.');
213 g.retrieve_templates();
215 g.error.standard_unexpected_error_alert('Error saving template',E);
221 g.error.standard_unexpected_error_alert('Error saving template',E);
225 /******************************************************************************************************/
226 /* Delete Template */
228 g.delete_template = function() {
230 var name = g.template_menu.value;
232 if (! window.confirm('Delete template "' + name + '"?') ) return;
233 delete(g.templates[name]);
234 var robj = g.network.simple_request(
235 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
237 if (typeof robj.ilsevent != 'undefined') {
240 alert('Template "' + name + '" deleted.');
244 g.retrieve_templates();
246 g.error.standard_unexpected_error_alert('Error deleting template',E);
252 g.error.standard_unexpected_error_alert('Error deleting template',E);
256 /******************************************************************************************************/
257 /* Export Templates */
259 g.export_templates = function() {
261 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
262 JSAN.use('util.file');
263 var f = pick_file('save');
266 var r = G.error.yns_alert(
267 'Would you like to overwrite the existing file ' + f.leafName + '?',
268 'Templates Export Warning',
272 'Check here to confirm this message'
274 if (r != 0) { file.close(); alert('Not overwriting file.'); return; }
276 var e_file = new util.file(''); e_file._file = f;
277 e_file.write_content( 'truncate', js2JSON( g.templates ) );
279 alert('Templates exported as file ' + f.leafName);
281 alert('File not chosen for export.');
285 g.error.standard_unexpected_error_alert('Error exporting templates',E);
289 /******************************************************************************************************/
290 /* Import Templates */
292 g.import_templates = function() {
294 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
295 JSAN.use('util.file');
296 var f = pick_file('open');
297 if (f && f.exists()) {
298 var i_file = new util.file(''); i_file._file = f;
299 var temp = JSON2js( i_file.get_content() );
301 for (var i in temp) {
303 if (g.templates[i]) {
305 var r = g.error.yns_alert(
306 'Replace the existing template with the imported template?\n' + g.error.pretty_print( js2JSON( temp[i] ) ),
307 'Template ' + i + ' already exists.','Yes','No',null,'Click here'
310 if (r == 0 /* Yes */) g.templates[i] = temp[i];
314 g.templates[i] = temp[i];
320 var r = g.error.yns_alert(
321 'Save all of these imported templates permanently to this account?',
322 'Final Warning', 'Yes', 'No', null, 'Click here'
325 if (r == 0 /* Yes */) {
326 var robj = g.network.simple_request(
327 'FM_AUS_UPDATE',[ses(),g.data.list.au[0].id(), { 'staff_client.copy_editor.templates' : g.templates }]
329 if (typeof robj.ilsevent != 'undefined') {
332 alert('All templates saved.');
336 g.retrieve_templates();
338 g.error.standard_unexpected_error_alert('Error saving templates',E);
344 util.widgets.remove_children('template_placeholder');
345 var list = util.functional.map_object_to_list( g.templates, function(obj,i) { return [i, i]; } );
346 g.template_menu = util.widgets.make_menulist( list );
347 $('template_placeholder').appendChild(g.template_menu);
348 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.");
352 alert('File not chosen for import.');
355 g.error.standard_unexpected_error_alert('Error importing templates',E);
360 /******************************************************************************************************/
361 /* Restore backup copies */
363 g.reset = function() {
365 g.copies = JSON2js( g.original_copies );
366 g.summarize( g.copies );
370 /******************************************************************************************************/
371 /* Apply a value to a specific field on all the copies being edited */
373 g.apply = function(field,value) {
374 g.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
375 if (value == '<HACK:KLUDGE:NULL>') value = null;
376 if (field == 'alert_message') { value = value.replace(/^\W+$/g,''); }
377 if (field == 'price' || field == 'deposit_amount') {
378 if (value == '') { value = null; } else { JSAN.use('util.money'); value = util.money.sanitize( value ); }
380 for (var i = 0; i < g.copies.length; i++) {
381 var copy = g.copies[i];
383 copy[field]( value ); copy.ischanged('1');
390 /******************************************************************************************************/
391 /* Apply a stat cat entry to all the copies being edited. An entry_id of < 0 signifies the stat cat is being removed. */
393 g.apply_stat_cat = function(sc_id,entry_id) {
394 g.error.sdump('D_TRACE','sc_id = ' + sc_id + ' entry_id = ' + entry_id + '\n');
395 for (var i = 0; i < g.copies.length; i++) {
396 var copy = g.copies[i];
399 var temp = copy.stat_cat_entries();
400 if (!temp) temp = [];
401 temp = util.functional.filter_list(
404 return (obj.stat_cat() != sc_id);
407 if (entry_id > -1) temp.push(
408 util.functional.find_id_object_in_list(
409 g.data.hash.asc[sc_id].entries(),
413 copy.stat_cat_entries( temp );
416 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
421 /******************************************************************************************************/
422 /* Apply an "owning lib" to all the copies being edited. That is, change and auto-vivicating volumes */
425 g.apply_owning_lib = function(ou_id) {
426 g.error.sdump('D_TRACE','ou_id = ' + ou_id + '\n');
427 for (var i = 0; i < g.copies.length; i++) {
428 var copy = g.copies[i];
430 if (!g.map_acn[copy.call_number()]) {
431 var volume = g.network.simple_request('FM_ACN_RETRIEVE',[ copy.call_number() ]);
432 if (typeof volume.ilsevent != 'undefined') {
433 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);
436 g.map_acn[copy.call_number()] = volume;
438 var old_volume = g.map_acn[copy.call_number()];
439 var acn_id = g.network.simple_request(
440 'FM_ACN_FIND_OR_CREATE',
441 [ses(),old_volume.label(),old_volume.record(),ou_id]
443 if (typeof acn_id.ilsevent != 'undefined') {
444 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);
447 copy.call_number(acn_id);
450 g.error.standard_unexpected_error_alert('apply_stat_cat',E);
455 /******************************************************************************************************/
456 /* This returns true if none of the copies being edited are pre-cats */
458 g.safe_to_change_owning_lib = function() {
461 for (var i = 0; i < g.copies.length; i++) {
462 var cn = g.copies[i].call_number();
463 if (typeof cn == 'object') { cn = cn.id(); }
464 if (cn == -1) { safe = false; }
468 g.error.standard_unexpected_error_alert('safe_to_change_owning_lib?',E);
473 /******************************************************************************************************/
474 /* This returns true if none of the copies being edited have a magical status found in my_constants.magical_statuses */
476 g.safe_to_edit_copy_status = function() {
479 for (var i = 0; i < g.copies.length; i++) {
480 var status = g.copies[i].status(); if (typeof status == 'object') status = status.id();
481 if (typeof my_constants.magical_statuses[ status ] != 'undefined') safe = false;
485 g.error.standard_unexpected_error_alert('safe_to_edit_copy_status?',E);
490 /******************************************************************************************************/
491 /* This concats and uniques all the alert messages for use as the default value for a new alert message */
493 g.populate_alert_message_input = function(tb) {
495 var seen = {}; var s = '';
496 for (var i = 0; i < g.copies.length; i++) {
497 var msg = g.copies[i].alert_message();
499 if (typeof seen[msg] == 'undefined') {
505 tb.setAttribute('value',s);
507 g.error.standard_unexpected_error_alert('populate_alert_message_input',E);
511 /******************************************************************************************************/
512 /* This returns a list of acpl's appropriate for the copies being edited */
514 g.get_acpl_list = function() {
517 JSAN.use('util.functional');
519 function get(lib_id,only_these) {
520 g.data.stash_retrieve();
521 var label = 'acpl_list_for_lib_'+lib_id;
522 if (typeof g.data[label] == 'undefined') {
523 var robj = g.network.simple_request('FM_ACPL_RETRIEVE', [ lib_id ]);
524 if (typeof robj.ilsevent != 'undefined') throw(robj);
526 for (var j = 0; j < robj.length; j++) {
527 var my_acpl = robj[j];
528 if (typeof g.data.hash.acpl[ my_acpl.id() ] == 'undefined') {
529 g.data.hash.acpl[ my_acpl.id() ] = my_acpl;
530 g.data.list.acpl.push( my_acpl );
532 var only_this_lib = my_acpl.owning_lib(); if (typeof only_this_lib == 'object') only_this_lib = only_this_lib.id();
533 if (only_these.indexOf( String( only_this_lib ) ) != -1) {
534 temp_list.push( my_acpl );
537 g.data[label] = temp_list; g.data.stash(label,'hash','list');
539 return g.data[label];
542 var temp_acpl_list = [];
544 /* find acpl's based on owning_lib */
547 for (var i = 0; i < g.copies.length; i++) {
548 var cn_id = g.copies[i].call_number();
550 if (! g.map_acn[ cn_id ]) {
551 g.map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
553 var consider_lib = g.map_acn[ cn_id ].owning_lib();
554 if ( libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { libs.push( consider_lib ); }
558 for (var i in g.callnumbers) {
559 var consider_lib = g.callnumbers[i].owning_lib;
560 if (typeof consider_lib == 'object') consider_lib = consider_lib.id();
561 if ( libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { libs.push( consider_lib ); }
564 JSAN.use('util.fm_utils');
565 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
566 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
569 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
570 var acpl_list = get(ancestor, ancestors);
571 if (acpl_list) for (var i = 0; i < acpl_list.length; i++) {
572 if (acpl_list[i] != null) {
573 temp_acpl_list.push(acpl_list[i]);
578 /* find acpl's based on circ_lib */
582 for (var i = 0; i < g.copies.length; i++) {
583 var consider_lib = g.copies[i].circ_lib();
584 if (typeof consider_lib == 'object') consider_lib = consider_lib.id();
585 if ( circ_libs.indexOf( String( consider_lib ) ) > -1 ) { /* already in list */ } else { circ_libs.push( consider_lib ); }
588 if (circ_libs.length > 0) {
589 var circ_ancestor = util.fm_utils.find_common_aou_ancestor( circ_libs );
590 if (typeof circ_ancestor == 'object' && circ_ancestor != null) circ_ancestor = circ_ancestor.id();
593 var circ_ancestors = util.fm_utils.find_common_aou_ancestors( circ_libs );
594 var circ_acpl_list = get(circ_ancestor, circ_ancestors);
595 var flat_acpl_list = util.functional.map_list( temp_acpl_list, function(o){return o.id();} );
596 for (var i = 0; i < circ_acpl_list.length; i++) {
597 var consider_acpl = circ_acpl_list[i].id();
598 if ( flat_acpl_list.indexOf( String( consider_acpl ) ) > -1 ) {
599 /* already in list */
601 if (circ_acpl_list[i] != null) temp_acpl_list.push( circ_acpl_list[i] );
607 return temp_acpl_list;
610 g.error.standard_unexpected_error_alert('get_acpl_list',E);
616 /******************************************************************************************************/
617 /* This keeps track of what fields have been edited for styling purposes */
621 /******************************************************************************************************/
622 /* These need data from the middle layer to render */
624 g.special_exception = {
625 'Owning Lib : Call Number' : function(label,value) {
626 JSAN.use('util.widgets');
627 if (value>0) { /* an existing call number */
629 api.FM_ACN_RETRIEVE.app,
630 api.FM_ACN_RETRIEVE.method,
633 var cn = '??? id = ' + value;
635 cn = req.getResultObject();
637 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
639 util.widgets.set_text(label,g.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
642 } else { /* a yet to be created call number */
644 util.widgets.set_text(label,g.data.hash.aou[ g.callnumbers[value].owning_lib ].shortname() + ' : ' + g.callnumbers[value].label);
648 'Creator' : function(label,value) {
649 if (value == null || value == '' || value == 'null') return;
650 g.network.simple_request(
651 'FM_AU_RETRIEVE_VIA_ID',
654 var p = '??? id = ' + value;
656 p = req.getResultObject();
660 g.error.sdump('D_ERROR','patron retrieve: ' + E);
662 JSAN.use('util.widgets');
663 util.widgets.set_text(label,p);
667 'Last Editor' : function(label,value) {
668 if (value == null || value == '' || value == 'null') return;
669 g.network.simple_request(
670 'FM_AU_RETRIEVE_VIA_ID',
673 var p = '??? id = ' + value;
675 p = req.getResultObject();
679 g.error.sdump('D_ERROR','patron retrieve: ' + E);
681 util.widgets.set_text(label,p);
688 /******************************************************************************************************/
689 g.readonly_stat_cat_names = [];
690 g.editable_stat_cat_names = [];
692 /******************************************************************************************************/
693 /* These get show in the left panel */
695 function init_panes() {
696 g.panes_and_field_names = {
703 render: 'fm.barcode();',
709 render: 'util.date.formatted_date( fm.create_date(), "%F");',
715 render: 'fm.creator();',
721 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
727 render: 'fm.editor();',
738 render: 'typeof fm.location() == "object" ? fm.location().name() : g.data.lookup("acpl",fm.location()).name()',
739 input: 'c = function(v){ g.apply("location",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.get_acpl_list(), function(obj) { return [ g.data.hash.aou[ obj.owning_lib() ].shortname() + " : " + obj.name(), obj.id() ]; }).sort()); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
744 "Circulation Library",
746 render: 'typeof fm.circ_lib() == "object" ? fm.circ_lib().shortname() : g.data.hash.aou[ fm.circ_lib() ].shortname()',
747 //input: 'c = function(v){ g.apply("circ_lib",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( util.functional.filter_list(g.data.list.my_aou, function(obj) { return g.data.hash.aout[ obj.ou_type() ].can_have_vols(); }), function(obj) { return [ obj.shortname(), obj.id() ]; }).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
748 input: 'c = function(v){ g.apply("circ_lib",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.aou, function(obj) { var sname = obj.shortname(); for (i = sname.length; i < 20; i++) sname += " "; return [ obj.name() ? sname + " " + obj.name() : obj.shortname(), obj.id(), ( ! get_bool( g.data.hash.aout[ obj.ou_type() ].can_have_vols() ) ), ( g.data.hash.aout[ obj.ou_type() ].depth() * 2), ]; }), g.data.list.au[0].ws_ou()); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
752 "Owning Lib : Call Number",
754 render: 'fm.call_number();',
755 input: 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,
761 render: 'fm.copy_number() == null ? "<Unset>" : fm.copy_number()',
762 input: 'c = function(v){ g.apply("copy_number",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
774 render: 'fm.circulate() == null ? "<Unset>" : ( get_bool( fm.circulate() ) ? "Yes" : "No" )',
775 input: 'c = function(v){ g.apply("circulate",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
781 render: 'fm.holdable() == null ? "<Unset>" : ( get_bool( fm.holdable() ) ? "Yes" : "No" )',
782 input: 'c = function(v){ g.apply("holdable",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
788 render: 'fm.age_protect() == null ? "<Unset>" : ( typeof fm.age_protect() == "object" ? fm.age_protect().name() : g.data.hash.crahp[ fm.age_protect() ].name() )',
789 input: 'c = function(v){ g.apply("age_protect",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "<Remove Protection>", "<HACK:KLUDGE:NULL>" ] ].concat( util.functional.map_list( g.data.list.crahp, function(obj) { return [ obj.name(), obj.id() ]; }).sort() ) ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
796 render: 'switch(fm.loan_duration()){ case 1: case "1": "Short"; break; case 2: case "2": "Normal"; break; case 3:case "3": "Long"; break; }',
797 input: 'c = function(v){ g.apply("loan_duration",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Short", "1" ], [ "Normal", "2" ], [ "Long", "3" ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
804 render: 'switch(fm.fine_level()){ case 1: case "1": "Low"; break; case 2: case "2": "Normal"; break; case 3: case "3": "High"; break; }',
805 input: 'c = function(v){ g.apply("fine_level",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Low", "1" ], [ "Normal", "2" ], [ "High", "3" ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
812 render: 'fm.circ_as_type() == null ? "<Unset>" : g.data.hash.citm[ fm.circ_as_type() ].value()',
813 input: 'c = function(v){ g.apply("circ_as_type",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.citm, function(n){return [ n.code() + " - " + n.value(), n.code()];} ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
817 "Circulation Modifier",
819 render: 'fm.circ_modifier() == null ? "<Unset>" : fm.circ_modifier()',
820 /*input: 'c = function(v){ g.apply("circ_modifier",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',*/
821 input: 'c = function(v){ g.apply("circ_modifier",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( g.data.list.circ_modifier, function(obj) { return [ obj, obj ]; } ).sort() ); x.setAttribute("editable","true"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
830 render: 'fm.alert_message() == null ? "<Unset>" : fm.alert_message()',
831 input: 'c = function(v){ g.apply("alert_message",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("multiline",true); g.populate_alert_message_input(x); x.addEventListener("apply",function(f){ return function(ev) { f( ev.target.value ); } }(c), false);',
838 render: 'fm.deposit() == null ? "<Unset>" : ( get_bool( fm.deposit() ) ? "Yes" : "No" )',
839 input: 'c = function(v){ g.apply("deposit",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
845 render: 'if (fm.deposit_amount() == null) { "<Unset>"; } else { util.money.sanitize( fm.deposit_amount() ); }',
846 input: 'c = function(v){ g.apply("deposit_amount",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
852 render: 'if (fm.price() == null) { "<Unset>"; } else { util.money.sanitize( fm.price() ); }',
853 input: 'c = function(v){ g.apply("price",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
860 render: 'fm.opac_visible() == null ? "<Unset>" : ( get_bool( fm.opac_visible() ) ? "Yes" : "No" )',
861 input: 'c = function(v){ g.apply("opac_visible",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
867 render: 'fm.ref() == null ? "<Unset>" : ( get_bool( fm.ref() ) ? "Yes" : "No" )',
868 input: 'c = function(v){ g.apply("ref",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ "Yes", get_db_true() ], [ "No", get_db_false() ] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
880 /******************************************************************************************************/
881 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
883 g.summarize = function( copies ) {
884 /******************************************************************************************************/
887 JSAN.use('util.date'); JSAN.use('util.money');
890 for (var i in g.panes_and_field_names) {
891 g.field_names = g.field_names.concat( g.panes_and_field_names[i] );
893 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
894 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
896 /******************************************************************************************************/
897 /* Loop through the field names */
899 for (var i = 0; i < g.field_names.length; i++) {
901 var field_name = g.field_names[i][0];
902 var render = g.field_names[i][1].render;
903 var attr = g.field_names[i][1].attr;
904 g.summary[ field_name ] = {};
906 /******************************************************************************************************/
907 /* Loop through the copies */
909 for (var j = 0; j < copies.length; j++) {
912 var cmd = render || ('fm.' + field_name + '();');
915 /**********************************************************************************************/
916 /* Try to retrieve the value for this field for this copy */
921 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
923 if (typeof value == 'object' && value != null) {
924 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
927 /**********************************************************************************************/
928 /* Tally the count */
930 if (g.summary[ field_name ][ value ]) {
931 g.summary[ field_name ][ value ]++;
933 g.summary[ field_name ][ value ] = 1;
937 g.error.sdump('D_TRACE','summary = ' + js2JSON(g.summary) + '\n');
940 /******************************************************************************************************/
941 /* Display the summarized data and inputs for editing */
943 g.render = function() {
945 /******************************************************************************************************/
946 /* Library setup and clear any existing interface */
948 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
950 for (var i in g.panes_and_field_names) {
951 var p = document.getElementById(i);
952 if (p) util.widgets.remove_children(p);
955 /******************************************************************************************************/
956 /* Populate the library filter menu for stat cats */
959 for (var i = 0; i < g.panes_and_field_names.right_pane4.length; i++) {
960 sc_libs[ g.panes_and_field_names.right_pane4[i][1].attr.sc_lib ] = true;
963 for (var i in sc_libs) { sc_libs2.push( [ g.data.hash.aou[ i ].shortname(), i ] ); }
965 var x = document.getElementById("stat_cat_lib_filter_menu").firstChild;
966 JSAN.use('util.widgets'); util.widgets.remove_children(x);
967 for (var i = 0; i < sc_libs2.length; i++) {
968 var menuitem = document.createElement('menuitem');
969 menuitem.setAttribute('id','filter_'+sc_libs2[i][1]);
970 menuitem.setAttribute('type','checkbox');
971 menuitem.setAttribute('checked','true');
972 menuitem.setAttribute('label',sc_libs2[i][0]);
973 menuitem.setAttribute('value',sc_libs2[i][1]);
974 menuitem.setAttribute('oncommand','try{g.toggle_stat_cat_display(this);}catch(E){alert(E);}');
975 x.appendChild(menuitem);
978 /******************************************************************************************************/
979 /* Prepare the panes */
981 var groupbox; var caption; var vbox; var grid; var rows;
983 /******************************************************************************************************/
984 /* Loop through the field names */
986 for (h in g.panes_and_field_names) {
987 if (!document.getElementById(h)) continue;
988 for (var i = 0; i < g.panes_and_field_names[h].length; i++) {
990 var f = g.panes_and_field_names[h][i]; var fn = f[0]; var attr = f[1].attr;
991 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
993 for (var a in attr) {
994 groupbox.setAttribute(a,attr[a]);
997 if (typeof g.changed[fn] != 'undefined') groupbox.setAttribute('class','copy_editor_field_changed');
998 caption = document.createElement('caption'); groupbox.appendChild(caption);
999 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
1000 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
1001 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
1002 grid.setAttribute('flex','1');
1003 rows = grid.lastChild;
1006 /**************************************************************************************/
1007 /* Loop through each value for the field */
1009 for (var j in g.summary[fn]) {
1010 var value = j; var count = g.summary[fn][j];
1011 row = document.createElement('row'); rows.appendChild(row);
1012 var label1 = document.createElement('description'); row.appendChild(label1);
1013 if (g.special_exception[ fn ]) {
1014 g.special_exception[ fn ]( label1, value );
1016 label1.appendChild( document.createTextNode(value) );
1018 var label2 = document.createElement('description'); row.appendChild(label2);
1019 var unit = count == 1 ? 'copy' : 'copies';
1020 label2.appendChild( document.createTextNode(count + ' ' + unit) );
1022 var hbox = document.createElement('hbox');
1023 hbox.setAttribute('id',fn);
1024 groupbox.appendChild(hbox);
1025 var hbox2 = document.createElement('hbox');
1026 groupbox.appendChild(hbox2);
1028 /**************************************************************************************/
1029 /* Render the input widget */
1031 if (f[1].input && g.edit) {
1032 g.render_input(hbox,f[1]);
1036 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
1042 /******************************************************************************************************/
1043 /* Synchronize stat cat visiblity with library filter menu */
1044 JSAN.use('util.file');
1045 var file = new util.file('copy_editor_prefs.'+g.data.server_unadorned);
1046 g.copy_editor_prefs = util.widgets.load_attributes(file);
1047 for (var i in g.copy_editor_prefs) {
1048 if (i.match(/filter_/) && g.copy_editor_prefs[i].checked == '') {
1050 g.toggle_stat_cat_display( document.getElementById(i) );
1051 } catch(E) { alert(E); }
1058 /******************************************************************************************************/
1059 /* This actually draws the change button and input widget for a given field */
1060 g.render_input = function(node,blob) {
1062 // node = hbox ; groupbox -> hbox, hbox
1064 var groupbox = node.parentNode;
1065 var caption = groupbox.firstChild;
1066 var vbox = node.previousSibling;
1068 var hbox2 = node.nextSibling;
1070 var input_cmd = blob.input;
1071 var render_cmd = blob.render;
1072 var attr = blob.attr;
1074 var block = false; var first = true;
1076 function on_mouseover(ev) {
1077 groupbox.setAttribute('style','background: white');
1080 function on_mouseout(ev) {
1081 groupbox.setAttribute('style','');
1084 vbox.addEventListener('mouseover',on_mouseover,false);
1085 vbox.addEventListener('mouseout',on_mouseout,false);
1086 groupbox.addEventListener('mouseover',on_mouseover,false);
1087 groupbox.addEventListener('mouseout',on_mouseout,false);
1088 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
1089 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
1091 function on_click(ev){
1093 if (block) return; block = true;
1095 function post_c(v) {
1097 /* FIXME - kludgy */
1098 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
1102 f = input_cmd.match(/apply\("(.+?)",/)[1];
1105 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
1111 g.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v };
1115 g.summarize( g.copies );
1117 document.getElementById(caption.id).focus();
1121 g.error.standard_unexpected_error_alert('post_c',E);
1124 var x; var c; eval( input_cmd );
1126 util.widgets.remove_children(vbox);
1127 util.widgets.remove_children(hbox);
1128 util.widgets.remove_children(hbox2);
1129 hbox.appendChild(x);
1130 var apply = document.createElement('button');
1131 apply.setAttribute('label','Apply');
1132 apply.setAttribute('accesskey','A');
1133 hbox2.appendChild(apply);
1134 apply.addEventListener('command',function() { c(x.value); },false);
1135 var cancel = document.createElement('button');
1136 cancel.setAttribute('label','Cancel');
1137 cancel.addEventListener('command',function() { setTimeout( function() { g.summarize( g.copies ); g.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
1138 hbox2.appendChild(cancel);
1139 setTimeout( function() { x.focus(); }, 0 );
1142 g.error.standard_unexpected_error_alert('render_input',E);
1145 vbox.addEventListener('click',on_click, false);
1146 hbox.addEventListener('click',on_click, false);
1147 caption.addEventListener('click',on_click, false);
1148 caption.addEventListener('keypress',function(ev) {
1149 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
1151 caption.setAttribute('style','-moz-user-focus: normal');
1152 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
1153 caption.setAttribute('onblur','this.setAttribute("class","")');
1156 g.error.sdump('D_ERROR',E + '\n');
1160 /******************************************************************************************************/
1161 /* store the copies in the global xpcom stash */
1163 g.stash_and_close = function() {
1165 if (g.handle_update) {
1167 var r = g.network.request(
1168 api.FM_ACP_FLESHED_BATCH_UPDATE.app,
1169 api.FM_ACP_FLESHED_BATCH_UPDATE.method,
1170 [ ses(), g.copies, true ]
1172 if (typeof r.ilsevent != 'undefined') {
1173 g.error.standard_unexpected_error_alert('copy update',r);
1175 alert('Items added/modified.');
1177 /* FIXME -- revisit the return value here */
1179 alert('copy update error: ' + js2JSON(E));
1182 //g.data.temp_copies = js2JSON( g.copies );
1183 //g.data.stash('temp_copies');
1184 xulG.copies = g.copies;
1185 update_modal_xulG(xulG);
1188 g.error.standard_unexpected_error_alert('stash and close',E);
1192 /******************************************************************************************************/
1193 /* spawn copy notes interface */
1195 g.copy_notes = function() {
1196 JSAN.use('util.window'); var win = new util.window();
1198 urls.XUL_COPY_NOTES,
1199 //+ '?copy_id=' + window.escape(g.copies[0].id()),
1200 'Copy Notes','chrome,resizable,modal',
1201 { 'copy_id' : g.copies[0].id() }
1205 /******************************************************************************************************/
1206 /* hides or unhides stat cats based on library stat cat filter menu */
1207 g.toggle_stat_cat_display = function(el) {
1208 var visible = el.getAttribute('checked');
1209 var nl = document.getElementsByAttribute('sc_lib',el.getAttribute('value'));
1210 for (var n = 0; n < nl.length; n++) {
1212 nl[n].setAttribute('hidden','false');
1214 nl[n].setAttribute('hidden','true');
1217 g.copy_editor_prefs[ el.getAttribute('id') ] = { 'checked' : visible };
1218 JSAN.use('util.widgets'); JSAN.use('util.file'); var file = new util.file('copy_editor_prefs.'+g.data.server_unadorned);
1219 var what_to_save = {};
1220 for (var i in g.copy_editor_prefs) {
1221 what_to_save[i] = [];
1222 for (var j in g.copy_editor_prefs[i]) what_to_save[i].push(j);
1224 util.widgets.save_attributes(file, what_to_save );
1227 /******************************************************************************************************/
1228 /* This adds a stat cat definition to the stat cat pane for rendering */
1229 g.add_stat_cat = function(sc) {
1231 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; g.data.stash('hash'); }
1235 if (typeof sc == 'object') {
1240 if (typeof g.stat_cat_seen[sc_id] != 'undefined') { return; }
1242 g.stat_cat_seen[ sc_id ] = 1;
1244 if (typeof sc != 'object') {
1246 sc = g.network.simple_request(
1247 'FM_ASC_BATCH_RETRIEVE',
1248 [ ses(), [ sc_id ] ]
1253 g.data.hash.asc[ sc.id() ] = sc; g.data.stash('hash');
1255 var label_name = g.data.hash.aou[ sc.owner() ].shortname() + " : " + sc.name();
1260 render: 'var l = util.functional.find_list( fm.stat_cat_entries(), function(e){ return e.stat_cat() == '
1261 + sc.id() + '; } ); l ? l.value() : "<Unset>";',
1262 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()
1263 + '].entries(), function(obj){ return [ obj.value(), obj.id() ]; } ) ).sort() ); '
1264 + 'x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c),false);',
1271 g.panes_and_field_names.right_pane4.push( temp_array );
1273 g.error.standard_unexpected_error_alert('Error adding stat cat to display definition',E);
1277 /******************************************************************************************************/
1278 /* Add stat cats to the panes_and_field_names.right_pane4 */
1279 g.populate_stat_cats = function() {
1281 g.data.stash_retrieve();
1282 g.stat_cat_seen = {};
1284 function get(lib_id,only_these) {
1285 g.data.stash_retrieve();
1286 var label = 'asc_list_for_lib_'+lib_id;
1287 if (typeof g.data[label] == 'undefined') {
1288 var robj = g.network.simple_request('FM_ASC_RETRIEVE_VIA_AOU', [ ses(), lib_id ]);
1289 if (typeof robj.ilsevent != 'undefined') throw(robj);
1291 for (var j = 0; j < robj.length; j++) {
1292 var my_asc = robj[j];
1293 if (typeof g.data.hash.asc == 'undefined') { g.data.hash.asc = {}; }
1294 if (typeof g.data.hash.asc[ my_asc.id() ] == 'undefined') {
1295 g.data.hash.asc[ my_asc.id() ] = my_asc;
1297 var only_this_lib = my_asc.owner(); if (typeof only_this_lib == 'object') only_this_lib = only_this_lib.id();
1298 if (only_these.indexOf( String( only_this_lib ) ) != -1) {
1299 temp_list.push( my_asc );
1302 g.data[label] = temp_list; g.data.stash(label,'hash','list');
1304 return g.data[label];
1307 /* The stat cats for the pertinent library -- this is based on workstation ou */
1308 var label = 'asc_list_for_' + typeof g.data.ws_ou == 'object' ? g.data.ws_ou.id() : g.data.ws_ou;
1309 g.data[ label ] = g.data.list.my_asc; g.data.stash('label');
1310 for (var i = 0; i < g.data.list.my_asc.length; i++) {
1311 g.add_stat_cat( g.data.list.my_asc[i] );
1314 /* For the others, we want to consider the owning libs, circ libs, and any libs that have stat cats already on the copies,
1315 however, if batch editing, we only want to show the ones they have in common. So let's compile the libs */
1317 function add_common_ancestors(sc_libs) {
1318 JSAN.use('util.fm_utils');
1319 var libs = []; for (var i in sc_libs) libs.push(i);
1320 var ancestor = util.fm_utils.find_common_aou_ancestor( libs );
1321 if (typeof ancestor == 'object' && ancestor != null) ancestor = ancestor.id();
1323 var ancestors = util.fm_utils.find_common_aou_ancestors( libs );
1324 var asc_list = get(ancestor, ancestors);
1325 for (var i = 0; i < asc_list.length; i++) {
1326 g.add_stat_cat( asc_list[i] );
1331 /* stat cats based on stat cat entries present on these copies */
1333 for (var i = 0; i < g.copies.length; i++) {
1334 var entries = g.copies[i].stat_cat_entries();
1335 if (!entries) entries = [];
1336 for (var j = 0; j < entries.length; j++) {
1337 var lib = entries[j].owner(); if (typeof lib == 'object') lib = lib.id();
1338 sc_libs[ lib ] = true;
1341 add_common_ancestors(sc_libs); // CAVEAT - if a copy has no stat_cat_entries, it basically gets no vote here
1343 /* stat cats based on Circ Lib */
1345 for (var i = 0; i < g.copies.length; i++) {
1346 var circ_lib = g.copies[i].circ_lib(); if (typeof circ_lib == 'object') circ_lib = circ_lib.id();
1347 sc_libs[ circ_lib ] = true;
1349 add_common_ancestors(sc_libs);
1351 /* stat cats based on Owning Lib */
1353 for (var i = 0; i < g.copies.length; i++) {
1354 var cn_id = g.copies[i].call_number();
1356 if (! g.map_acn[ cn_id ]) {
1357 g.map_acn[ cn_id ] = g.network.simple_request('FM_ACN_RETRIEVE',[ cn_id ]);
1359 var owning_lib = g.map_acn[ cn_id ].owning_lib(); if (typeof owning_lib == 'object') owning_lib = owning_lib.id();
1360 sc_libs[ owning_lib ] = true;
1363 add_common_ancestors(sc_libs); // CAVEAT - if a copy is a pre-cat, it basically gets no vote here
1365 g.panes_and_field_names.right_pane4.sort();
1368 g.error.standard_unexpected_error_alert('Error populating stat cats for display',E);