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) {
49 /******************************************************************************************************/
50 /* Get the fm_type ids from various sources and flesh them */
52 var fm_type_ids = params[fm_type + '_ids'];
53 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});
54 if (!fm_type_ids) fm_type_ids = [];
56 obj[fm_type_plural] = [];
57 retrieve_params.push(fm_type_ids);
58 if (fm_type_ids.length > 0) obj[fm_type_plural] = obj.network.simple_request(
64 /******************************************************************************************************/
65 /* And other fleshed copies if any */
67 if (!obj[fm_type_plural]) obj[fm_type_plural] = [];
68 var fms = params[fm_type_plural];
69 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})
70 if (fms) obj[fm_type_plural] = obj[fm_type_plural].concat(fms);
73 // If we have just one, wrap in array
74 if (!obj[fm_type_plural].length) {
75 obj[fm_type_plural] = [obj[fm_type_plural]];
79 /******************************************************************************************************/
84 /******************************************************************************************************/
85 /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
88 if (typeof params.do_edit == 'undefined') {
89 do_edit = xul_param('do_edit',{'modal_xulG':true});
91 do_edit = params.do_edit;
96 // Editor desired, but let's check permissions
100 /* FIXME: add permission check
101 var check = obj.network.simple_request(
102 'PERM_MULTI_ORG_CHECK',
105 obj.data.list.au[0].id(),
106 util.functional.map_list(
110 var cn_id = o.call_number();
112 lib = o.circ_lib(); // base perms on circ_lib instead of owning_lib if pre-cat
114 if (! obj.map_acn[ cn_id ]) {
115 var req = obj.network.simple_request('FM_ACN_RETRIEVE.authoritative',[ cn_id ]);
116 if (typeof req.ilsevent == 'undefined') {
117 obj.map_acn[ cn_id ] = req;
118 lib = obj.map_acn[ cn_id ].owning_lib();
123 lib = obj.map_acn[ cn_id ].owning_lib();
126 return typeof lib == 'object' ? lib.id() : lib;
129 obj[fm_type_plural].length == 1 ? [ 'UPDATE_COPY' ] : [ 'UPDATE_COPY', 'UPDATE_BATCH_COPY' ]
133 obj.do_edit = check.length == 0;
135 obj.error.standard_unexpected_error_alert('batch permission check',E);
139 $(fm_type + '_save').setAttribute('hidden','false');
141 $('top_nav').setAttribute('hidden','true');
144 $('top_nav').setAttribute('hidden','true');
148 if (obj[fm_type_plural].length > 0 && obj[fm_type_plural][0].isnew()) {
150 if (obj.can_have_notes) $(fm_type + '_notes').setAttribute('hidden','true');
151 $(fm_type + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create'));
152 $(fm_type + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create.accesskey'));
153 } else if (obj.mode == 'create') { // switching from create to modify
155 if (obj.can_have_notes) $(fm_type + '_notes').setAttribute('hidden','false');
156 $(fm_type + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify'));
157 $(fm_type + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify.accesskey'));
160 obj.panes_and_field_names.left_pane =
163 $('catStrings').getString('staff.cat.copy_editor.status'),
165 render: 'typeof fm.status() == "object" ? fm.status().name() : obj.data.hash.ccs[ fm.status() ].name()',
166 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,
167 //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);',
170 ].concat(obj.panes_and_field_names.left_pane);
173 if (obj[fm_type_plural].length != 1) {
174 document.getElementById(fm_type + '_notes').setAttribute('hidden','true');
177 // clear change markers
180 /******************************************************************************************************/
181 /* Show the Record Details? (only for 'in_modal' mode)*/
184 if (xul_param('in_modal',{'modal_xulG':true}) && obj.docid) {
185 bdb = document.getElementById('brief_display_box'); while(bdb.firstChild) bdb.removeChild(bdb.lastChild);
186 var brief_display = document.createElement('iframe'); bdb.appendChild(brief_display);
187 brief_display.setAttribute( 'src', urls.XUL_BIB_BRIEF + '?docid=' + obj.docid); // this is a modal window, so can't push in xulG
188 brief_display.setAttribute( 'flex','1' );
191 /******************************************************************************************************/
192 /* Backup copies :) */
194 obj['original_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
197 var err_msg = $("commonStrings").getFormattedString('common.exception', ['serial/' + fm_type +'_editor.js - init', E]);
198 try { obj.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
203 /******************************************************************************************************/
204 /* Restore backup copies */
206 'editor_base_reset' : function() {
208 var fm_type_plural = obj.fm_type_plural;
211 obj[fm_type_plural] = JSON2js( obj['original_' + fm_type_plural] );
212 obj.summarize( obj[fm_type_plural] );
216 /******************************************************************************************************/
217 /* Apply a value to a specific field on all the copies being edited */
218 /* Don't forget to use util.money.sanitize if dealing with money values */
220 'editor_base_apply' : function(field, value, loop_func) {
222 var fm_type_plural = obj.fm_type_plural;
224 var do_loop_func = (typeof loop_func == 'function');
226 obj.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
227 if (value == '<HACK:KLUDGE:NULL>') value = null;
228 for (var i = 0; i < obj[fm_type_plural].length; i++) {
229 var fm = obj[fm_type_plural][i];
231 fm[field]( value ); fm.ischanged('1');
242 /******************************************************************************************************/
243 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
245 'editor_base_summarize' : function(my_fms) {
247 /******************************************************************************************************/
250 JSAN.use('util.date'); JSAN.use('util.money');
252 obj.field_names = [];
253 for (var i in obj.panes_and_field_names) {
254 obj.field_names = obj.field_names.concat( obj.panes_and_field_names[i] );
257 /******************************************************************************************************/
258 /* Loop through the field names */
260 for (var i = 0; i < obj.field_names.length; i++) {
262 var field_name = obj.field_names[i][0];
263 var render = obj.field_names[i][1].render;
264 var attr = obj.field_names[i][1].attr;
265 var value_key = obj.field_names[i][1].value_key;
266 var dropdown_key = obj.field_names[i][1].dropdown_key;
267 obj.summary[ field_name ] = {};
269 /******************************************************************************************************/
270 /* Loop through the copies */
272 for (var j = 0; j < my_fms.length; j++) {
275 var cmd = render || ('fm.' + field_name + '();');
278 /**********************************************************************************************/
279 /* Try to retrieve the value for this field for this copy */
283 if (typeof(value) == 'undefined') {
287 obj.editor_values[value_key] = eval(dropdown_key);
288 } else if (value_key) {
289 obj.editor_values[value_key] = value;
295 obj.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
297 if (typeof value == 'object' && value != null) {
298 alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
301 /**********************************************************************************************/
302 /* Tally the count */
304 if (obj.summary[ field_name ][ value ]) {
305 obj.summary[ field_name ][ value ]++;
307 obj.summary[ field_name ][ value ] = 1;
311 obj.error.sdump('D_TRACE','summary = ' + js2JSON(obj.summary) + '\n');
314 /******************************************************************************************************/
315 /* Display the summarized data and inputs for editing */
317 'editor_base_render' : function() {
319 var fm_type = obj.fm_type;
321 /******************************************************************************************************/
322 /* Library setup and clear any existing interface */
324 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
326 for (var i in obj.panes_and_field_names) {
327 var p = document.getElementById(i);
328 if (p) util.widgets.remove_children(p);
331 /******************************************************************************************************/
332 /* Prepare the panes */
334 var groupbox; var caption; var vbox; var grid; var rows;
336 /******************************************************************************************************/
337 /* Loop through the field names */
339 for (h in obj.panes_and_field_names) {
340 if (!document.getElementById(h)) continue;
341 for (var i = 0; i < obj.panes_and_field_names[h].length; i++) {
343 var f = obj.panes_and_field_names[h][i]; var fn = f[0]; var attr = f[1].attr;
344 groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
346 for (var a in attr) {
347 groupbox.setAttribute(a,attr[a]);
350 if (typeof obj.changed[fn] != 'undefined') {
351 groupbox.setAttribute('class','copy_editor_field_changed');
353 caption = document.createElement('caption'); groupbox.appendChild(caption);
354 caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
355 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
356 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
357 grid.setAttribute('flex','1');
358 rows = grid.lastChild;
361 /**************************************************************************************/
362 /* Loop through each value for the field */
364 for (var j in obj.summary[fn]) {
365 var value = j; var count = obj.summary[fn][j];
366 row = document.createElement('row'); rows.appendChild(row);
367 var label1 = document.createElement('description'); row.appendChild(label1);
368 label1.setAttribute('id',fn + '_label');
369 //if (obj.special_exception[ fn ]) {
370 // obj.special_exception[ fn ]( label1, value );
372 label1.appendChild( document.createTextNode(value) );
374 var label2 = document.createElement('description'); row.appendChild(label2);
377 fm_count = $('serialStrings').getString('staff.serial.' + fm_type +'_editor.count');
379 fm_count = $('serialStrings').getFormattedString('staff.serial.' + fm_type +'_editor.count.plural', [count]);
381 label2.appendChild( document.createTextNode(fm_count) );
383 var hbox = document.createElement('hbox');
384 hbox.setAttribute('id',fn);
385 groupbox.appendChild(hbox);
386 var hbox2 = document.createElement('hbox');
387 groupbox.appendChild(hbox2);
389 /**************************************************************************************/
390 /* Render the input widget */
392 if (f[1].input && obj.do_edit) {
393 obj.render_input(hbox,f[1]);
397 obj.error.sdump('D_ERROR','copy editor: ' + E + '\n');
403 /******************************************************************************************************/
404 /* Synchronize stat cat visibility with library filter menu, and default template selection */
405 JSAN.use('util.file');
406 var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
407 obj[fm_type + '_editor_prefs'] = util.widgets.load_attributes(file);
408 for (var i in obj[fm_type + '_editor_prefs']) {
409 if (i.match(/filter_/) && obj[fm_type + '_editor_prefs'][i].checked == '') {
411 obj.toggle_stat_cat_display( document.getElementById(i) );
412 } catch(E) { alert(E); }
415 if (obj.template_menu) obj.template_menu.value = obj.template_menu.getAttribute('value');
419 /******************************************************************************************************/
420 /* This actually draws the change button and input widget for a given field */
421 'editor_base_render_input' : function(node, blob) {
423 var fm_type_plural = obj.fm_type_plural;
426 // node = hbox ; groupbox -> hbox, hbox
428 var groupbox = node.parentNode;
429 var caption = groupbox.firstChild;
430 var vbox = node.previousSibling;
432 var hbox2 = node.nextSibling;
434 var input_cmd = blob.input;
435 var render_cmd = blob.render;
436 var attr = blob.attr;
438 var block = false; var first = true;
440 function on_mouseover(ev) {
441 groupbox.setAttribute('style','background: white');
444 function on_mouseout(ev) {
445 groupbox.setAttribute('style','');
448 vbox.addEventListener('mouseover',on_mouseover,false);
449 vbox.addEventListener('mouseout',on_mouseout,false);
450 groupbox.addEventListener('mouseover',on_mouseover,false);
451 groupbox.addEventListener('mouseout',on_mouseout,false);
452 groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
453 groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
455 function on_click(ev){
457 if (block) return; block = true;
459 function post_c(v, unchanged) {
462 var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
466 f = input_cmd.match(/apply.?\("(.+?)",/)[1];
469 f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
475 obj.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v }; */
477 obj.changed[ hbox.id ] = true;
482 obj.summarize( obj[fm_type_plural] );
484 document.getElementById(caption.id).focus();
488 obj.error.standard_unexpected_error_alert('post_c',E);
491 var x; var c; eval( input_cmd );
493 util.widgets.remove_children(vbox);
494 util.widgets.remove_children(hbox);
495 util.widgets.remove_children(hbox2);
497 var apply = document.createElement('button');
498 apply.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.apply.label'));
499 apply.setAttribute('accesskey', $('catStrings').getString('staff.cat.copy_editor.apply.accesskey'));
500 hbox2.appendChild(apply);
501 apply.addEventListener('command',function() { c(x.value); },false);
502 var cancel = document.createElement('button');
503 cancel.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.cancel.label'));
504 cancel.addEventListener('command',function() { setTimeout( function() { obj.summarize( obj[fm_type_plural] ); obj.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
505 hbox2.appendChild(cancel);
506 setTimeout( function() { x.focus(); }, 0 );
509 obj.error.standard_unexpected_error_alert('render_input',E);
512 vbox.addEventListener('click',on_click, false);
513 hbox.addEventListener('click',on_click, false);
514 caption.addEventListener('click',on_click, false);
515 caption.addEventListener('keypress',function(ev) {
516 if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
518 caption.setAttribute('style','-moz-user-focus: normal');
519 caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
520 caption.setAttribute('onblur','this.setAttribute("class","")');
523 obj.error.sdump('D_ERROR',E + '\n');
527 /******************************************************************************************************/
528 /* save or store the updated fms as appropriate */
530 'editor_base_save' : function(update_method) {
532 var fm_type_plural = obj.fm_type_plural;
533 var fm_type= obj.fm_type;
536 if (obj.handle_update) {
538 //send fms to the update function
539 var r = obj.network.request(
542 [ ses(), obj[fm_type_plural] ]
544 if (typeof r.ilsevent != 'undefined') {
545 obj.error.standard_unexpected_error_alert('serial ' + fm_type + ' update',r);
547 alert($('serialStrings').getString('staff.serial.editor_base.handle_update.success'));
549 if (obj.trigger_refresh) {
550 obj.refresh_command();
555 /* FIXME -- revisit the return value here */
557 alert($('serialStrings').getString('staff.serial.editor_base.handle_update.error') + ' ' + js2JSON(E));
559 } else if (xul_param('in_modal',{'modal_xulG':true})) {
560 // TODO: this is to perhaps allow this editor to be called
561 // in a modal window, but is unfinished functionality
563 xulG[fm_type_plural] = obj[fm_type_plural];
564 update_modal_xulG(xulG);
566 obj.data['temp_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
567 obj.data.stash('temp_' + fm_type_plural);
570 if (xul_param('in_modal',{'modal_xulG':true})) {
574 obj.error.standard_unexpected_error_alert(fm_type + '_editor save',E);
578 /******************************************************************************************************/
579 'editor_base_save_attributes' : function() {
581 var fm_type = obj.fm_type;
583 JSAN.use('util.widgets'); JSAN.use('util.file'); var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
584 var what_to_save = {};
585 for (var i in obj[fm_type + '_editor_prefs']) {
586 what_to_save[i] = [];
587 for (var j in obj[fm_type + '_editor_prefs'][i]) what_to_save[i].push(j);
589 util.widgets.save_attributes(file, what_to_save );
593 dump('exiting serial/editor_base.js\n');