]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/xul/staff_client/server/cat/volume_copy_creator.js
css hooks so we can hide class, affix, and part columns in volume creator/editor...
[Evergreen.git] / Open-ILS / xul / staff_client / server / cat / volume_copy_creator.js
1 const g_max_copies_that_can_be_added_at_a_time_per_volume = 999;
2 const rel_vert_pos_volume_count = 1;
3 const rel_vert_pos_call_number_classification = 2;
4 const rel_vert_pos_call_number_prefix = 3;
5 const rel_vert_pos_call_number = 4;
6 const rel_vert_pos_call_number_suffix = 5;
7 const rel_vert_pos_copy_count = 6;
8 const rel_vert_pos_barcode = 7;
9 const rel_vert_pos_part = 8;
10 const update_timer = 1000;
11 var g = {};
12 g.use_defaults = true;
13 g.acn_map = {}; // store retrieved acn objects here by id
14
15 function my_init() {
16     try {
17
18         /***********************************************************************************************************/
19         /* Initial setup */
20
21         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
22         if (typeof JSAN == 'undefined') { throw( $("commonStrings").getString('common.jsan.missing') ); }
23         JSAN.errorLevel = "die"; // none, warn, or die
24         JSAN.addRepository('/xul/server/');
25         JSAN.use('util.error'); g.error = new util.error();
26         g.error.sdump('D_TRACE','my_init() for cat/volume_copy_creator.xul');
27
28         JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
29         JSAN.use('util.widgets'); JSAN.use('util.functional'); JSAN.use('util.fm_utils');
30
31         JSAN.use('util.network'); g.network = new util.network();
32
33         g.refresh = xul_param('onrefresh');
34
35         if (xulG.unified_interface) {
36             $('non_unified_buttons').hidden = true;
37             xulG.reset_batch_menus = function() {
38                 $('batch_class_menulist').value = false;
39                 util.widgets.dispatch('command',$('batch_class_menulist'));
40                 $('batch_prefix_menulist').value = false;
41                 util.widgets.dispatch('command',$('batch_prefix_menulist'));
42                 $('batch_suffix_menulist').value = false;
43                 util.widgets.dispatch('command',$('batch_suffix_menulist'));
44             }
45             xulG.apply_template_to_batch = function(id,value) {
46                 if (!isNaN(Number(value))) {
47                     $(id).value = value;
48                     util.widgets.dispatch('command',$(id));
49                 }
50                 setTimeout(
51                     function() {
52                         // TODO:  Only apply batch to columns that haven't been adjusted manually?
53                         util.widgets.dispatch('command',$('batch_button'));
54                     },0
55                 );
56             }
57         } else {
58             $('Create').hidden = true;
59         }
60
61         /***********************************************************************************************************/
62         /* Am I adding just copies or copies and volumes?  Or am I rebarcoding existing copies? */
63
64         // g.copy_shortcut = { ou_id : { callnumber_composite_key : callnumber_id, callnumber_label : callnumber_id, ... }, ... }
65         g.copy_shortcut = xul_param('copy_shortcut');
66         // g.existing_copies = [ copy1, copy2, ... ]
67         g.existing_copies = xul_param('existing_copies') || [];
68
69         function set_attr(id,attr,msgcat_key) {
70             var x = $(id);
71             if (x) {
72                 x.setAttribute(
73                     attr,
74                     $('catStrings').getString(msgcat_key)
75                 );
76             }
77         }
78         if (g.existing_copies.length > 0) {
79             set_attr('EditThenCreate','label','staff.cat.volume_copy_creator.edit_then_rebarcode.btn.label');
80             set_attr('EditThenCreate','accesskey','staff.cat.volume_copy_creator.edit_then_rebarcode.btn.accesskey');
81             set_attr('CreateWithDefaults','label','staff.cat.volume_copy_creator.rebarcode.btn.label');
82             set_attr('CreateWithDefaults','accesskey','staff.cat.volume_copy_creator.rebarcode.btn.accesskey');
83             set_attr('Create','label','staff.cat.volume_copy_creator.rebarcode.btn.label');
84             set_attr('Create','accesskey','staff.cat.volume_copy_creator.rebarcode.btn.accesskey');
85         } else {
86             set_attr('EditThenCreate','label','staff.cat.volume_copy_creator.edit_then_create.btn.label');
87             set_attr('EditThenCreate','accesskey','staff.cat.volume_copy_creator.edit_then_create.btn.accesskey');
88             set_attr('CreateWithDefaults','label','staff.cat.volume_copy_creator.create_with_defaults.btn.label');
89             set_attr('CreateWithDefaults','accesskey','staff.cat.volume_copy_creator.create_with_defaults.btn.accesskey');
90             set_attr('Create','label','staff.cat.volume_copy_creator.create.btn.label');
91             set_attr('Create','accesskey','staff.cat.volume_copy_creator.create.btn.accesskey');
92         }
93
94         //g.error.sdump('D_ERROR','location.href = ' + location.href + '\n\ncopy_short cut = ' + g.copy_shortcut + '\n\nou_ids = ' + xul_param('ou_ids'));
95
96         var ou_ids = xul_param('ou_ids',{'concat' : true}) || [];
97
98         // Get the default callnumber classification scheme from OU settings
99         dojo.require('fieldmapper.OrgUtils');
100         //fieldmapper.aou.fetchOrgSettingDefault(ses('ws_ou'), 'cat.default_classification_scheme');
101         g.label_class = g.data.hash.aous['cat.default_classification_scheme'];
102
103         // Assign a default value if none was returned
104         if (!g.label_class) {
105             g.label_class = g.data.list.acnc[0].id();
106         }
107
108         /***********************************************************************************************************/
109         /* If we're passed existing_copies, rig up a copy_shortcut object to leverage existing code for rendering the volume labels, etc.
110          * Also make a lookup object for existing copies keyed on org id and callnumber composite key, and another keyed on copy id. */
111
112         // g.org_label_existing_copy_map = { ou_id : { callnumber_composite_key : [ copy1, copy2, ... ] }, ... }
113         g.org_label_existing_copy_map = {};
114         // g.id_copy_map = { acp_id : acp, ... }
115         g.id_copy_map = {};
116         for (var i = 0; i < g.existing_copies.length; i++) {
117             if (! g.copy_shortcut) { g.copy_shortcut = {}; }
118             var copy = g.existing_copies[i];
119             g.id_copy_map[ copy.id() ] = copy;
120             var call_number = copy.call_number();
121             g.doc_id = call_number.record();
122             if (!g.copy_shortcut[ call_number.owning_lib() ]) {
123                 ou_ids.push( call_number.owning_lib() );
124                 g.copy_shortcut[ call_number.owning_lib() ] = {};
125                 g.org_label_existing_copy_map[ call_number.owning_lib() ] = {};
126             }
127             var acnc_id = call_number.label_class() ?
128                 ( typeof call_number.label_class() == 'object' ? call_number.label_class().id() : call_number.label_class() )
129                 : g.label_class;
130             var acnp_id = typeof call_number.prefix() == 'object' ? call_number.prefix().id() : call_number.prefix();
131             var acns_id = typeof call_number.suffix() == 'object' ? call_number.suffix().id() : call_number.suffix();
132             var callnumber_composite_key = acnc_id + ':' + acnp_id + ':' + call_number.label() + ':' + acns_id;
133             g.copy_shortcut[ call_number.owning_lib() ][ callnumber_composite_key ] = call_number.id();
134             if (! g.org_label_existing_copy_map[ call_number.owning_lib() ][ callnumber_composite_key ]) {
135                 g.org_label_existing_copy_map[ call_number.owning_lib() ][ callnumber_composite_key ] = [];
136             }
137             g.org_label_existing_copy_map[ call_number.owning_lib() ][ callnumber_composite_key ].push( copy );
138         }
139
140         /***********************************************************************************************************/
141         /* What record am I dealing with?  */
142
143         g.doc_id = g.doc_id || xul_param('doc_id');
144         if (! g.doc_id) {
145             alert('Error in volume_copy_creator.js, g.doc_id not valid');
146             window.close(); return;
147         }
148         var sb = document.getElementById('summary_box'); while(sb.firstChild) sb.removeChild(sb.lastChild);
149         var summary = document.createElement('iframe'); sb.appendChild(summary);
150         summary.setAttribute('src',urls.XUL_BIB_BRIEF);
151         summary.setAttribute('flex','1');
152         get_contentWindow(summary).xulG = { 'docid' : g.doc_id };
153
154         /***********************************************************************************************************/
155         /* Setup pcrud and fetch the monographic parts for this bib */
156
157         dojo.require('openils.PermaCrud');
158         g.pcrud = new openils.PermaCrud({'authtoken':ses()});
159         g.parts = g.pcrud.search('bmp',{'record':g.doc_id},{'order_by': { 'bmp' : 'label_sortkey' } });
160         g.parts_hash = util.functional.convert_object_list_to_hash( g.parts );
161
162         /***********************************************************************************************************/
163         /* For the batch drop downs */
164
165         g.list_classes();
166         g.list_callnumbers(g.doc_id, g.label_class);
167         g.render_batch_button();
168
169         /***********************************************************************************************************/
170         /* render the orgs and volumes/input */
171
172         var rows = document.getElementById('rows');
173
174         g.ou_ids = [];
175         for (var i = 0; i < ou_ids.length; i++) {
176             try {
177                 var org = g.data.hash.aou[ ou_ids[i] ];
178                 if ( get_bool( g.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) {
179                     var row = document.createElement('row'); rows.appendChild(row); row.setAttribute('ou_id',ou_ids[i]);
180                     g.render_library_label(row,ou_ids[i]);
181                     g.render_volume_count_entry( row, ou_ids[i] );
182                     g.ou_ids.push( ou_ids[i] );
183                 }
184             } catch(E) {
185                 g.error.sdump('D_ERROR',E);
186             }
187         }
188         g.common_ancestor_ou_ids = util.fm_utils.find_common_aou_ancestors( g.ou_ids ).reverse();
189
190         /***********************************************************************************************************/
191         /* For the remainder batch drop downs */
192
193         g.list_prefixes();
194         g.list_suffixes();
195
196         /************/
197
198         g.load_prefs();
199
200         if (g.existing_copies.length > 0) {
201             g.gather_copies_soon();
202         }
203
204         try {
205             $('main').parentNode.scrollLeft = 9999;
206         } catch(E) {
207             dump('Error in volume_copy_creator.js, my_init(), trying to auto-scroll to the far right: ' + E + '\n');
208         }
209
210     } catch(E) {
211         var err_msg = $("commonStrings").getFormattedString('common.exception', ['cat/volume_copy_creator.js', E]);
212         try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
213         alert(err_msg);
214     }
215 }
216
217 g.render_library_label = function(row,ou_id) {
218     dump('g.render_library_label(row='+row+',ou_id='+ou_id+')\n');
219     var label = document.createElement('label'); row.appendChild(label);
220     label.setAttribute('ou_id',ou_id);
221     label.setAttribute('value',g.data.hash.aou[ ou_id ].shortname());
222 }
223
224 g.render_volume_count_entry = function(row,ou_id) {
225     dump('g.render_volume_count_entry(row='+row+',ou_id='+ou_id+')\n');
226     var hb = document.createElement('vbox'); row.appendChild(hb);
227     var tb = document.createElement('textbox'); hb.appendChild(tb);
228     if (g.use_defaults) {
229         tb.value = 1; // default to 1 volume per org
230         tb.select();
231     }
232     tb.setAttribute('ou_id',ou_id); tb.setAttribute('size','3'); tb.setAttribute('cols','3');
233     tb.setAttribute('rel_vert_pos',rel_vert_pos_volume_count);
234     if ( (!g.copy_shortcut) && (!g.last_focus) ) { tb.focus(); g.last_focus = tb; }
235     var node;
236     function render_copy_count_entry(ev) {
237         dump('\t\trender_copy_count_entry()\n');
238         if (ev.target.disabled) return;
239         if (! isNaN( Number( ev.target.value) ) ) {
240             if ( Number( ev.target.value ) > g_max_copies_that_can_be_added_at_a_time_per_volume ) {
241                 g.error.yns_alert($("catStrings").getFormattedString('staff.cat.volume_copy_creator.render_volume_count_entry.message', [g_max_copies_that_can_be_added_at_a_time_per_volume]),
242                     $("catStrings").getString('staff.cat.volume_copy_creator.render_volume_count_entry.title'),
243                     $("catStrings").getString('staff.cat.volume_copy_creator.render_volume_count_entry.ok_label'),null,null,'');
244                 return;
245             }
246             if (node) { row.removeChild(node); node = null; }
247             node = g.render_callnumber_copy_count_entry(row,ou_id,ev.target.value);
248         }
249     }
250     util.widgets.apply_vertical_tab_on_enter_handler(
251         tb,
252         function() { render_copy_count_entry({'target':tb}); setTimeout(function(){util.widgets.vertical_tab(tb);},0); },
253         g.delay_gather_copies_soon
254     );
255     tb.addEventListener( 'change', render_copy_count_entry, false);
256     tb.addEventListener( 'change', g.gather_copies_soon, false);
257     tb.addEventListener( 'focus', function(ev) { g.last_focus = ev.target; }, false );
258     setTimeout(
259         function() {
260             try {
261                 if (g.copy_shortcut) {
262                     dump('\t\tg.render_volume_count_entry, using g.copy_shortcut\n');
263                     JSAN.use('util.functional');
264                     tb.value = util.functional.map_object_to_list(
265                         g.copy_shortcut[ou_id],
266                         function(o,i) {
267                             return g.copy_shortcut[ou_id][i];
268                         }
269                     ).length;
270                     dump('\t\tnumber of volumes = ' + tb.value + '\n');
271                     render_copy_count_entry({'target':tb});
272                     tb.disabled = true;
273                 } else if (tb.value) {
274                     dump('\t\tg.render_volume_count_entry, number of volumes = ' + tb.value + '\n');
275                     // since we're now supplying a default
276                     render_copy_count_entry({'target':tb});
277                     setTimeout(
278                         function() {
279                             util.widgets.vertical_tab(tb);
280                         }, 0
281                     );
282                 }
283             } catch(E) {
284                 alert(E);
285             }
286         }, 0
287     );
288 }
289
290 g.render_callnumber_copy_count_entry = function(row,ou_id,count) {
291     dump('g.render_call_number_copy_count_entry(row='+row+',ou_id='+ou_id+',count='+count+')\n');
292     var grid = util.widgets.make_grid( [ {}, {} ] ); row.appendChild(grid);
293     grid.setAttribute('flex','1');
294     grid.setAttribute('ou_id',ou_id);
295     var rows = grid.lastChild;
296     var r = document.createElement('row'); rows.appendChild( r );
297     var x = document.createElement('label'); r.appendChild(x);
298         x.setAttribute('value', $("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.classification'));
299         x.setAttribute('style','font-weight: bold');
300         x.setAttribute('class','cn_class');
301     x = document.createElement('label'); r.appendChild(x);
302         x.setAttribute('value', $("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.prefix'));
303         x.setAttribute('style','font-weight: bold');
304         x.setAttribute('class','cn_prefix');
305     x = document.createElement('label'); r.appendChild(x);
306         x.setAttribute('value', $("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.call_nums'));
307         x.setAttribute('style','font-weight: bold');
308     x = document.createElement('label'); r.appendChild(x);
309         x.setAttribute('value', $("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.suffix'));
310         x.setAttribute('style','font-weight: bold');
311         x.setAttribute('class','cn_suffix');
312     x = document.createElement('label'); r.appendChild(x);
313         x.setAttribute('value',$("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.num_of_copies'));
314         x.setAttribute('style','font-weight: bold');
315     x = document.createElement('label'); r.appendChild(x);
316         x.setAttribute('value',$("catStrings").getString('staff.cat.volume_copy_creator.render_callnumber_copy_count_entry.barcodes_and_parts'));
317         x.setAttribute('style','font-weight: bold');
318
319     function handle_change_precipitating_barcode_rendering(
320         callnumber_composite_key,
321         number_of_copies_column_textbox,
322         barcode_column_box
323     ) {
324         dump('handle_change_precipitating_barcode_rendering('+callnumber_composite_key+',number_of_copies = '+number_of_copies_column_textbox.value+','+ barcode_column_box + ')\n');
325
326         if (isNaN( Number( number_of_copies_column_textbox.value ) )) {
327             dump('1:handle_change_precipitating_barcode_rendering early return\n');
328             return;
329         }
330         if ( Number( number_of_copies_column_textbox.value ) > g_max_copies_that_can_be_added_at_a_time_per_volume ) {
331             g.error.yns_alert($("catStrings").getFormattedString('staff.cat.volume_copy_creator.render_volume_count_entry.message', [g_max_copies_that_can_be_added_at_a_time_per_volume]),
332                 $("catStrings").getString('staff.cat.volume_copy_creator.render_volume_count_entry.title'),
333                 $("catStrings").getString('staff.cat.volume_copy_creator.render_volume_count_entry.ok_label'),null,null,'');
334             return;
335         }
336
337         while (barcode_column_box.childNodes.length > Number(number_of_copies_column_textbox.value)) {
338             barcode_column_box.removeChild( barcode_column_box.lastChild );
339         }
340         g.render_barcode_entry(
341             barcode_column_box,
342             callnumber_composite_key,
343             Number(number_of_copies_column_textbox.value),
344             ou_id
345         );
346
347         if (! xulG.unified_interface) {
348             document.getElementById("EditThenCreate").disabled = false;
349             document.getElementById("CreateWithDefaults").disabled = false;
350         } else {
351             document.getElementById("Create").disabled = false;
352         }
353     }
354
355     function handle_change_to_callnumber_data(ev) {
356         dump('handle_change_to_callnumber_data\n');
357         var _call_number_column_textbox = ev.target;
358         var _call_number_column_box = _call_number_column_textbox.parentNode;
359
360         var _classification_column_box = _call_number_column_box.previousSibling.previousSibling; /* two over to the left */
361         var _classification_column_menulist = _classification_column_box.firstChild;
362
363         var _prefix_column_box = _call_number_column_box.previousSibling; /* one over to the left */
364         var _prefix_column_menulist = _prefix_column_box.firstChild;
365
366         var _suffix_column_box = _call_number_column_box.nextSibling; /* one over to the right */
367         var _suffix_column_menulist = _suffix_column_box.firstChild;
368
369         var _number_of_copies_column_box = _call_number_column_box.nextSibling.nextSibling; /* two over to the right */
370         var _number_of_copies_column_textbox = _number_of_copies_column_box.firstChild;
371
372         var _barcode_column_box = _number_of_copies_column_box.nextSibling;
373
374         var acn_label = _call_number_column_textbox.value;
375         var acnc_id = _classification_column_menulist.value;
376         var acnp_id = _prefix_column_menulist.value;
377         var acns_id = _suffix_column_menulist.value;
378         var callnumber_composite_key = acnc_id + ':' + acnp_id + ':' + acn_label + ':' + acns_id;
379         dump('\tcomposite_key = ' + callnumber_composite_key + '\n');
380
381         _call_number_column_textbox.setAttribute('callkey',callnumber_composite_key);
382         _call_number_column_textbox.setAttribute('acnc_id',acnc_id);
383         _call_number_column_textbox.setAttribute('acnp_id',acnp_id);
384         _call_number_column_textbox.setAttribute('acns_id',acns_id);
385
386         handle_change_precipitating_barcode_rendering(
387             callnumber_composite_key,
388             _number_of_copies_column_textbox,
389             _barcode_column_box
390         );
391     }
392
393     function handle_change_number_of_copies_column_textbox(ev) {
394         dump('handle_change_number_of_copies_column_textbox\n');
395         var _number_of_copies_column_textbox = ev.target;
396         var _number_of_copies_column_box = _number_of_copies_column_textbox.parentNode;
397         var _call_number_column_box = _number_of_copies_column_box.previousSibling.previousSibling; /* two over */
398         var _call_number_column_textbox = _call_number_column_box.firstChild;
399         handle_change_to_callnumber_data({'target':_call_number_column_textbox}); // let this guy do the work
400     }
401
402     for (var i = 0; i < count; i++) {
403         var r = document.createElement('row'); rows.appendChild(r);
404
405             /**** CLASSIFICATION COLUMN ****/
406             var classification_column_box = document.createElement('vbox');
407             classification_column_box.setAttribute('class','cn_class');
408             r.appendChild(classification_column_box);
409
410             /**** PREFIX COLUMN ****/
411             var prefix_column_box = document.createElement('vbox');
412             prefix_column_box.setAttribute('class','cn_prefix');
413             r.appendChild(prefix_column_box);
414
415             /**** CALLNUMBER COLUMN ****/
416             var call_number_column_box = document.createElement('vbox');
417             r.appendChild(call_number_column_box);
418                 var call_number_column_textbox = document.createElement('textbox');
419                 call_number_column_box.appendChild(call_number_column_textbox);
420                     if (g.use_defaults && $('marc_cn').firstChild) {
421                         // default to first real value from batch callnumber menu
422                         var menupopup = $('marc_cn').firstChild.firstChild;
423                         if (menupopup.childNodes.length > 1) {
424                             call_number_column_textbox.value = menupopup.childNodes[1].getAttribute('label');
425                             call_number_column_textbox.select();
426                         }
427                     }
428                     call_number_column_textbox.setAttribute('rel_vert_pos',rel_vert_pos_call_number);
429                     call_number_column_textbox.setAttribute('ou_id',ou_id);
430                     util.widgets.apply_vertical_tab_on_enter_handler(
431                         call_number_column_textbox,
432                         function() {
433                             handle_change_to_callnumber_data({'target':call_number_column_textbox});
434                             setTimeout(
435                                 function(){
436                                     util.widgets.vertical_tab(call_number_column_textbox);
437                                 },0
438                             );
439                         },
440                         g.delay_gather_copies_soon
441                     );
442                     call_number_column_textbox.addEventListener( 'change', handle_change_to_callnumber_data, false);
443                     call_number_column_textbox.addEventListener( 'change', g.gather_copies_soon, false);
444                     call_number_column_textbox.addEventListener( 'focus', function(ev) { g.last_focus = ev.target; }, false );
445
446                     /**** CLASSIFICATION COLUMN revisited ****/
447                     var classification_column_menulist = g.render_class_menu(call_number_column_textbox);
448                     classification_column_menulist.addEventListener(
449                         'command',
450                         function() {
451                             handle_change_to_callnumber_data({'target':call_number_column_textbox});
452                         }
453                         ,false
454                     );
455                     classification_column_box.appendChild(classification_column_menulist);
456                     classification_column_menulist.value = g.label_class;
457
458                     /**** PREFIX COLUMN revisited ****/
459                     var prefix_column_menulist = g.render_prefix_menu(call_number_column_textbox);
460                     prefix_column_menulist.addEventListener(
461                         'command',
462                         function() {
463                             handle_change_to_callnumber_data({'target':call_number_column_textbox});
464                         }
465                         ,false
466                     );
467
468                     prefix_column_box.appendChild(prefix_column_menulist);
469
470             /**** SUFFIX COLUMN ****/
471             var suffix_column_box = document.createElement('vbox');
472             suffix_column_box.setAttribute('class','cn_suffix');
473             r.appendChild(suffix_column_box);
474                 var suffix_column_menulist = g.render_suffix_menu(call_number_column_textbox);
475                 suffix_column_menulist.addEventListener(
476                     'command',
477                     function() {
478                         handle_change_to_callnumber_data({'target':call_number_column_textbox});
479                     }
480                     ,false
481                 );
482                 suffix_column_box.appendChild(suffix_column_menulist);
483
484             /**** NUMBER OF COPIES COLUMN ****/
485             var number_of_copies_column_box = document.createElement('vbox');
486             r.appendChild(number_of_copies_column_box);
487                 var number_of_copies_column_textbox = document.createElement('textbox');
488                 number_of_copies_column_box.appendChild(number_of_copies_column_textbox);
489                     if (g.use_defaults) {
490                         // default to one copy per call number
491                         number_of_copies_column_textbox.value = 1;
492                         number_of_copies_column_textbox.select();
493                     }
494                     number_of_copies_column_textbox.setAttribute('size','3'); number_of_copies_column_textbox.setAttribute('cols','3');
495                     number_of_copies_column_textbox.setAttribute('rel_vert_pos',rel_vert_pos_copy_count);
496                     number_of_copies_column_textbox.setAttribute('ou_id',ou_id);
497                     util.widgets.apply_vertical_tab_on_enter_handler(
498                         number_of_copies_column_textbox,
499                         function() {
500                             handle_change_number_of_copies_column_textbox({'target':number_of_copies_column_textbox});
501                             setTimeout(
502                                 function(){
503                                     util.widgets.vertical_tab(number_of_copies_column_textbox);
504                                 },0
505                             );
506                         },
507                         g.delay_gather_copies_soon
508                     );
509                     number_of_copies_column_textbox.addEventListener( 'change', handle_change_number_of_copies_column_textbox, false);
510                     number_of_copies_column_textbox.addEventListener( 'change', g.gather_copies_soon, false);
511                     number_of_copies_column_textbox.addEventListener( 'focus', function(ev) { g.last_focus = ev.target; }, false );
512                     if ( !g.last_focus ) { number_of_copies_column_textbox.focus(); g.last_focus = number_of_copies_column_textbox; }
513
514             /**** BARCODE COLUMN ****/
515             var barcode_column_box = document.createElement('vbox');
516             r.appendChild(barcode_column_box);
517
518         setTimeout(
519             function(idx,call_number_column_textbox,number_of_copies_column_textbox){
520                 return function() {
521                     try {
522                         JSAN.use('util.functional');
523                         if (g.copy_shortcut) {
524                             dump('\t\tg.render_call_number_copy_count_entry() using g.copy_shortcut\n');
525                             var callnumber_composite_key = util.functional.map_object_to_list(
526                                 g.copy_shortcut[ou_id],
527                                 function(o,i) {
528                                     return i;
529                                 }
530                             )[idx];
531                             dump('\tcallnumber_composite_key = ' + callnumber_composite_key + '\n');
532                             if (g.org_label_existing_copy_map[ou_id]) {
533                                 var num_of_copies = g.org_label_existing_copy_map[ou_id][callnumber_composite_key].length;
534                                 if (num_of_copies>0) {
535                                     number_of_copies_column_textbox.value = num_of_copies;
536                                     number_of_copies_column_textbox.disabled = true;
537                                 }
538                             }
539                             var acn_label = callnumber_composite_key.split(/:/).slice(2,-1).join(':');
540                             var acnc_id = callnumber_composite_key.split(/:/)[0];
541                             var acnp_id = callnumber_composite_key.split(/:/)[1];
542                             var acns_id = callnumber_composite_key.split(/:/).slice(-1)[0];
543                             call_number_column_textbox.value = acn_label;
544                             classification_column_menulist.value = acnc_id;
545                             prefix_column_menulist.value = acnp_id;
546                             suffix_column_menulist.value = acns_id;
547                             dump('\tacn_label = ' + acn_label + ' acnc_id = ' + acnc_id + ' acnp_id = ' + acnp_id + ' acns_id = ' + acns_id + '\n');
548                             handle_change_to_callnumber_data({'target':call_number_column_textbox});
549                         } else {
550                             dump('\t\tg.render_call_number_copy_count_entry() using defaults\n');
551
552                             // if we're providing defaults, keep on rendering
553                             if (call_number_column_textbox.value) {
554                                 util.widgets.dispatch('change',call_number_column_textbox);
555                             }
556                             if (number_of_copies_column_textbox.value) {
557                                 util.widgets.dispatch('change',number_of_copies_column_textbox);
558                             }
559                         }
560                     } catch(E) {
561                         alert(E);
562                     }
563                 }
564             }(i,call_number_column_textbox,number_of_copies_column_textbox),0
565         );
566     }
567
568     return grid;
569 }
570
571 g.render_part_menu = function(barcode_tb) {
572     var hbox = document.createElement('hbox');
573     var menulist = document.createElement('menulist');
574         menulist.setAttribute('editable','true');
575         hbox.appendChild(menulist);
576     var button = document.createElement('button');
577         button.setAttribute('label',$('catStrings').getString('staff.cat.volume_copy_creator.create_part.btn.label'));
578         button.hidden = true;
579         hbox.appendChild(button);
580
581     var menupopup = document.createElement('menupopup');
582         menulist.appendChild(menupopup);
583         g.render_part_menuitems(menupopup);
584
585     button.addEventListener(
586         'command',
587         function(ev) {
588             var new_part = new bmp();
589                 new_part.isnew(1);
590                 new_part.label(menulist.value);
591                 new_part.record(g.doc_id);
592             g.pcrud.create(new_part, {
593                 "oncomplete": function (r, objs) {
594                     var db_part = objs[0];
595                     if (!db_part) { return; }
596                     g.parts.push( db_part );
597                     g.parts_hash[ db_part.id() ] = db_part;
598                     g.render_part_menuitems(menupopup);
599                     if (menulist.selectedItem) {
600                         barcode_tb.setAttribute('bmp_id',menulist.selectedItem.value);
601                         button.hidden = true;
602                     }
603                     g.gather_copies_soon();
604                 }
605             });
606         },
607         false
608     );
609
610     menulist.addEventListener(
611         'change',
612         function(ev) {
613             if (! ev.target.selectedItem) {
614                 button.hidden = false;
615             }
616         },
617         false
618     );
619     menulist.addEventListener('change',g.gather_copies_soon,false);
620     menulist.addEventListener(
621         'command',
622         function(ev) {
623             barcode_tb.setAttribute('bmp_id',menulist.selectedItem.value);
624             button.hidden = true;
625         },
626         false
627     );
628     menulist.addEventListener('command',g.gather_copies_soon,false);
629
630     return hbox;
631 }
632
633 g.render_part_menuitems = function(menupopup) {
634     util.widgets.remove_children(menupopup);
635     var menuitem = document.createElement('menuitem');
636     menuitem.setAttribute('label','');
637     menuitem.setAttribute('value','');
638     menupopup.appendChild(menuitem);
639     for (var i = 0; i < g.parts.length; i++) {
640         var menuitem = document.createElement('menuitem');
641         menuitem.setAttribute('label',g.parts[i].label());
642         menuitem.setAttribute('value',g.parts[i].id());
643         menupopup.appendChild(menuitem);
644     }
645
646 }
647
648 g.render_barcode_entry = function(node,callnumber_composite_key,count,ou_id) {
649     try {
650         dump('g.render_barcode_entry(node,'+callnumber_composite_key+',count='+count+',ou_id='+ou_id+'\n');
651         function ready_to_create(ev) {
652             if (! xulG.unified_interface) {
653                 document.getElementById("EditThenCreate").disabled = false;
654                 document.getElementById("CreateWithDefaults").disabled = false;
655             } else {
656                 document.getElementById("Create").disabled = false;
657             }
658         }
659
660         JSAN.use('util.barcode');
661
662         for (var i = 0; i < count; i++) {
663             var tb_part_box;
664             var tb;
665             var part_menu;
666             var set_handlers = false;
667             if (typeof node.childNodes[i] == 'undefined') {
668                 tb_part_box = document.createElement('hbox');
669                 node.appendChild(tb_part_box);
670                 tb = document.createElement('textbox');
671                 tb_part_box.appendChild(tb);
672                 part_menu = g.render_part_menu(tb);
673                 part_menu.setAttribute('class','part_column');
674                 tb_part_box.appendChild(part_menu);
675                 set_handlers = true;
676             } else {
677                 tb_part_box = node.childNodes[i];
678                 tb = tb_part_box.firstChild;
679                 part_menu = tb_part_box.lastChild;
680             }
681             tb.setAttribute('ou_id',ou_id);
682             tb.setAttribute('callkey',callnumber_composite_key);
683             tb.setAttribute('rel_vert_pos',rel_vert_pos_barcode);
684             part_menu.firstChild.setAttribute('rel_vert_pos',rel_vert_pos_part);
685             if (!tb.value && g.org_label_existing_copy_map[ ou_id ]) {
686                 tb.value = g.org_label_existing_copy_map[ ou_id ][ callnumber_composite_key ][i].barcode();
687                 tb.setAttribute('acp_id', g.org_label_existing_copy_map[ ou_id ][ callnumber_composite_key ][i].id());
688                 var temp_parts = g.org_label_existing_copy_map[ ou_id ][ callnumber_composite_key ][i].parts();
689                 temp_parts = util.functional.filter_list(
690                     temp_parts,
691                     function(p) {
692                         return p.record() == g.doc_id; // filter out foreign parts
693                     }
694                 );
695                 if (temp_parts.length > 0) {
696                     tb.setAttribute('bmp_id',temp_parts[0].id());
697                     part_menu.firstChild.value = g.parts_hash[ temp_parts[0].id() ].label();
698                 }
699                 tb.select();
700                 if (! g.first_focus) { g.first_focus = tb; }
701             }
702             if (g.use_defaults && ! g.first_focus) {
703                 g.first_focus = tb;
704                 tb.focus();
705             }
706             if (set_handlers) {
707                 util.widgets.apply_vertical_tab_on_enter_handler(
708                     tb,
709                     function() { ready_to_create({'target':tb}); setTimeout(function(){util.widgets.vertical_tab(tb);},0); },
710                     g.delay_gather_copies_soon
711                 );
712                 util.widgets.apply_vertical_tab_on_enter_handler(
713                     part_menu.firstChild,
714                     function() { setTimeout(function(){util.widgets.vertical_tab(part_menu.firstChild);},0); },
715                     g.delay_gather_copies_soon
716                 );
717                 tb.addEventListener('change', function(ev) {
718                     var barcode = String( ev.target.value ).replace(/\s/g,'');
719                     if (barcode != ev.target.value) ev.target.value = barcode;
720                     if ($('check_barcodes').checked && ! util.barcode.check(barcode) ) {
721                         g.error.yns_alert($("catStrings").getFormattedString('staff.cat.volume_copy_creator.render_barcode_entry.alert_message', [barcode]),
722                             $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_title'),
723                             $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_ok_button'),null,null,
724                             $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_confirm'));
725                         setTimeout( function() { ev.target.select(); ev.target.focus(); }, 0);
726                     }
727                 }, false);
728                 tb.addEventListener('change', g.gather_copies_soon, false);
729                 tb.addEventListener( 'focus', function(ev) { g.last_focus = ev.target; }, false );
730             }
731         }
732
733         g.gather_copies_soon();
734         setTimeout( function() { if (g.first_focus) { g.first_focus.focus(); } }, 0 );
735
736     } catch(E) {
737         g.error.sdump('D_ERROR','g.render_barcode_entry: ' + E);
738     }
739 }
740
741 g.generate_barcodes = function() {
742     try {
743         var nodes = document.getElementsByAttribute('rel_vert_pos',rel_vert_pos_barcode);
744         if (nodes.length < 1) { return; }
745         var first_barcode = nodes[0].value;
746
747         if (! first_barcode) { return; }
748
749         var barcodes = g.network.simple_request(
750             'AUTOGENERATE_BARCODES',
751             [
752                 ses(),
753                 first_barcode,
754                 nodes.length - 1,
755                 $('check_barcodes').checked ? {} : { "checkdigit" : false }
756             ]
757         );
758
759         if (typeof barcodes.ilsevent != 'undefined') {
760             throw(barcodes);
761         }
762
763         for (var i = 0; i < barcodes.length; i++) {
764             nodes[i+1].value = barcodes[i];
765             nodes[i+1].select();
766             util.widgets.dispatch('change',nodes[i+1]);
767         }
768
769         setTimeout(
770             function() {
771                 g.gather_copies_soon();
772             },0
773         );
774
775     } catch(E) {
776         g.error.sdump('D_ERROR','g.generate_barcodes: ' + E);
777     }
778 }
779
780 g.delay_gather_copies_soon = function() {
781     if (xulG.unified_interface) {
782         dump('g.delay_gather_copies_soon()\n');
783         g.gather_copies_soon();
784     }
785 }
786
787 g.gather_copies_soon = function(ev) {
788     try {
789         if (!xulG.unified_interface) { return; }
790         dump('g.gather_copies_soon()\n');
791         if (g.update_copy_editor_timeoutID) {
792             clearTimeout(g.update_copy_editor_timeoutID);
793         }
794         // This function is expensive when it comes to keeping the UI responsive, so let's give it a delay
795         // that quick entry of consecutive fields can override
796         g.update_copy_editor_timeoutID = setTimeout(
797             function() {
798                 try {
799                     g.gather_copies();
800                     xulG.refresh_copy_editor();
801                 } catch(E) {
802                     dump('Error in volume_copy_editor.js with g.gather_copies_soon setTimeout func(): ' + E + '\n');
803                 }
804             }, update_timer
805         );
806     } catch(E) {
807         alert('Error in volume_copy_creator.js, g.gather_copies_soon(): ' + E);
808     }
809 }
810
811 g.new_acp_id = -1;
812 g.new_acn_id = -1;
813
814 g.gather_copies = function() {
815     dump('g.gather_copies()\n');
816     try {
817         var nl = document.getElementsByTagName('textbox');
818
819         g.volumes_scaffold = {};
820         /*
821             g.volumes_scaffold = {
822                 '#ou_id' : {
823                     '#class_id:#prefix_id:#callnumber label:#suffix_id' : {
824                         'callnumber_data' : {
825                             'acn_id' : '#callnumber id',
826                             'acn_label' : '#callnumber label',
827                             'acnc_id' : '#classification_id',
828                             'acnp_id' : '#prefix_id',
829                             'acns_id' : '#suffix_id'
830                         },
831                         'barcode_data' :
832                             [
833                                 {
834                                     'barcode' : '#barcode',
835                                     'acp_id' : '#copy_id',
836                                     'bmp_id' : '#part_id'
837                                 }, ...
838                             ]
839                     }
840                 }, ...
841             }
842         */
843
844         var barcodes = [];
845         var v_count = 0;
846         for (var i = 0; i < nl.length; i++) {
847             if ( nl[i].getAttribute('rel_vert_pos') == rel_vert_pos_barcode ) barcodes.push( nl[i] );
848             if ( nl[i].getAttribute('rel_vert_pos') == rel_vert_pos_call_number )  {
849                 v_count++;
850                 var ou_id = nl[i].getAttribute('ou_id');
851                 var acn_id = nl[i].getAttribute('acn_id');
852                 if (!acn_id) {
853                     acn_id = g.new_acn_id--;
854                     nl[i].setAttribute('acn_id',acn_id);
855                 }
856                 var acnc_id = nl[i].getAttribute('acnc_id') || g.label_class;
857                 var acnp_id = nl[i].getAttribute('acnp_id') || -1;
858                 var acns_id = nl[i].getAttribute('acns_id') || -1;
859                 var callnumber = nl[i].value;
860                 if (typeof g.volumes_scaffold[ou_id] == 'undefined') {
861                     g.volumes_scaffold[ou_id] = {}
862                 }
863                 var composite_key = acnc_id + ':' + acnp_id + ':' + callnumber + ':' + acns_id;
864                 if (typeof g.volumes_scaffold[ou_id][composite_key] == 'undefined') {
865                     g.volumes_scaffold[ou_id][composite_key] = {
866                         //'node' : nl[i],
867                         'callnumber_data' : {
868                             'acn_id' : acn_id,
869                             'acn_label' : callnumber,
870                             'acnc_id' : acnc_id,
871                             'acnp_id' : acnp_id,
872                             'acns_id' : acns_id
873                         },
874                         'barcode_data' : []
875                     }
876                     dump('fleshing volumes scaffold with ou_id = ' + ou_id + ' composite_key = ' + composite_key + ' acn_id = ' + acn_id + '\n');
877                 }
878             }
879         };
880         dump('volume_copy_creator: processed ' + nl.length + ' textbox nodes, consisting of ' + barcodes.length + ' barcodes and ' + v_count + 'volumes\n');
881         dump('volume scaffold = ' + js2JSON(g.volumes_scaffold) + '\n');
882
883         for (var i = 0; i < barcodes.length; i++) {
884             var acp_id = barcodes[i].getAttribute('acp_id') || g.new_acp_id--;
885             if (acp_id < 0) {
886                 barcodes[i].setAttribute('acp_id',acp_id);
887             }
888             var ou_id = barcodes[i].getAttribute('ou_id');
889             var callnumber_composite_key = barcodes[i].getAttribute('callkey');
890             var barcode = barcodes[i].value;
891             var bmp_id = barcodes[i].getAttribute('bmp_id');
892
893             dump('placing ' + barcode + ' for ou = ' + ou_id + ' into composite_key bin ' + callnumber_composite_key + '\n');
894
895             if (typeof g.volumes_scaffold[ou_id] == 'undefined') {
896                 dump('1: I want to remove this soon, so alert me if it is getting used, ou_id = ' + ou_id + '\n');
897                 g.volumes_scaffold[ou_id] = {}
898             }
899             if (typeof g.volumes_scaffold[ou_id][callnumber_composite_key] == 'undefined') {
900                 dump('2: when does this happen, and why? ou_id = ' + ou_id + ' callnumber_composite_key = ' + callnumber_composite_key + '\n');
901                 // one way this can happen, race condition between this function and editing a widget
902                 g.volumes_scaffold[ou_id][callnumber_composite_key] = {
903                     'callnumber_data' : {
904                         // not ideal, but hey...
905                         'acn_label' : callnumber_composite_key.split(/:/).slice(2,-1).join(':'),
906                         'acnc_id' : callnumber_composite_key.split(/:/)[0],
907                         'acnp_id' : callnumber_composite_key.split(/:/)[1],
908                         'acns_id' : callnumber_composite_key.split(/:/).slice(-1)[0]
909                     },
910                     'barcode_data' : []
911                 }
912             }
913
914             if (barcode != '') {
915                 g.volumes_scaffold[ou_id][callnumber_composite_key].barcode_data.push(
916                     {
917                         'barcode' : barcode,
918                         'acp_id' : acp_id,
919                         'bmp_id' : bmp_id
920                     }
921                 );
922             }
923         }
924
925         var volumes = [];
926         var copies = [];
927         var volume_data = {};
928
929         // Get the default copy status; default to "In Process" if unset, per 1.6
930         var normal_ccs = g.data.hash.aous['cat.default_copy_status_normal'] || 5;
931
932         function new_copy(acp_id,ou_id,acn_id,barcode) {
933             var copy = new acp();
934             copy.id( acp_id );
935             copy.isnew('1');
936             copy.barcode( barcode );
937             copy.call_number( acn_id );
938             copy.circ_lib(ou_id);
939             /* FIXME -- use constants */
940             copy.deposit(0);
941             copy.price(0);
942             copy.deposit_amount(0);
943             copy.fine_level(2); // Normal
944             copy.loan_duration(2); // Normal
945             copy.location(1); // Stacks
946             copy.status(normal_ccs);
947             copy.circulate(get_db_true());
948             copy.holdable(get_db_true());
949             copy.opac_visible(get_db_true());
950             copy.ref(get_db_false());
951             return copy;
952         }
953
954         for (var ou_id in g.volumes_scaffold) {
955             for (var composite_key in g.volumes_scaffold[ou_id]) {
956                 for (var i = 0; i < g.volumes_scaffold[ou_id][composite_key].barcode_data.length; i++) {
957                     var barcode = g.volumes_scaffold[ou_id][composite_key].barcode_data[i].barcode;
958                     var acp_id = g.volumes_scaffold[ou_id][composite_key].barcode_data[i].acp_id;
959                     var bmp_id = g.volumes_scaffold[ou_id][composite_key].barcode_data[i].bmp_id;
960                     var acn_id = g.volumes_scaffold[ou_id][composite_key].callnumber_data.acn_id;
961                     dump('gather_copies(): barcode = ' + barcode + ' acp_id = ' + acp_id + ' bmp_id = ' + bmp_id + ' acn_id = ' + acn_id + ' composite_key = ' + composite_key + '\n');
962                     var copy = g.id_copy_map[ acp_id ];
963                     if (!copy) {
964                         copy = new_copy(acp_id,ou_id,acn_id,barcode);
965                         g.id_copy_map[ acp_id ] = copy;
966                     } else {
967                         copy.ischanged( get_db_true() );
968                     }
969                     copy.barcode( barcode );
970                     copy.call_number( acn_id );
971                     var temp_parts = util.functional.filter_list(
972                         copy.parts() || [],
973                         function(p) {
974                             return (p.record() != g.doc_id); // filter out parts for this bib
975                         }
976                     );
977                     if (bmp_id) {
978                         temp_parts.push( g.parts_hash[ bmp_id ] );
979                     }
980                     copy.parts( temp_parts );
981                     copies.push( copy );
982                 }
983             }
984         }
985
986         xulG.copies = copies;
987         return copies;
988
989     } catch(E) {
990         alert('Error in volume_copy_creator.js, g.gather_copies():' + E);
991     }
992 }
993
994 g.vivicate_update_volumes = function() {
995     try {
996         var volumes = [];
997         for (var ou_id in g.volumes_scaffold) {
998             for (var composite_key in g.volumes_scaffold[ou_id]) {
999
1000                 var callnumber_data = g.volumes_scaffold[ou_id][composite_key].callnumber_data;
1001                 var acn_id = callnumber_data.acn_id;
1002                 var acnp_id = callnumber_data.acnp_id;
1003                 var acns_id = callnumber_data.acns_id;
1004                 var acnc_id = callnumber_data.acnc_id;
1005
1006                 if (acn_id < 0) {
1007
1008                     var acn_blob = g.network.simple_request(
1009                         'FM_ACN_FIND_OR_CREATE',
1010                         [ ses(), callnumber_data.acn_label, g.doc_id, ou_id, acnp_id, acns_id, acnc_id ]
1011                     );
1012                     dump('FM_ACN_FIND_OR_CREATE: label = ' + callnumber_data.acn_label
1013                         + ' doc = ' + g.doc_id + ' ou = ' + ou_id + ' acnp = ' + acnp_id + ' acns = ' + acns_id + ' acnc = ' + acnc_id + '\n');
1014
1015                     if (typeof acn_blob.ilsevent != 'undefined') {
1016                         alert('Error in g.vivicate_update_volumes, acn_id = ' + acn_id + ' acn_blob = ' + js2JSON(acn_blob));
1017                         continue;
1018                     }
1019
1020                     acn_id = acn_blob.acn_id;
1021
1022                     if (typeof g.acn_map[ acn_id ] == 'undefined') {
1023                         var temp_acn = g.network.simple_request(
1024                             'FM_ACN_RETRIEVE.authoritative',
1025                             [ acn_id ]
1026                         );
1027                         if (typeof temp_acn.ilsevent != 'undefined') {
1028                             alert('Error in g.vivicate_update_volumes, acn_id = ' + acn_id + ' temp_acn = ' + js2JSON(temp_acn));
1029                             continue;
1030                         }
1031                         g.acn_map[ acn_id ] = temp_acn;
1032                         if (callnumber_data.acn_id < 0) {
1033                             g.acn_map[ callnumber_data.acn_id ] = temp_acn;
1034                         }
1035                     }
1036
1037                 }
1038 /*
1039                 var my_acn = g.acn_map[ acn_id ];
1040
1041                 var node = g.volumes_scaffold[ou_id][composite_key].node;
1042                 var class_menulist = node.parentNode.previousSibling.previousSibling.firstChild;
1043                 var prefix_menulist = node.parentNode.previousSibling.firstChild;
1044                 var suffix_menulist = node.parentNode.nextSibling.firstChild;
1045
1046                 if ( String(class_menulist.value) != String(my_acn.label_class()) {
1047                     my_acn.label_class( class_menulist.value );
1048                     my_acn.ischanged( get_db_true() );
1049                 }
1050                 if ( String(prefix_menulist.value) != String(my_acn.prefix()) {
1051                     my_acn.prefix( prefix_menulist.value );
1052                     my_acn.ischanged( get_db_true() );
1053                 }
1054                 if ( String(suffix_menulist.value) != String(my_acn.suffix()) {
1055                     my_acn.suffix( suffix_menulist.value );
1056                     my_acn.ischanged( get_db_true() );
1057                 }
1058
1059                 if (get_bool( my_acn.ischanged() )) {
1060                     volumes.push( my_acn );
1061                 }
1062 */
1063             }
1064         }
1065         if (volumes.length > 0) {
1066             if (typeof xul_param('update_volume') == 'function') {
1067                 xul_param('update_volume')(volumes);
1068             } else {
1069                  var r = g.network.simple_request(
1070                     'FM_ACN_TREE_UPDATE',
1071                     [ ses(),volumes, false, { 'auto_merge_vols' : false } ]
1072                 );
1073                 if (typeof r.ilsevent != 'undefined') {
1074                     alert('error with volume update: ' + js2JSON(r));
1075                 }
1076             }
1077         }
1078     } catch(E) {
1079         alert('Error in volume_copy_creator.js, vivicate_volumes(): ' + E);
1080     }
1081 }
1082
1083 g.stash_and_close = function(param) {
1084
1085     try {
1086
1087         if (g.update_copy_editor_timeoutID) {
1088             clearTimeout(g.update_copy_editor_timeoutID);
1089         }
1090
1091         var copies;
1092         if (xulG.unified_interface) {
1093             g.gather_copies();
1094             xulG.refresh_copy_editor();
1095             copies = xulG.copies;
1096         } else {
1097             copies = g.gather_copies();
1098         }
1099
1100         var dont_close = false;
1101
1102         g.vivicate_update_volumes();
1103         for (var i = 0; i < copies.length; i++) {
1104             var acn_id = copies[i].call_number();
1105             if (typeof g.acn_map[acn_id] != 'undefined') {
1106                 // handle vivicated-callnumbers
1107                 copies[i].call_number( g.acn_map[acn_id].id() );
1108             } else {
1109                 alert('error in stash and close, acn_id = ' + acn_id);
1110             }
1111         }
1112
1113         if (copies.length > 0) {
1114             if (param == 'edit') {
1115                 JSAN.use('cat.util');
1116                 copies = cat.util.spawn_copy_editor( { 'edit' : true, 'docid' : g.doc_id, 'copies' : copies, 'caller_handles_update' : true });
1117             }
1118             if (typeof xul_param('update_copy') == 'function') {
1119                 xul_param('update_copy')(copies);
1120             } else {
1121                  var r = g.network.simple_request(
1122                     'FM_ACP_FLESHED_BATCH_UPDATE',
1123                     [ ses(),copies, true ]
1124                 );
1125                 if (typeof r.ilsevent != 'undefined') {
1126                     alert('error with copy update:' + js2JSON(r));
1127                 }
1128             }
1129             try {
1130                 //case 1706 /* ITEM_BARCODE_EXISTS */ :
1131                 if (copies && copies.length > 0 && $('print_labels').checked) {
1132                     JSAN.use('util.functional');
1133                     dont_close = true;
1134                     xulG.set_tab(
1135                         urls.XUL_SPINE_LABEL,
1136                         { 'tab_name' : $("catStrings").getString('staff.cat.util.spine_editor.tab_name') },
1137                         {
1138                             'barcodes' : util.functional.map_list( copies, function(o){return o.barcode();})
1139                         }
1140                     );
1141                 }
1142             } catch(E) {
1143                 alert('2: Error in volume_copy_creator.js with g.stash_and_close(): ' + E);
1144             }
1145         }
1146
1147         try { if (typeof window.refresh == 'function') { window.refresh(); } } catch(E) { dump(E+'\n'); }
1148         try { if (typeof g.refresh == 'function') { g.refresh(); } } catch(E) { dump(E+'\n'); }
1149
1150         if (typeof xulG.unlock_copy_editor == 'function') {
1151             xulG.unlock_copy_editor();
1152         }
1153
1154         if (! dont_close) { xulG.close_tab(); }
1155
1156     } catch(E) {
1157         alert('3: Error in volume_copy_creator.js with g.stash_and_close(): ' + E);
1158     }
1159 }
1160
1161 g.load_prefs = function() {
1162     try {
1163         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
1164         JSAN.use('util.file'); var file = new util.file('volume_copy_creator.prefs');
1165         if (file._file.exists()) {
1166             var prefs = file.get_object(); file.close();
1167             if (prefs.check_barcodes) {
1168                 if ( prefs.check_barcodes == 'false' ) {
1169                     $('check_barcodes').checked = false;
1170                 } else {
1171                     $('check_barcodes').checked = prefs.check_barcodes;
1172                 }
1173             } else {
1174                 $('check_barcodes').checked = false;
1175             }
1176             if (prefs.print_labels) {
1177                 if ( prefs.print_labels == 'false' ) {
1178                     $('print_labels').checked = false;
1179                 } else {
1180                     $('print_labels').checked = prefs.print_labels;
1181                 }
1182             } else {
1183                 $('print_labels').checked = false;
1184             }
1185
1186         }
1187     } catch(E) {
1188         alert('Error in volume_copy_creator.js with g.load_prefs(): ' + E);
1189     }
1190 }
1191
1192 g.save_prefs = function () {
1193     try {
1194         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
1195         JSAN.use('util.file'); var file = new util.file('volume_copy_creator.prefs');
1196         file.set_object(
1197             {
1198                 'check_barcodes' : $('check_barcodes').checked,
1199                 'print_labels' : $('print_labels').checked,
1200             }
1201         );
1202         file.close();
1203     } catch(E) {
1204         alert('Error in volume_copy_creator.js with g.save_prefs(): ' + E);
1205     }
1206 }
1207
1208 g.render_class_menu = function(call_number_tb) {
1209     var ml = util.widgets.make_menulist(
1210         util.functional.map_list(
1211             g.data.list.acnc,
1212             function(o) {
1213                 return [ o.name(), o.id() ];
1214             }
1215         )
1216     );
1217     ml.setAttribute('rel_vert_pos',rel_vert_pos_call_number_classification);
1218     ml.addEventListener(
1219         'command',
1220         function() {
1221             call_number_tb.setAttribute('acnc_id',ml.value);
1222         },
1223         false
1224     );
1225     return ml;
1226 }
1227
1228 g.render_prefix_menu = function(call_number_tb) {
1229     var ou_id = call_number_tb.getAttribute('ou_id');
1230     var org = g.data.hash.aou[ ou_id ];
1231     var menulist = document.createElement('menulist');
1232         var menupopup = document.createElement('menupopup');
1233         menulist.appendChild(menupopup);
1234         var org_list = []; // order from top of consortium to owning lib
1235         while(org) {
1236             org_list.unshift(org.id());
1237             org = org.parent_ou();
1238             if (org && typeof org != 'object') {
1239                 org = g.data.hash.aou[ org ];
1240             }
1241         }
1242         for (var i = 0; i < org_list.length; i++) {
1243             g.render_prefix_menu_items(menupopup,org_list[i]);
1244         }
1245
1246     menulist.setAttribute('rel_vert_pos',rel_vert_pos_call_number_prefix);
1247     menulist.addEventListener(
1248         'command',
1249         function() {
1250             call_number_tb.setAttribute('acnp_id',menulist.value);
1251         },
1252         false
1253     );
1254     return menulist;
1255 }
1256
1257 g.render_prefix_menu_items = function(menupopup,ou_id) {
1258     if (typeof g.data.list['acnp_for_lib_'+ou_id] == 'undefined') {
1259         g.data.list['acnp_for_lib_'+ou_id] = g.network.simple_request(
1260             'FM_ACNP_RETRIEVE_VIA_PCRUD',
1261             [ ses(), {"owning_lib":{"=":ou_id}}, {"order_by":{"acnp":"label_sortkey"}} ]
1262         );
1263         g.data.stash('list');
1264     }
1265     for (var i = 0; i < g.data.list['acnp_for_lib_'+ou_id].length; i++) {
1266         var my_acnp = g.data.list['acnp_for_lib_'+ou_id][i];
1267         var menuitem = document.createElement('menuitem');
1268         menupopup.appendChild(menuitem);
1269             menuitem.setAttribute(
1270                 'label',
1271                 my_acnp.id() == -1 ? '' :
1272                 $('catStrings').getFormattedString(
1273                     'staff.cat.volume_copy_creator.call_number_prefix.menuitem_label',
1274                     [
1275                         my_acnp.label(),
1276                         g.data.hash.aou[ ou_id ].shortname()
1277                     ]
1278                 )
1279             );
1280             menuitem.setAttribute('value',my_acnp.id());
1281     }
1282 }
1283
1284 g.render_suffix_menu = function(call_number_tb) {
1285     var ou_id = call_number_tb.getAttribute('ou_id');
1286     var org = g.data.hash.aou[ ou_id ];
1287     var menulist = document.createElement('menulist');
1288         var menupopup = document.createElement('menupopup');
1289         menulist.appendChild(menupopup);
1290         var org_list = []; // order from top of consortium to owning lib
1291         while(org) {
1292             org_list.unshift(org.id());
1293             org = org.parent_ou();
1294             if (org && typeof org != 'object') {
1295                 org = g.data.hash.aou[ org ];
1296             }
1297         }
1298         for (var i = 0; i < org_list.length; i++) {
1299             g.render_suffix_menu_items(menupopup,org_list[i]);
1300         }
1301
1302     menulist.setAttribute('rel_vert_pos',rel_vert_pos_call_number_suffix);
1303     menulist.addEventListener(
1304         'command',
1305         function() {
1306             call_number_tb.setAttribute('acns_id',menulist.value);
1307         },
1308         false
1309     );
1310     return menulist;
1311 }
1312
1313 g.render_suffix_menu_items = function(menupopup,ou_id) {
1314     if (typeof g.data.list['acns_for_lib_'+ou_id] == 'undefined') {
1315         g.data.list['acns_for_lib_'+ou_id] = g.network.simple_request(
1316             'FM_ACNS_RETRIEVE_VIA_PCRUD',
1317             [ ses(), {"owning_lib":{"=":ou_id}}, {"order_by":{"acns":"label_sortkey"}} ]
1318         );
1319         g.data.stash('list');
1320     }
1321     for (var i = 0; i < g.data.list['acns_for_lib_'+ou_id].length; i++) {
1322         var my_acns = g.data.list['acns_for_lib_'+ou_id][i];
1323         var menuitem = document.createElement('menuitem');
1324         menupopup.appendChild(menuitem);
1325             menuitem.setAttribute(
1326                 'label',
1327                 my_acns.id() == -1 ? '' :
1328                 $('catStrings').getFormattedString(
1329                     'staff.cat.volume_copy_creator.call_number_suffix.menuitem_label',
1330                     [
1331                         my_acns.label(),
1332                         g.data.hash.aou[ ou_id ].shortname()
1333                     ]
1334                 )
1335             );
1336             menuitem.setAttribute('value',my_acns.id());
1337     }
1338 }
1339
1340
1341 g.list_callnumbers = function(doc_id, label_class) {
1342     var cn_blob;
1343     try {
1344         cn_blob = g.network.simple_request('BLOB_MARC_CALLNUMBERS_RETRIEVE',[g.doc_id, label_class]);
1345     } catch(E) {
1346         cn_blob = [];
1347     }
1348     var hbox = document.getElementById('marc_cn');
1349     var ml = util.widgets.make_menulist(
1350         [
1351             [ '', '' ]
1352         ].concat(
1353             util.functional.map_list(
1354                 cn_blob,
1355                 function(o) {
1356                     for (var i in o) {
1357                         return [ o[i], i ];
1358                     }
1359                 }
1360             )
1361         )
1362     ); hbox.appendChild(ml);
1363     ml.setAttribute('editable','true');
1364     ml.setAttribute('width', '200');
1365     ml.setAttribute('id', 'marc_cn_menulist');
1366 }
1367
1368 g.list_classes = function() {
1369     var hbox = $('batch_class');
1370     var ml = util.widgets.make_menulist(
1371         [
1372             [ '<No Change>', false ]
1373         ].concat(
1374             util.functional.map_list(
1375                 g.data.list.acnc,
1376                 function(o) {
1377                     return [ o.name(), o.id() ];
1378                 }
1379             )
1380         )
1381     ); hbox.appendChild(ml);
1382     ml.setAttribute('id','batch_class_menulist');
1383     ml.addEventListener(
1384         'command',
1385         function() {
1386             if (!isNaN(Number(ml.value))) {
1387                 addCSSClass(hbox,'copy_editor_field_changed');
1388                 if (xulG.unified_interface) {
1389                     xulG.notify_of_templatable_field_change('batch_class_menulist',ml.value);
1390                 }
1391             } else {
1392                 removeCSSClass(hbox,'copy_editor_field_changed');
1393             }
1394         },
1395         false
1396     );
1397 }
1398
1399 g.list_prefixes = function() {
1400     var hbox = $('batch_prefix');
1401     var ml = util.widgets.make_menulist(
1402         [
1403             [ '<No Change>', false ]
1404         ]
1405     ); hbox.appendChild(ml);
1406     for (var i = 0; i < g.common_ancestor_ou_ids.length; i++) {
1407         g.render_prefix_menu_items(ml.firstChild,g.common_ancestor_ou_ids[i]);
1408     }
1409     ml.setAttribute('id','batch_prefix_menulist');
1410     ml.addEventListener(
1411         'command',
1412         function() {
1413             if (!isNaN(Number(ml.value))) {
1414                 addCSSClass(hbox,'copy_editor_field_changed');
1415                 if (xulG.unified_interface) {
1416                     xulG.notify_of_templatable_field_change('batch_prefix_menulist',ml.value);
1417                 }
1418             } else {
1419                 removeCSSClass(hbox,'copy_editor_field_changed');
1420             }
1421         },
1422         false
1423     );
1424 }
1425
1426 g.list_suffixes = function() {
1427     var hbox = $('batch_suffix');
1428     var ml = util.widgets.make_menulist(
1429         [
1430             [ '<No Change>', false ]
1431         ]
1432     ); hbox.appendChild(ml);
1433     for (var i = 0; i < g.common_ancestor_ou_ids.length; i++) {
1434         g.render_suffix_menu_items(ml.firstChild,g.common_ancestor_ou_ids[i]);
1435     }
1436     ml.setAttribute('id','batch_suffix_menulist');
1437     ml.addEventListener(
1438         'command',
1439         function() {
1440             if (!isNaN(Number(ml.value))) {
1441                 addCSSClass(hbox,'copy_editor_field_changed');
1442                 if (xulG.unified_interface) {
1443                     xulG.notify_of_templatable_field_change('batch_suffix_menulist',ml.value);
1444                 }
1445             } else {
1446                 removeCSSClass(hbox,'copy_editor_field_changed');
1447             }
1448         },
1449         false
1450     );
1451 }
1452
1453 g.render_batch_button = function() {
1454     var hbox = $('batch_button_box');
1455     var btn = document.createElement('button');
1456     btn.setAttribute('id','batch_button');
1457     btn.setAttribute('label',$('catStrings').getString('staff.cat.volume_copy_creator.my_init.btn.label'));
1458     btn.setAttribute('accesskey',$('catStrings').getString('staff.cat.volume_copy_creator.my_init.btn.accesskey'));
1459     btn.setAttribute('image','/xul/server/skin/media/images/down_arrow.gif');
1460     hbox.appendChild(btn);
1461     btn.addEventListener(
1462         'command',
1463         function() {
1464             var nl = document.getElementsByTagName('textbox');
1465             for (var i = 0; i < nl.length; i++) {
1466                 /* label */
1467                 if (nl[i].getAttribute('rel_vert_pos')==rel_vert_pos_call_number && !nl[i].disabled) {
1468                     var label =  $('marc_cn').firstChild.value;
1469                     if (label != '') {
1470                         nl[i].value = label;
1471                         util.widgets.dispatch('change',nl[i]);
1472                     }
1473                 }
1474             }
1475             nl = document.getElementsByTagName('menulist');
1476             for (var i = 0; i < nl.length; i++) {
1477                 /* classification */
1478                 if (nl[i].getAttribute('rel_vert_pos')==rel_vert_pos_call_number_classification && !nl[i].disabled) {
1479                     var value =  $('batch_class_menulist').value;
1480                     if (!isNaN( Number(value) )) {
1481                         nl[i].value = value;
1482                         util.widgets.dispatch('command',nl[i]);
1483                     }
1484                 }
1485                 /* prefix */
1486                 if (nl[i].getAttribute('rel_vert_pos')==rel_vert_pos_call_number_prefix && !nl[i].disabled) {
1487                     var value =  $('batch_prefix_menulist').value;
1488                     if (!isNaN( Number(value) )) {
1489                         nl[i].value = value;
1490                         util.widgets.dispatch('command',nl[i]);
1491                     }
1492                 }
1493                 /* suffix */
1494                 if (nl[i].getAttribute('rel_vert_pos')==rel_vert_pos_call_number_suffix && !nl[i].disabled) {
1495                     var value =  $('batch_suffix_menulist').value;
1496                     if (!isNaN( Number(value) )) {
1497                         nl[i].value = value;
1498                         util.widgets.dispatch('command',nl[i]);
1499                     }
1500                 }
1501             }
1502             setTimeout(
1503                 function() {
1504                     g.gather_copies_soon();
1505                 },0
1506             );
1507             if (g.last_focus) setTimeout( function() { g.last_focus.focus(); }, 0 );
1508         },
1509         false
1510     );
1511 }