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 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
15 if (typeof JSAN == 'undefined') {
16 throw( $('commonStrings').getString('common.jsan.missing') );
18 JSAN.errorLevel = "die"; // none, warn, or die
19 JSAN.addRepository('/xul/server/');
20 JSAN.use('util.error'); obj.error = new util.error();
21 obj.error.sdump('D_TRACE','my_init() for serial/editor_base.js');
23 JSAN.use('util.functional');
24 JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
25 JSAN.use('util.network'); obj.network = new util.network();
28 /******************************************************************************************************/
31 obj.docid = xul_param('docid',{'modal_xulG':true});
33 if (typeof params.handle_update == 'undefined') {
34 obj.handle_update = xul_param('handle_update',{'modal_xulG':true});
36 obj.handle_update = params.handle_update;
39 obj.trigger_refresh = params.trigger_refresh;
40 obj.refresh_command = params.refresh_command;
41 var fm_type = obj.fm_type;
42 var fm_type_plural = obj.fm_type_plural;
43 var retrieve_function = params.retrieve_function;
44 var retrieve_params = params.retrieve_params;
45 if (!retrieve_params) {
48 if (params.xul_id_prefix) {
49 obj.xul_id_prefix = params.xul_id_prefix;
51 obj.xul_id_prefix = fm_type;
54 /******************************************************************************************************/
55 /* Get the fm_type ids from various sources and flesh them */
57 var fm_type_ids = params[fm_type + '_ids'];
58 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});
59 if (!fm_type_ids) fm_type_ids = [];
61 obj[fm_type_plural] = [];
62 retrieve_params.push(fm_type_ids);
63 if (fm_type_ids.length > 0) obj[fm_type_plural] = obj.network.simple_request(
69 /******************************************************************************************************/
70 /* And other fleshed copies if any */
72 if (!obj[fm_type_plural]) obj[fm_type_plural] = [];
73 var fms = params[fm_type_plural];
74 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})
75 if (fms) obj[fm_type_plural] = obj[fm_type_plural].concat(fms);
78 // If we have just one, wrap in array
79 if (!obj[fm_type_plural].length) {
80 obj[fm_type_plural] = [obj[fm_type_plural]];
84 /******************************************************************************************************/
89 /******************************************************************************************************/
90 /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
93 if (typeof params.do_edit == 'undefined') {
94 do_edit = xul_param('do_edit',{'modal_xulG':true});
96 do_edit = params.do_edit;
101 // Editor desired, but let's check permissions
105 /* FIXME: add permission check
106 var check = obj.network.simple_request(
107 'PERM_MULTI_ORG_CHECK',
110 obj.data.list.au[0].id(),
111 util.functional.map_list(
115 var cn_id = o.call_number();
117 lib = o.circ_lib(); // base perms on circ_lib instead of owning_lib if pre-cat
119 if (! obj.map_acn[ cn_id ]) {
120 var req = obj.network.simple_request('FM_ACN_RETRIEVE.authoritative',[ cn_id ]);
121 if (typeof req.ilsevent == 'undefined') {
122 obj.map_acn[ cn_id ] = req;
123 lib = obj.map_acn[ cn_id ].owning_lib();
128 lib = obj.map_acn[ cn_id ].owning_lib();
131 return typeof lib == 'object' ? lib.id() : lib;
134 obj[fm_type_plural].length == 1 ? [ 'UPDATE_COPY' ] : [ 'UPDATE_COPY', 'UPDATE_BATCH_COPY' ]
138 obj.do_edit = check.length == 0;
140 obj.error.standard_unexpected_error_alert('batch permission check',E);
144 $(obj.xul_id_prefix + '_save').setAttribute('hidden','false');
146 $('top_nav').setAttribute('hidden','true');
149 $('top_nav').setAttribute('hidden','true');
153 if (obj[fm_type_plural].length > 0 && obj[fm_type_plural][0].isnew()) {
155 if (obj.can_have_notes) $(obj.xul_id_prefix + '_notes').setAttribute('hidden','true');
156 $(obj.xul_id_prefix + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create.label'));
157 $(obj.xul_id_prefix + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create.accesskey'));
158 } else if (obj.mode == 'create') { // switching from create to modify
160 if (obj.can_have_notes) $(obj.xul_id_prefix + '_notes').setAttribute('hidden','false');
161 $(obj.xul_id_prefix + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify.label'));
162 $(obj.xul_id_prefix + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify.accesskey'));
165 obj.panes_and_field_names.left_pane =
168 $('catStrings').getString('staff.cat.copy_editor.status'),
170 render: 'typeof fm.status() == "object" ? fm.status().name() : obj.data.hash.ccs[ fm.status() ].name()',
171 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,
172 //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);',
175 ].concat(obj.panes_and_field_names.left_pane);
178 if (obj[fm_type_plural].length != 1) {
179 if (obj.can_have_notes) $(obj.xul_id_prefix + '_notes').setAttribute('hidden','true');
182 // clear change markers
185 /******************************************************************************************************/
186 /* Show the Record Details? (only for 'in_modal' mode)*/
189 if (xul_param('in_modal',{'modal_xulG':true}) && obj.docid) {
190 bdb = document.getElementById('brief_display_box'); while(bdb.firstChild) bdb.removeChild(bdb.lastChild);
191 var brief_display = document.createElement('iframe'); bdb.appendChild(brief_display);
192 brief_display.setAttribute( 'src', urls.XUL_BIB_BRIEF + '?docid=' + obj.docid); // this is a modal window, so can't push in xulG
193 brief_display.setAttribute( 'flex','1' );
196 /******************************************************************************************************/
197 /* Backup copies :) */
199 obj['original_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
202 var err_msg = $("commonStrings").getFormattedString('common.exception', ['serial/' + fm_type +'_editor.js - init', E]);
203 try { obj.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
208 /******************************************************************************************************/
209 /* Restore backup copies */
211 'editor_base_reset' : function() {
213 var fm_type_plural = obj.fm_type_plural;
216 obj[fm_type_plural] = JSON2js( obj['original_' + fm_type_plural] );
217 obj.summarize( obj[fm_type_plural] );
221 /******************************************************************************************************/
222 /* Apply a value to a specific field on all the copies being edited */
223 /* Don't forget to use util.money.sanitize if dealing with money values */
225 'editor_base_apply' : function(field, value, loop_func) {
227 var fm_type_plural = obj.fm_type_plural;
229 var do_loop_func = (typeof loop_func == 'function');
231 obj.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
232 if (value == '<HACK:KLUDGE:NULL>') value = null;
233 for (var i = 0; i < obj[fm_type_plural].length; i++) {
234 var fm = obj[fm_type_plural][i];
236 fm[field]( value ); fm.ischanged('1');
247 /******************************************************************************************************/
248 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
250 'editor_base_summarize' : function(my_fms) {
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 for (var i = 0; i < obj.field_names.length; i++) {
267 var field_name = obj.field_names[i][0];
268 var render = obj.field_names[i][1].render;
269 var attr = obj.field_names[i][1].attr;
270 var value_key = obj.field_names[i][1].value_key;
271 var dropdown_key = obj.field_names[i][1].dropdown_key;
272 obj.summary[ field_name ] = {};
274 /******************************************************************************************************/
275 /* Loop through the copies */
277 for (var j = 0; j < my_fms.length; j++) {
280 var cmd = render || ('fm.' + field_name + '();');
283 /**********************************************************************************************/
284 /* Try to retrieve the value for this field for this copy */
288 if (typeof(value) == 'undefined') {
292 obj.editor_values[value_key] = eval(dropdown_key);
293 } else if (value_key) {
294 obj.editor_values[value_key] = value;
297 value = $('serialStrings').getString('serial.editor_base.unset');
300 obj.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
302 if (typeof value == 'object' && value != null) {
303 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
306 /**********************************************************************************************/
307 /* Tally the count */
309 if (obj.summary[ field_name ][ value ]) {
310 obj.summary[ field_name ][ value ]++;
312 obj.summary[ field_name ][ value ] = 1;
316 obj.error.sdump('D_TRACE','summary = ' + js2JSON(obj.summary) + '\n');
319 /******************************************************************************************************/
320 /* Display the summarized data and inputs for editing */
322 'editor_base_render' : function() {
324 var fm_type = obj.fm_type;
326 /******************************************************************************************************/
327 /* Library setup and clear any existing interface */
329 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
331 for (var i in obj.panes_and_field_names) {
332 var p = document.getElementById(i);
333 if (p) util.widgets.remove_children(p);
336 /******************************************************************************************************/
337 /* Prepare the panes */
339 var groupbox; var caption; var vbox; var grid; var rows;
341 /******************************************************************************************************/
342 /* Loop through the field names */
344 for (h in obj.panes_and_field_names) {
345 if (!document.getElementById(h)) continue;
346 for (var i = 0; i < obj.panes_and_field_names[h].length; i++) {
348 var f = obj.panes_and_field_names[h][i]; var fn = f[0]; var attr = f[1].attr;
349 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
351 for (var a in attr) {
352 groupbox.setAttribute(a,attr[a]);
355 if (typeof obj.changed[fn] != 'undefined') {
356 groupbox.setAttribute('class','copy_editor_field_changed');
358 caption = document.createElement('caption'); groupbox.appendChild(caption);
359 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
360 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
361 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
362 grid.setAttribute('flex','1');
363 rows = grid.lastChild;
366 /**************************************************************************************/
367 /* Loop through each value for the field */
369 for (var j in obj.summary[fn]) {
370 var value = j; var count = obj.summary[fn][j];
371 row = document.createElement('row'); rows.appendChild(row);
372 var label1 = document.createElement('description'); row.appendChild(label1);
373 label1.setAttribute('id',fn + '_label');
374 //if (obj.special_exception[ fn ]) {
375 // obj.special_exception[ fn ]( label1, value );
377 label1.appendChild( document.createTextNode(value) );
379 var label2 = document.createElement('description'); row.appendChild(label2);
382 fm_count = $('serialStrings').getString('staff.serial.' + fm_type +'_editor.count');
384 fm_count = $('serialStrings').getFormattedString('staff.serial.' + fm_type +'_editor.count.plural', [count]);
386 label2.appendChild( document.createTextNode(fm_count) );
388 var hbox = document.createElement('hbox');
389 hbox.setAttribute('id',fn);
390 groupbox.appendChild(hbox);
391 var hbox2 = document.createElement('hbox');
392 groupbox.appendChild(hbox2);
394 /**************************************************************************************/
395 /* Render the input widget */
397 if (f[1].input && obj.do_edit) {
398 obj.render_input(hbox,f[1]);
402 obj.error.sdump('D_ERROR','copy editor: ' + E + '\n');
408 /******************************************************************************************************/
409 /* Synchronize stat cat visibility with library filter menu, and default template selection */
410 JSAN.use('util.file');
411 var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
412 obj[fm_type + '_editor_prefs'] = util.widgets.load_attributes(file);
413 for (var i in obj[fm_type + '_editor_prefs']) {
414 if (i.match(/filter_/) && obj[fm_type + '_editor_prefs'][i].checked == '') {
416 obj.toggle_stat_cat_display( document.getElementById(i) );
417 } catch(E) { alert(E); }
420 if (obj.template_menu) obj.template_menu.value = obj.template_menu.getAttribute('value');
424 /******************************************************************************************************/
425 /* This actually draws the change button and input widget for a given field */
426 'editor_base_render_input' : function(node, blob) {
428 var fm_type_plural = obj.fm_type_plural;
431 // node = hbox ; groupbox -> hbox, hbox
433 var groupbox = node.parentNode;
434 var caption = groupbox.firstChild;
435 var vbox = node.previousSibling;
437 var hbox2 = node.nextSibling;
439 var input_cmd = blob.input;
440 var render_cmd = blob.render;
441 var attr = blob.attr;
443 var block = false; var first = true;
445 function on_mouseover(ev) {
446 groupbox.setAttribute('style','background: white');
449 function on_mouseout(ev) {
450 groupbox.setAttribute('style','');
453 vbox.addEventListener('mouseover',on_mouseover,false);
454 vbox.addEventListener('mouseout',on_mouseout,false);
455 groupbox.addEventListener('mouseover',on_mouseover,false);
456 groupbox.addEventListener('mouseout',on_mouseout,false);
457 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
458 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
460 function on_click(ev){
462 if (block) return; block = true;
464 function post_c(v, unchanged) {
467 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
471 f = input_cmd.match(/apply.?\("(.+?)",/)[1];
474 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
480 obj.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v }; */
482 obj.changed[ hbox.id ] = true;
487 obj.summarize( obj[fm_type_plural] );
489 document.getElementById(caption.id).focus();
493 obj.error.standard_unexpected_error_alert('post_c',E);
496 var x; var c; eval( input_cmd );
498 util.widgets.remove_children(vbox);
499 util.widgets.remove_children(hbox);
500 util.widgets.remove_children(hbox2);
502 var apply = document.createElement('button');
503 apply.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.apply.label'));
504 apply.setAttribute('accesskey', $('catStrings').getString('staff.cat.copy_editor.apply.accesskey'));
505 hbox2.appendChild(apply);
506 apply.addEventListener('command',function() { c(x.value); },false);
507 var cancel = document.createElement('button');
508 cancel.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.cancel.label'));
509 cancel.addEventListener('command',function() { setTimeout( function() { obj.summarize( obj[fm_type_plural] ); obj.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
510 hbox2.appendChild(cancel);
511 setTimeout( function() { x.focus(); }, 0 );
514 obj.error.standard_unexpected_error_alert('render_input',E);
517 vbox.addEventListener('click',on_click, false);
518 hbox.addEventListener('click',on_click, false);
519 caption.addEventListener('click',on_click, false);
520 caption.addEventListener('keypress',function(ev) {
521 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
523 caption.setAttribute('style','-moz-user-focus: normal');
524 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
525 caption.setAttribute('onblur','this.setAttribute("class","")');
528 obj.error.sdump('D_ERROR',E + '\n');
532 /******************************************************************************************************/
533 /* save or store the updated fms as appropriate */
535 'editor_base_save' : function(update_method) {
537 var fm_type_plural = obj.fm_type_plural;
538 var fm_type= obj.fm_type;
541 if (obj.handle_update) {
543 //send fms to the update function
544 var r = obj.network.request(
547 [ ses(), obj[fm_type_plural] ]
549 if (typeof r.ilsevent != 'undefined') {
550 obj.error.standard_unexpected_error_alert('serial ' + fm_type + ' update',r);
552 alert($('serialStrings').getString('staff.serial.editor_base.handle_update.success'));
554 if (obj.trigger_refresh) {
555 obj.refresh_command();
560 /* FIXME -- revisit the return value here */
562 alert($('serialStrings').getString('staff.serial.editor_base.handle_update.error') + ' ' + js2JSON(E));
564 } else if (xul_param('in_modal',{'modal_xulG':true})) {
565 // TODO: this is to perhaps allow this editor to be called
566 // in a modal window, but is unfinished functionality
568 xulG[fm_type_plural] = obj[fm_type_plural];
569 update_modal_xulG(xulG);
571 obj.data['temp_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
572 obj.data.stash('temp_' + fm_type_plural);
575 if (xul_param('in_modal',{'modal_xulG':true})) {
579 obj.error.standard_unexpected_error_alert(fm_type + '_editor save',E);
583 /******************************************************************************************************/
584 'editor_base_save_attributes' : function() {
586 var fm_type = obj.fm_type;
588 JSAN.use('util.widgets'); JSAN.use('util.file'); var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
589 var what_to_save = {};
590 for (var i in obj[fm_type + '_editor_prefs']) {
591 what_to_save[i] = [];
592 for (var j in obj[fm_type + '_editor_prefs'][i]) what_to_save[i].push(j);
594 util.widgets.save_attributes(file, what_to_save );
598 dump('exiting serial/editor_base.js\n');