5 /******************************************************************************************************/
6 /* setup JSAN and some initial libraries */
8 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
9 if (typeof JSAN == 'undefined') { throw( "The JSAN library object is missing."); }
10 JSAN.errorLevel = "die"; // none, warn, or die
11 JSAN.addRepository('/xul/server/');
12 JSAN.use('util.error'); g.error = new util.error();
13 g.error.sdump('D_TRACE','my_init() for cat/copy_editor.xul');
15 JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
16 JSAN.use('util.network'); g.network = new util.network();
20 g.session = g.cgi.param('session') || g.cgi.param('ses');
21 g.docid = g.cgi.param('docid');
23 /******************************************************************************************************/
24 /* Get the copy ids from various sources */
27 if (g.cgi.param('copy_ids')) copy_ids = JSON2js( g.cgi.param('copy_ids') );
28 if (!copy_ids) copy_ids = [];
29 if (window.xulG && window.xulG.copy_ids) copy_ids = copy_ids.concat( window.xulG.copy_ids );
31 if (copy_ids.length > 0) g.copies = g.network.request(
32 api.FM_ACP_FLESHED_BATCH_RETRIEVE.app,
33 api.FM_ACP_FLESHED_BATCH_RETRIEVE.method,
37 /******************************************************************************************************/
38 /* And fleshed copies if any */
40 if (!g.copies) g.copies = [];
41 if (window.xulG && window.xulG.copies) g.copies = g.copies.concat( window.xulG.copies );
42 if (g.cgi.param('copies')) g.copies = g.copies.concat( JSON2js( g.cgi.param('copies') ) );
44 /******************************************************************************************************/
45 /* We try to retrieve callnumbers for existing copies, but for new copies, we rely on this */
47 if (window.xulG && window.xulG.callnumbers) g.callnumbers = window.xulG.callnumbers;
48 if (g.cgi.param('callnumbers')) g.callnumbers = JSON2js( g.cgi.param('callnumbers') );
50 /******************************************************************************************************/
51 /* Is the interface an editor or a viewer? */
53 if (g.cgi.param('edit') == '1') {
55 document.getElementById('caption').setAttribute('label','Copy Editor');
56 document.getElementById('nav').setAttribute('hidden','false');
59 /******************************************************************************************************/
60 /* Show the Record Details? */
62 document.getElementById('brief_display').setAttribute(
64 urls.XUL_BIB_BRIEF + '?docid=' + g.docid
67 document.getElementById('brief_display').setAttribute('hidden','true');
70 /******************************************************************************************************/
73 g.summarize( g.copies );
77 var err_msg = "!! This software has encountered an error. Please tell your friendly " +
78 "system administrator or software developer the following:\ncat/copy_editor.xul\n" + E + '\n';
79 try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
84 /******************************************************************************************************/
85 /* Apply a value to a specific field on all the copies being edited */
87 g.apply = function(field,value) {
88 g.error.sdump('D_TRACE','field = ' + field + ' value = ' + value + '\n');
89 for (var i = 0; i < g.copies.length; i++) {
90 var copy = g.copies[i];
92 copy[field]( value ); copy.ischanged('1');
99 /******************************************************************************************************/
100 /* These need data from the middle layer to render */
102 g.special_exception = {
103 'Call Number' : function(label,value) {
104 if (value>0) { /* an existing call number */
106 api.FM_ACN_RETRIEVE.app,
107 api.FM_ACN_RETRIEVE.method,
110 var cn = '??? id = ' + value;
112 cn = req.getResultObject().label();
114 g.error.sdump('D_ERROR','callnumber retrieve: ' + E);
116 label.setAttribute('value',cn);
119 } else { /* a yet to be created call number */
121 label.setAttribute('value',g.callnumbers[value]);
125 'Creator' : function(label,value) {
127 api.FM_AU_RETRIEVE_VIA_ID.app,
128 api.FM_AU_RETRIEVE_VIA_ID.method,
129 [ g.session, value ],
131 var p = '??? id = ' + value;
133 p = req.getResultObject();
134 p = p.card().barcode() + ' : ' + p.family_name();
137 g.error.sdump('D_ERROR','patron retrieve: ' + E);
139 label.setAttribute('value',p);
143 'Last Editor' : function(label,value) {
145 api.FM_AU_RETRIEVE_VIA_ID.app,
146 api.FM_AU_RETRIEVE_VIA_ID.method,
147 [ g.session, value ],
149 var p = '??? id = ' + value;
151 p = req.getResultObject();
152 p = p.card().barcode() + ' : ' + p.family_name();
155 g.error.sdump('D_ERROR','patron retrieve: ' + E);
157 label.setAttribute('value',p);
164 /******************************************************************************************************/
165 g.readonly_stat_cat_names = [];
166 g.editable_stat_cat_names = [];
168 /******************************************************************************************************/
169 /* These get show in the left panel */
171 g.left_pane_field_names = [
175 render: 'fm.barcode();',
181 render: 'fm.call_number();',
187 render: 'util.date.formatted_date( fm.create_date(), "%F");',
193 render: 'util.date.formatted_date( fm.edit_date(), "%F");',
199 /******************************************************************************************************/
200 /* These get shown in the right panel */
202 g.right_pane_field_names = [
206 render: 'fm.creator();',
212 render: 'fm.editor();',
218 render: 'fm.circ_as_type();',
219 input: 'x = document.createElement("textbox"); x.addEventListener("change",function(ev) { g.apply("circ_as_type",ev.target.value); }, false);',
223 "Circulation Library",
225 render: 'fm.circ_lib().shortname();',
226 input: '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("command",function(ev) { g.apply("circ_lib",ev.target.value); }, false);',
230 "Circulation Modifier",
232 render: 'fm.circ_modifier();',
233 input: 'x = document.createElement("textbox"); x.addEventListener("change",function(ev) { g.apply("circ_modifier",ev.target.value); }, false);',
239 render: 'fm.circulate() ? "Yes" : "No";',
240 input: 'x = util.widgets.make_menulist( [ [ "Yes", "1" ], [ "No", "0" ] ] ); x.addEventListener("command",function(ev) { g.apply("circulate",ev.target.value); }, false);',
246 render: 'fm.copy_number();',
247 input: 'x = document.createElement("textbox"); x.addEventListener("change",function(ev) { g.apply("copy_number",ev.target.value); }, false);',
253 render: 'fm.deposit() ? "Yes" : "No";',
254 input: 'x = util.widgets.make_menulist( [ [ "Yes", "1" ], [ "No", "0" ] ] ); x.addEventListener("command",function(ev) { g.apply("deposit",ev.target.value); }, false);',
260 render: 'util.money.sanitize( fm.deposit_amount() );',
261 input: 'x = document.createElement("textbox"); x.addEventListener("change",function(ev) { g.apply("deposit_amount",ev.target.value); }, false);',
267 render: 'switch(fm.fine_level()){ case 1: "Low"; break; case 2: "Normal"; break; case 3: "High"; break; }',
268 input: 'x = util.widgets.make_menulist( [ [ "Low", "1" ], [ "Normal", "2" ], [ "High", "3" ] ] ); x.addEventListener("command",function(ev) { g.apply("fine_level",ev.target.value); }, false);',
274 render: 'fm.holdable() ? "Yes" : "No";',
275 input: 'x = util.widgets.make_menulist( [ [ "Yes", "1" ], [ "No", "0" ] ] ); x.addEventListener("command",function(ev) { g.apply("holdable",ev.target.value); }, false);',
281 render: 'switch(fm.loan_duration()){ case 1: "Short"; break; case 2: "Normal"; break; case 3: "Long"; break; }',
282 input: 'x = util.widgets.make_menulist( [ [ "Short", "1" ], [ "Normal", "2" ], [ "Long", "3" ] ] ); x.addEventListener("command",function(ev) { g.apply("loan_duration",ev.target.value); }, false);',
289 render: 'fm.location().name();',
290 input: 'x = util.widgets.make_menulist( util.functional.map_list( g.data.list.acpl, function(obj) { return [ obj.name(), obj.id() ]; }).sort()); x.addEventListener("command",function(ev) { g.apply("location",ev.target.value); }, false);',
297 render: 'fm.opac_visible() ? "Yes" : "No";',
298 input: 'x = util.widgets.make_menulist( [ [ "Yes", "1" ], [ "No", "0" ] ] ); x.addEventListener("command",function(ev) { g.apply("opac_visible",ev.target.value); }, false);',
304 render: 'util.money.sanitize( fm.price() );',
305 input: 'x = document.createElement("textbox"); x.addEventListener("change",function(ev) { g.apply("deposit_amount",ev.target.value); }, false);',
311 render: 'fm.ref() ? "Yes" : "No";',
312 input: 'x = util.widgets.make_menulist( [ [ "Yes", "1" ], [ "No", "0" ] ] ); x.addEventListener("command",function(ev) { g.apply("ref",ev.target.value); }, false);',
318 render: 'fm.status().name();',
319 input: 'x = util.widgets.make_menulist( util.functional.map_list( g.data.list.ccs, function(obj) { return [ obj.name(), obj.id() ]; } ).sort() ); x.addEventListener("command",function(ev) { g.apply("status",ev.target.value); }, false);',
326 /******************************************************************************************************/
327 /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
329 g.summarize = function( copies ) {
330 /******************************************************************************************************/
333 JSAN.use('util.date'); JSAN.use('util.money');
335 g.field_names = g.left_pane_field_names;
336 g.field_names = g.field_names.concat( g.right_pane_field_names );
337 g.field_names = g.field_names.concat( g.editable_stat_cat_names );
338 g.field_names = g.field_names.concat( g.readonly_stat_cat_names );
340 /******************************************************************************************************/
341 /* Loop through the field names */
343 for (var i = 0; i < g.field_names.length; i++) {
345 var field_name = g.field_names[i][0];
346 var render = g.field_names[i][1].render;
347 g.summary[ field_name ] = {};
349 /******************************************************************************************************/
350 /* Loop through the copies */
352 for (var j = 0; j < copies.length; j++) {
355 var cmd = render || ('fm.' + field_name + '();');
358 /**********************************************************************************************/
359 /* Try to retrieve the value for this field for this copy */
364 g.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
366 if (typeof value == 'object' && value != null) {
367 alert('FIXME: field_name = ' + field_name + ' value = ' + js2JSON(value) + '\n');
370 /**********************************************************************************************/
371 /* Tally the count */
373 if (g.summary[ field_name ][ value ]) {
374 g.summary[ field_name ][ value ]++;
376 g.summary[ field_name ][ value ] = 1;
380 g.error.sdump('D_ERROR','summary = ' + js2JSON(g.summary) + '\n');
383 /******************************************************************************************************/
384 /* Display the summarized data and inputs for editing */
386 g.render = function() {
388 /******************************************************************************************************/
389 /* Library setup and clear any existing interface */
391 JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
393 var cns = document.getElementById('call_number_summary');
394 util.widgets.remove_children( cns );
395 var bcs = document.getElementById('barcode_summary');
396 util.widgets.remove_children( bcs );
397 var rp = document.getElementById('right_pane');
398 util.widgets.remove_children( rp );
400 /******************************************************************************************************/
401 /* Make the call number summary */
403 var grid = util.widgets.make_grid( [ { 'flex' : '1' } ] );
404 cns.appendChild(grid);
405 for (var i in g.summary['Call Number']) {
406 var cn_id = i; var count = g.summary['Call Number'][i];
407 var row = document.createElement('row'); grid.lastChild.appendChild(row);
408 var cn_label = document.createElement('label'); row.appendChild(cn_label);
409 g.special_exception['Call Number']( cn_label, cn_id );
410 var count_label = document.createElement('label'); row.appendChild(count_label);
411 var unit = count == 1 ? 'copy' : 'copies';
412 count_label.setAttribute('value',count + ' ' + unit);
415 /******************************************************************************************************/
416 /* List the copy barcodes */
418 for (var i in g.summary['Barcode']) {
420 var hbox = document.createElement('hbox'); bcs.appendChild(hbox);
421 var bc_label = document.createElement('label'); hbox.appendChild(bc_label);
422 bc_label.setAttribute('value',bc);
425 /******************************************************************************************************/
426 /* List the other non-editable fields in this pane */
428 var groupbox; var caption; var vbox; var grid; var rows;
429 for (var i = 0; i < g.left_pane_field_names.length; i++) {
431 var f = g.left_pane_field_names[i]; var fn = f[0];
432 if (fn == 'Call Number' || fn == 'Barcode') continue;
433 groupbox = document.createElement('groupbox'); bcs.parentNode.parentNode.appendChild(groupbox);
434 caption = document.createElement('caption'); groupbox.appendChild(caption);
435 caption.setAttribute('label',fn);
436 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
437 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
438 grid.setAttribute('flex','1');
439 rows = grid.lastChild;
442 /**************************************************************************************/
443 /* Loop through each value for the field */
445 for (var j in g.summary[fn]) {
446 var value = j; var count = g.summary[fn][j];
447 row = document.createElement('row'); rows.appendChild(row);
448 var label1 = document.createElement('label'); row.appendChild(label1);
449 if (g.special_exception[ fn ]) {
450 g.special_exception[ fn ]( label1, value );
452 label1.setAttribute('value',value);
454 var label2 = document.createElement('label'); row.appendChild(label2);
455 var unit = count == 1 ? 'copy' : 'copies';
456 label2.setAttribute('value',count + ' ' + unit);
458 var hbox = document.createElement('hbox');
459 vbox.appendChild(hbox);
461 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
465 /******************************************************************************************************/
466 /* Prepare the right panel, which is different for 1-copy view and multi-copy view */
468 if (g.copies.length == 1) {
470 /******************************************************************************************************/
471 /* 1-copy mode has a single groupbox and each field is a row on a grid */
473 var groupbox; var caption; var vbox; var grid; var rows;
474 groupbox = document.createElement('groupbox'); rp.appendChild(groupbox);
475 caption = document.createElement('caption'); groupbox.appendChild(caption);
476 caption.setAttribute('label','Fields');
477 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
478 grid = util.widgets.make_grid( [ {}, { 'flex' : 1 } ] ); vbox.appendChild(grid);
479 grid.setAttribute('flex','1');
480 rows = grid.lastChild;
482 /******************************************************************************************************/
483 /* Loop through the field names */
485 for (var i = 0; i < g.right_pane_field_names.length; i++) {
487 var f = g.right_pane_field_names[i]; var fn = f[0];
490 /**************************************************************************************/
491 /* Loop through each value for the field */
493 for (var j in g.summary[fn]) {
494 var value = j; var count = g.summary[fn][j];
495 row = document.createElement('row'); rows.appendChild(row);
496 var label0 = document.createElement('label'); row.appendChild(label0);
497 label0.setAttribute('value',fn);
498 label0.setAttribute('style','font-weight: bold');
499 var label1 = document.createElement('label'); row.appendChild(label1);
500 if (g.special_exception[ fn ]) {
501 g.special_exception[ fn ]( label1, value );
503 label1.setAttribute('value',value);
508 /**************************************************************************************/
509 /* Render the input widget */
511 var hbox = document.createElement('hbox');
512 row.setAttribute('style','border-bottom: dotted black thin');
513 row.appendChild(hbox);
514 if (f[1].input && g.edit) {
516 var spacer = document.createElement('spacer'); hbox.appendChild(spacer);
517 spacer.setAttribute('flex','1');
518 var x; eval( f[1].input );
519 if (x) hbox.appendChild(x);
522 g.error.sdump('D_ERROR',E + '\n');
527 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
533 /******************************************************************************************************/
534 /* multi-copy mode has a groupbox for each field */
536 var groupbox; var caption; var vbox; var grid; var rows;
538 /******************************************************************************************************/
539 /* Loop through the field names */
541 for (var i = 0; i < g.right_pane_field_names.length; i++) {
543 var f = g.right_pane_field_names[i]; var fn = f[0];
544 groupbox = document.createElement('groupbox'); rp.appendChild(groupbox);
545 caption = document.createElement('caption'); groupbox.appendChild(caption);
546 caption.setAttribute('label',fn);
547 vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
548 grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
549 grid.setAttribute('flex','1');
550 rows = grid.lastChild;
553 /**************************************************************************************/
554 /* Loop through each value for the field */
556 for (var j in g.summary[fn]) {
557 var value = j; var count = g.summary[fn][j];
558 row = document.createElement('row'); rows.appendChild(row);
559 var label1 = document.createElement('label'); row.appendChild(label1);
560 if (g.special_exception[ fn ]) {
561 g.special_exception[ fn ]( label1, value );
563 label1.setAttribute('value',value);
565 var label2 = document.createElement('label'); row.appendChild(label2);
566 var unit = count == 1 ? 'copy' : 'copies';
567 label2.setAttribute('value',count + ' ' + unit);
570 var hbox = document.createElement('hbox');
571 vbox.appendChild(hbox);
573 /**************************************************************************************/
574 /* Render the input widget */
576 if (f[1].input && g.edit) {
578 var spacer = document.createElement('spacer'); hbox.appendChild(spacer);
579 spacer.setAttribute('flex','1');
580 var x; eval( f[1].input );
581 if (x) hbox.appendChild(x);
584 g.error.sdump('D_ERROR',E + '\n');
588 g.error.sdump('D_ERROR','copy editor: ' + E + '\n');
594 /******************************************************************************************************/
595 /* store the copies in the global xpcom stash */
597 g.stash_and_close = function() {
598 g.data.temp = js2JSON( g.copies );
599 g.error.sdump('D_CAT','in modal window, g.data.temp = \n' + g.data.temp + '\n');
600 g.data.stash('temp');