1 dump('entering serial/editor_base.js\n');
4 if (typeof serial == 'undefined') serial = {};
8 'editor_base_init' : function (params) {
11 /******************************************************************************************************/
12 /* setup JSAN and some initial libraries */
14 if (typeof JSAN == 'undefined') {
15 throw( $('commonStrings').getString('common.jsan.missing') );
17 JSAN.errorLevel = "die"; // none, warn, or die
18 JSAN.addRepository('/xul/server/');
19 JSAN.use('util.error'); obj.error = new util.error();
20 obj.error.sdump('D_TRACE','my_init() for serial/editor_base.js');
22 JSAN.use('util.functional');
23 JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
24 JSAN.use('util.network'); obj.network = new util.network();
27 /******************************************************************************************************/
30 obj.docid = xul_param('docid',{'modal_xulG':true});
32 if (typeof params.handle_update == 'undefined') {
33 obj.handle_update = xul_param('handle_update',{'modal_xulG':true});
35 obj.handle_update = params.handle_update;
38 obj.trigger_refresh = params.trigger_refresh;
39 obj.refresh_command = params.refresh_command;
40 var fm_type = obj.fm_type;
41 var fm_type_plural = obj.fm_type_plural;
42 var retrieve_function = params.retrieve_function;
43 var retrieve_params = params.retrieve_params;
44 if (!retrieve_params) {
47 if (params.xul_id_prefix) {
48 obj.xul_id_prefix = params.xul_id_prefix;
50 obj.xul_id_prefix = fm_type;
53 /******************************************************************************************************/
54 /* Get the fm_type ids from various sources and flesh them */
56 var fm_type_ids = params[fm_type + '_ids'];
57 if (!fm_type_ids) fm_type_ids = xul_param(fm_type + '_ids',{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xulG':true,'JSON2js_if_xpcom':true,'stash_name':'temp_' + fm_type + '_ids','clear_xpcom':true,'modal_xulG':true});
58 if (!fm_type_ids) fm_type_ids = [];
60 obj[fm_type_plural] = [];
61 retrieve_params.push(fm_type_ids);
62 if (fm_type_ids.length > 0) obj[fm_type_plural] = obj.network.simple_request(
68 /******************************************************************************************************/
69 /* And other fleshed copies if any */
71 if (!obj[fm_type_plural]) obj[fm_type_plural] = [];
72 var fms = params[fm_type_plural];
73 if (!fms) fms = xul_param(fm_type_plural,{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xpcom':true,'stash_name':'temp_' + fm_type_plural,'clear_xpcom':true,'modal_xulG':true})
74 if (fms) obj[fm_type_plural] = obj[fm_type_plural].concat(fms);
77 // If we have just one, wrap in array
78 if (!obj[fm_type_plural].length) {
79 obj[fm_type_plural] = [obj[fm_type_plural]];
83 /******************************************************************************************************/
88 /******************************************************************************************************/
89 /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
92 if (typeof params.do_edit == 'undefined') {
93 do_edit = xul_param('do_edit',{'modal_xulG':true});
95 do_edit = params.do_edit;
100 // Editor desired, but let's check permissions
104 /* FIXME: add permission check
105 var check = obj.network.simple_request(
106 'PERM_MULTI_ORG_CHECK',
109 obj.data.list.au[0].id(),
110 util.functional.map_list(
114 var cn_id = o.call_number();
116 lib = o.circ_lib(); // base perms on circ_lib instead of owning_lib if pre-cat
118 if (! obj.map_acn[ cn_id ]) {
119 var req = obj.network.simple_request('FM_ACN_RETRIEVE.authoritative',[ cn_id ]);
120 if (typeof req.ilsevent == 'undefined') {
121 obj.map_acn[ cn_id ] = req;
122 lib = obj.map_acn[ cn_id ].owning_lib();
127 lib = obj.map_acn[ cn_id ].owning_lib();
130 return typeof lib == 'object' ? lib.id() : lib;
133 obj[fm_type_plural].length == 1 ? [ 'UPDATE_COPY' ] : [ 'UPDATE_COPY', 'UPDATE_BATCH_COPY' ]
137 obj.do_edit = check.length == 0;
139 obj.error.standard_unexpected_error_alert('batch permission check',E);
143 $(obj.xul_id_prefix + '_save').setAttribute('hidden','false');
145 $('top_nav').setAttribute('hidden','true');
148 $('top_nav').setAttribute('hidden','true');
152 if (obj[fm_type_plural].length > 0 && obj[fm_type_plural][0].isnew()) {
154 if (obj.can_have_notes) $(obj.xul_id_prefix + '_notes').setAttribute('hidden','true');
155 $(obj.xul_id_prefix + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create.label'));
156 $(obj.xul_id_prefix + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create.accesskey'));
157 } else if (obj.mode == 'create') { // switching from create to modify
159 if (obj.can_have_notes) $(obj.xul_id_prefix + '_notes').setAttribute('hidden','false');
160 $(obj.xul_id_prefix + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify.label'));
161 $(obj.xul_id_prefix + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify.accesskey'));
164 obj.panes_and_field_names.left_pane =
167 $('catStrings').getString('staff.cat.copy_editor.status'),
169 render: 'typeof fm.status() == "object" ? fm.status().name() : obj.data.hash.ccs[ fm.status() ].name()',
170 input: obj.safe_to_edit_copy_status() ? 'c = function(v){ obj.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.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,
171 //input: 'c = function(v){ obj.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( util.functional.filter_list( obj.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);',
174 ].concat(obj.panes_and_field_names.left_pane);
177 if (obj[fm_type_plural].length != 1) {
178 if (obj.can_have_notes) $(obj.xul_id_prefix + '_notes').setAttribute('hidden','true');
181 // clear change markers
184 /******************************************************************************************************/
185 /* Show the Record Details? (only for 'in_modal' mode)*/
188 if (xul_param('in_modal',{'modal_xulG':true}) && obj.docid) {
189 bdb = document.getElementById('brief_display_box'); while(bdb.firstChild) bdb.removeChild(bdb.lastChild);
190 var brief_display = document.createElement('iframe'); bdb.appendChild(brief_display);
191 brief_display.setAttribute( 'src', urls.XUL_BIB_BRIEF + '?docid=' + obj.docid); // this is a modal window, so can't push in xulG
192 brief_display.setAttribute( 'flex','1' );
195 /******************************************************************************************************/
196 /* Backup copies :) */
198 obj['original_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
201 var err_msg = $("commonStrings").getFormattedString('common.exception', ['serial/' + fm_type +'_editor.js - init', E]);
202 try { obj.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
207 /******************************************************************************************************/
208 /* Restore backup copies */
210 'editor_base_reset' : function() {
212 var fm_type_plural = obj.fm_type_plural;
215 obj[fm_type_plural] = JSON2js( obj['original_' + fm_type_plural] );
216 obj.summarize( obj[fm_type_plural] );
220 /******************************************************************************************************/
221 /* Apply a value to a specific field on all the copies being edited */
222 /* Don't forget to use util.money.sanitize if dealing with money values */
224 'editor_base_apply' : function(field, value, loop_func) {
226 var fm_type_plural = obj.fm_type_plural;
228 var do_loop_func = (typeof loop_func == 'function');
230 obj.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
231 if (value == '<HACK:KLUDGE:NULL>') value = null;
232 for (var i = 0; i < obj[fm_type_plural].length; i++) {
233 var fm = obj[fm_type_plural][i];
235 fm[field]( value ); fm.ischanged('1');
246 /******************************************************************************************************/
247 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
249 'editor_base_summarize' : function(my_fms) {
251 var fm_type = obj.fm_type;
252 /******************************************************************************************************/
255 JSAN.use('util.date'); JSAN.use('util.money');
257 obj.field_names = [];
258 for (var i in obj.panes_and_field_names) {
259 obj.field_names = obj.field_names.concat( obj.panes_and_field_names[i] );
262 /******************************************************************************************************/
263 /* Loop through the field names */
265 obj.missing_required = [];
267 for (var i = 0; i < obj.field_names.length; i++) {
269 var field_name = obj.field_names[i][0];
270 var render = obj.field_names[i][1].render;
271 var attr = obj.field_names[i][1].attr;
272 var value_key = obj.field_names[i][1].value_key;
273 var dropdown_key = obj.field_names[i][1].dropdown_key;
274 var required = obj.field_names[i][1].required;
275 obj.summary[ field_name ] = {};
277 /******************************************************************************************************/
278 /* Loop through the copies */
280 for (var j = 0; j < my_fms.length; j++) {
283 var cmd = render || ('fm.' + field_name + '();');
286 /**********************************************************************************************/
287 /* Try to retrieve the value for this field for this copy */
291 if (value == null) { // true for both 'null' and undefined
295 obj.editor_values[value_key] = eval(dropdown_key);
296 } else if (value_key) {
297 obj.editor_values[value_key] = value;
299 if (required && value == "") {
300 obj.missing_required.push(fieldmapper.IDL.fmclasses[fm_type].field_map[field_name].label); //TODO: consider applying a style
304 value = $('serialStrings').getString('serial.editor_base.unset');
308 obj.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
310 if (typeof value == 'object' && value != null) {
311 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
314 /**********************************************************************************************/
315 /* Tally the count */
317 if (obj.summary[ field_name ][ value ]) {
318 obj.summary[ field_name ][ value ]++;
320 obj.summary[ field_name ][ value ] = 1;
325 obj.error.sdump('D_TRACE','summary = ' + js2JSON(obj.summary) + '\n');
328 /******************************************************************************************************/
329 /* Display the summarized data and inputs for editing */
331 'editor_base_render' : function() {
333 var fm_type = obj.fm_type;
335 /******************************************************************************************************/
336 /* Library setup and clear any existing interface */
338 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
340 for (var i in obj.panes_and_field_names) {
341 var p = document.getElementById(i);
342 if (p) util.widgets.remove_children(p);
345 /******************************************************************************************************/
346 /* Prepare the panes */
348 var groupbox; var caption; var vbox; var grid; var rows;
350 /******************************************************************************************************/
351 /* Loop through the field names */
353 for (h in obj.panes_and_field_names) {
354 if (!document.getElementById(h)) continue;
355 for (var i = 0; i < obj.panes_and_field_names[h].length; i++) {
357 var f = obj.panes_and_field_names[h][i]; var fn = f[0]; var attr = f[1].attr;
358 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
360 for (var a in attr) {
361 groupbox.setAttribute(a,attr[a]);
364 if (typeof obj.changed[fn] != 'undefined') {
365 groupbox.setAttribute('class','copy_editor_field_changed');
367 caption = document.createElement('caption'); groupbox.appendChild(caption);
369 caption.setAttribute('label',f[1].label);
371 caption.setAttribute('label',fieldmapper.IDL.fmclasses[fm_type].field_map[fn].label);
373 caption.setAttribute('id','caption_'+fn);
374 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
375 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
376 grid.setAttribute('flex','1');
377 rows = grid.lastChild;
380 /**************************************************************************************/
381 /* Loop through each value for the field */
383 for (var j in obj.summary[fn]) {
384 var value = j; var count = obj.summary[fn][j];
385 row = document.createElement('row'); rows.appendChild(row);
386 var label1 = document.createElement('description'); row.appendChild(label1);
387 label1.setAttribute('id',fn + '_label');
388 //if (obj.special_exception[ fn ]) {
389 // obj.special_exception[ fn ]( label1, value );
391 label1.appendChild( document.createTextNode(value) );
393 var label2 = document.createElement('description'); row.appendChild(label2);
396 fm_count = $('serialStrings').getString('staff.serial.' + fm_type +'_editor.count');
398 fm_count = $('serialStrings').getFormattedString('staff.serial.' + fm_type +'_editor.count.plural', [count]);
400 label2.appendChild( document.createTextNode(fm_count) );
402 var hbox = document.createElement('hbox');
403 hbox.setAttribute('id',fn);
404 groupbox.appendChild(hbox);
405 var hbox2 = document.createElement('hbox');
406 groupbox.appendChild(hbox2);
408 /**************************************************************************************/
409 /* Render the input widget */
411 if (f[1].input && obj.do_edit) {
412 obj.render_input(hbox,f[1]);
416 obj.error.sdump('D_ERROR','copy editor: ' + E + '\n');
422 /******************************************************************************************************/
423 /* Synchronize stat cat visibility with library filter menu, and default template selection */
424 JSAN.use('util.file');
425 var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
426 obj[fm_type + '_editor_prefs'] = util.widgets.load_attributes(file);
427 for (var i in obj[fm_type + '_editor_prefs']) {
428 if (i.match(/filter_/) && obj[fm_type + '_editor_prefs'][i].checked == '') {
430 obj.toggle_stat_cat_display( document.getElementById(i) );
431 } catch(E) { alert(E); }
434 if (obj.template_menu) obj.template_menu.value = obj.template_menu.getAttribute('value');
438 /******************************************************************************************************/
439 /* This actually draws the change button and input widget for a given field */
440 'editor_base_render_input' : function(node, blob) {
442 var fm_type_plural = obj.fm_type_plural;
445 // node = hbox ; groupbox -> hbox, hbox
447 var groupbox = node.parentNode;
448 var caption = groupbox.firstChild;
449 var vbox = node.previousSibling;
451 var hbox2 = node.nextSibling;
453 var input_cmd = blob.input;
454 var render_cmd = blob.render;
455 var attr = blob.attr;
457 var block = false; var first = true;
459 function on_mouseover(ev) {
460 groupbox.setAttribute('style','background: white');
463 function on_mouseout(ev) {
464 groupbox.setAttribute('style','');
467 vbox.addEventListener('mouseover',on_mouseover,false);
468 vbox.addEventListener('mouseout',on_mouseout,false);
469 groupbox.addEventListener('mouseover',on_mouseover,false);
470 groupbox.addEventListener('mouseout',on_mouseout,false);
471 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
472 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
474 function on_click(ev){
476 if (block) return; block = true;
478 function post_c(v, unchanged) {
481 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
485 f = input_cmd.match(/apply.?\("(.+?)",/)[1];
488 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
494 obj.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v }; */
496 obj.changed[ hbox.id ] = true;
501 obj.summarize( obj[fm_type_plural] );
503 document.getElementById(caption.id).focus();
507 obj.error.standard_unexpected_error_alert('post_c',E);
510 var x; var c; eval( input_cmd );
512 util.widgets.remove_children(vbox);
513 util.widgets.remove_children(hbox);
514 util.widgets.remove_children(hbox2);
516 var apply = document.createElement('button');
517 apply.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.apply.label'));
518 apply.setAttribute('accesskey', $('catStrings').getString('staff.cat.copy_editor.apply.accesskey'));
519 hbox2.appendChild(apply);
520 apply.addEventListener('command',function() { c(x.value); },false);
521 var cancel = document.createElement('button');
522 cancel.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.cancel.label'));
523 cancel.addEventListener('command',function() { setTimeout( function() { obj.summarize( obj[fm_type_plural] ); obj.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
524 hbox2.appendChild(cancel);
525 setTimeout( function() { x.focus(); }, 0 );
528 obj.error.standard_unexpected_error_alert('render_input',E);
531 vbox.addEventListener('click',on_click, false);
532 hbox.addEventListener('click',on_click, false);
533 caption.addEventListener('click',on_click, false);
534 caption.addEventListener('keypress',function(ev) {
535 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
537 caption.setAttribute('style','-moz-user-focus: normal');
538 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
539 caption.setAttribute('onblur','this.setAttribute("class","")');
542 obj.error.sdump('D_ERROR',E + '\n');
546 /******************************************************************************************************/
547 /* save or store the updated fms as appropriate */
549 'editor_base_save' : function(update_method) {
551 var fm_type_plural = obj.fm_type_plural;
552 var fm_type = obj.fm_type;
555 if (obj.handle_update) {
557 if (obj.missing_required.length > 0) {
558 alert($('serialStrings').getString('staff.serial.required_fields_alert') + obj.missing_required.join(', '));
559 return; //stop submission
562 //send fms to the update function
563 var r = obj.network.request(
566 [ ses(), obj[fm_type_plural] ]
568 if (typeof r.ilsevent != 'undefined') {
569 obj.error.standard_unexpected_error_alert('serial ' + fm_type + ' update',r);
571 alert($('serialStrings').getString('staff.serial.editor_base.handle_update.success'));
573 if (obj.trigger_refresh) {
574 obj.refresh_command();
579 /* FIXME -- revisit the return value here */
581 alert($('serialStrings').getString('staff.serial.editor_base.handle_update.error') + ' ' + js2JSON(E));
583 } else if (xul_param('in_modal',{'modal_xulG':true})) {
584 // TODO: this is to perhaps allow this editor to be called
585 // in a modal window, but is unfinished functionality
587 xulG[fm_type_plural] = obj[fm_type_plural];
588 update_modal_xulG(xulG);
590 obj.data['temp_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
591 obj.data.stash('temp_' + fm_type_plural);
594 if (xul_param('in_modal',{'modal_xulG':true})) {
598 obj.error.standard_unexpected_error_alert(fm_type + '_editor save',E);
602 /******************************************************************************************************/
603 'editor_base_save_attributes' : function() {
605 var fm_type = obj.fm_type;
607 JSAN.use('util.widgets'); JSAN.use('util.file'); var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
608 var what_to_save = {};
609 for (var i in obj[fm_type + '_editor_prefs']) {
610 what_to_save[i] = [];
611 for (var j in obj[fm_type + '_editor_prefs'][i]) what_to_save[i].push(j);
613 util.widgets.save_attributes(file, what_to_save );
617 dump('exiting serial/editor_base.js\n');