]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/xul/staff_client/server/cat/util.js
Merge remote branch 'working/user/dbs/fix-nonfiling-titles'
[Evergreen.git] / Open-ILS / xul / staff_client / server / cat / util.js
1 dump('entering cat/util.js\n');
2
3 function $(id) { return document.getElementById(id); }
4
5 if (typeof cat == 'undefined') var cat = {};
6 cat.util = {};
7
8 cat.util.EXPORT_OK    = [ 
9     'spawn_copy_editor', 'add_copies_to_bucket', 'show_in_opac', 'spawn_spine_editor', 'transfer_copies', 
10     'transfer_title_holds', 'mark_item_missing', 'mark_item_damaged', 'replace_barcode', 'fast_item_add', 
11     'make_bookable', 'edit_new_brsrc', 'edit_new_bresv', 'batch_edit_volumes', 'render_fine_level',
12     'render_loan_duration', 'mark_item_as_missing_pieces', 'render_callnumbers_for_bib_menu',
13     'render_cn_prefix_menuitems', 'render_cn_suffix_menuitems', 'render_cn_class_menu',
14     'render_cn_prefix_menu', 'render_cn_suffix_menu', 'transfer_specific_title_holds',
15     'request_items', 'mark_for_overlay', 'get_cbs_for_bre_id'
16 ];
17 cat.util.EXPORT_TAGS    = { ':all' : cat.util.EXPORT_OK };
18
19 cat.util.replace_barcode = function(old_bc) {
20     try {
21         JSAN.use('util.network');
22         var network = new util.network();
23
24         if (!old_bc) old_bc = window.prompt($("catStrings").getString('staff.cat.util.replace_barcode.old_bc_window_prompt.prompt'),
25             '',
26             $("catStrings").getString('staff.cat.util.replace_barcode.old_bc_window_prompt.title'));
27         if (!old_bc) return;
28
29         var copy;
30         try {
31             copy = network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ old_bc ]);
32             if (typeof copy.ilsevent != 'undefined') throw(copy); 
33             if (!copy) throw(copy);
34         } catch(E) {
35             alert($("catStrings").getFormattedString('staff.cat.util.replace_barcode.error_alert', [old_bc]) + '\n');
36             return old_bc;
37         }
38     
39         // Why did I want to do this twice?  Because this copy is more fleshed?
40         try {
41             copy = network.simple_request('FM_ACP_RETRIEVE',[ copy.id() ]);
42             if (typeof copy.ilsevent != 'undefined') throw(copy);
43             if (!copy) throw(copy);
44         } catch(E) {
45             try {
46                 alert($("catStrings").getFormattedString('staff.cat.util.replace_barcode.error_alert', [old_bc]) +
47                      '\n' + (typeof E.ilsevent == 'undefined' ? '' : E.textcode + ' : ' + E.desc));
48             } catch(F) {
49                 alert(E + '\n' + F);
50             }
51             return old_bc;
52         }
53     
54         var new_bc = window.prompt($("catStrings").getString('staff.cat.util.replace_barcode.new_bc_window_prompt.prompt'),
55             '',
56             $("catStrings").getString('staff.cat.util.replace_barcode.new_bc_window_prompt.title'));
57         new_bc = String( new_bc ).replace(/\s/g,'');
58         /* Casting a possibly null input value to a String turns it into "null" */
59         if (!new_bc || new_bc == 'null') {
60             alert($("catStrings").getString('staff.cat.util.replace_barcode.new_bc.failed'));
61             return old_bc;
62         }
63     
64         var test = network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ new_bc ]);
65         if (typeof test.ilsevent == 'undefined') {
66             alert('Rename aborted.  Another copy has barcode "' + new_bc + '".');
67             return old_bc;
68         } else {
69             if (test.ilsevent != 1502 /* ASSET_COPY_NOT_FOUND */) {
70                 obj.error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.util.replace_barcode.testing_error', [new_bc]), test);
71                 return old_bc;
72             }    
73         }
74
75         copy.barcode(new_bc); copy.ischanged('1');
76         var r = network.simple_request('FM_ACP_FLESHED_BATCH_UPDATE', [ ses(), [ copy ] ]);
77         if (typeof r.ilsevent != 'undefined') { 
78             if (r.ilsevent != 0) {
79                 if (r.ilsevent == 5000 /* PERM_FAILURE */) {
80                     alert($("catStrings").getString('staff.cat.util.replace_barcode.insufficient_permission_for_rename'));
81                     return old_bc;
82                 } else {
83                     obj.error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.util.replace_barcode.item_rename_error'),r);
84                     return old_bc;
85                 }
86             }
87         }
88
89         return new_bc;
90     } catch(E) {
91         JSAN.use('util.error'); var error = new util.error();
92         error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.util.replace_barcode.rename_error'),E);
93         return old_bc;
94     }
95 }
96
97 cat.util.transfer_title_holds = function(old_targets) {
98     JSAN.use('OpenILS.data'); var data = new OpenILS.data();
99     JSAN.use('util.network'); var network = new util.network();
100     try {
101         data.stash_retrieve();
102         var target = data.marked_record_for_hold_transfer;
103         if (!target) {
104             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.destination_needed.label');
105             alert(m);
106             return;
107         }
108         var robj = network.simple_request('TRANSFER_TITLE_HOLDS',[ ses(), target, old_targets ]);
109         if (robj == 1) {
110             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.success.label');
111             alert(m);
112         } else {
113             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.failure.label');
114             alert(m);
115         }
116     } catch(E) {
117         alert('Error in cat.util.transfer_title.holds(): ' + E);
118     }
119 }
120
121 cat.util.transfer_specific_title_holds = function(hold_ids,unique_targets) {
122     JSAN.use('OpenILS.data'); var data = new OpenILS.data();
123     JSAN.use('util.network'); var network = new util.network();
124     try {
125         data.stash_retrieve();
126         var target = data.marked_record_for_hold_transfer;
127         if (!target) {
128             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.destination_needed.label');
129             alert(m);
130             return;
131         }
132         if (unique_targets.length > 1) {
133             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.many_bibs.warning');
134             if (! window.confirm(m)) {
135                 return;
136             }
137         }
138         var robj = network.simple_request('TRANSFER_SPECIFIC_TITLE_HOLDS',[ ses(), target, hold_ids ]);
139         if (robj == 1) {
140             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.success.label');
141             alert(m);
142         } else {
143             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.failure.label');
144             alert(m);
145         }
146     } catch(E) {
147         alert('Error in cat.util.transfer_title.holds(): ' + E);
148     }
149 }
150
151
152 cat.util.transfer_copies = function(params) {
153     JSAN.use('util.error'); var error = new util.error();
154     JSAN.use('OpenILS.data'); var data = new OpenILS.data();
155     JSAN.use('util.network'); var network = new util.network();
156     try {
157         data.stash_retrieve();
158         if (!data.marked_volume) {
159             alert($("catStrings").getString('staff.cat.util.transfer_copies.unmarked_volume_alert'));
160             return;
161         }
162         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
163         var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: auto">';
164         if (!params.message) {
165             params.message = $("catStrings").getFormattedString('staff.cat.util.transfer_copies.params_message', [data.hash.aou[ params.owning_lib ].shortname(), params.volume_label]);
166             //params.message = 'Transfer items from their original volumes to ';
167             //params.message += data.hash.aou[ params.owning_lib ].shortname() + "'s volume labelled ";
168             //params.message += '"' + params.volume_label + '" on the following record (and change their circ libs to match)?';
169         }
170
171         xml += '<description>' + params.message.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') + '</description>';
172         xml += '<hbox><button label="' + $("catStrings").getString('staff.cat.util.transfer_copies.transfer.label')+ '" name="fancy_submit"/>';
173         xml += '<button label="' + $("catStrings").getString('staff.cat.util.transfer_copies.cancel.label');
174         xml += '" accesskey="'+ $("catStrings").getString('staff.cat.util.transfer_copies.cancel.accesskey') +'" name="fancy_cancel"/></hbox>';
175         xml += '<iframe style="overflow: scroll" flex="1" src="' + urls.XUL_BIB_BRIEF + '?docid=' + params.docid + '"/>';
176         xml += '</vbox>';
177         //data.temp_transfer = xml; data.stash('temp_transfer');
178         JSAN.use('util.window'); var win = new util.window();
179         var fancy_prompt_data = win.open(
180             urls.XUL_FANCY_PROMPT,
181             //+ '?xml_in_stash=temp_transfer'
182             //+ '&title=' + window.escape('Item Transfer'),
183             'fancy_prompt', 'chrome,resizable,modal,width=500,height=300',
184             { 'xml' : xml, 'title' : $("catStrings").getString('staff.cat.util.transfer_copies.window_title') }
185         );
186         if (fancy_prompt_data.fancy_status == 'incomplete') { alert($("catStrings").getString('staff.cat.util.transfer_copies.aborted_transfer')); return; }
187
188         JSAN.use('util.functional');
189
190         var copies = network.simple_request('FM_ACP_FLESHED_BATCH_RETRIEVE.authoritative', [ params.copy_ids ]);
191
192         for (var i = 0; i < copies.length; i++) {
193             copies[i].call_number( data.marked_volume );
194             copies[i].circ_lib( params.owning_lib );
195             copies[i].ischanged( 1 );
196         }
197
198         var robj = network.simple_request(
199             'FM_ACP_FLESHED_BATCH_UPDATE', 
200             [ ses(), copies, true ], 
201             null,
202             {
203                 'title' : $("catStrings").getString('staff.cat.util.transfer_copies.override_transfer_failure'),
204                 'overridable_events' : [
205                     1208 /* TITLE_LAST_COPY */,
206                     1227 /* COPY_DELETE_WARNING */,
207                 ]
208             }
209         );
210         
211         if (typeof robj.ilsevent != 'undefined') {
212             throw(robj);
213         } else {
214             alert($("catStrings").getString('staff.cat.util.transfer_copies.successful_transfer'));
215         }
216
217     } catch(E) {
218         error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.util.transfer_copies.transfer_error'),E);
219     }
220 }
221
222 cat.util.spawn_spine_editor = function(selection_list) {
223     JSAN.use('util.error'); var error = new util.error();
224     try {
225         JSAN.use('util.functional');
226         xulG.new_tab(
227             xulG.url_prefix( urls.XUL_SPINE_LABEL ),
228             { 'tab_name' : $("catStrings").getString('staff.cat.util.spine_editor.tab_name') },
229             {
230                 'barcodes' : util.functional.map_list( selection_list, function(o){return o.barcode;}) 
231             }
232         );
233     } catch(E) {
234         error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.util.spine_editor.spine_editor_error'),E);
235     }
236 }
237
238 cat.util.show_in_opac = function(selection_list) {
239     JSAN.use('util.error'); var error = new util.error();
240     JSAN.use('util.network'); var network = new util.network();
241     var doc_id; var seen = {};
242     try {
243         for (var i = 0; i < selection_list.length; i++) {
244             doc_id = selection_list[i].doc_id;
245             if (!doc_id) {
246                 var barcode = selection_list[i].barcode;
247                 doc_id = network.simple_request('FM_BRE_ID_VIA_BARCODE',[barcode]);
248                 if (typeof doc_id.ilsevent != 'undefined' || doc_id == -1) {
249                     alert($("catStrings").getFormattedString('staff.cat.util.show_in_opac.unknown_barcode', [barcode]));
250                     continue;
251                 }
252             }
253             if (doc_id == -1 ) {
254                 continue; /* pre-cat */
255             }
256             if (typeof seen[doc_id] != 'undefined') {
257                 continue;
258             }
259             seen[doc_id] = true;
260             var opac_url = xulG.url_prefix( urls.opac_rdetail ) + doc_id;
261             var content_params = { 
262                 'session' : ses(),
263                 'authtime' : ses('authtime'),
264                 'opac_url' : opac_url,
265             };
266             xulG.new_tab(
267                 xulG.url_prefix(urls.XUL_OPAC_WRAPPER), 
268                 {'tab_name':$('catStrings').getString('staff.cat.util.show_in_opac.retrieving_title')}, 
269                 content_params
270             );
271         }
272     } catch(E) {
273         error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.util.show_in_opac.catalog_error_for_doc_id', [doc_id]),E);
274     }
275 }
276
277 cat.util.add_copies_to_bucket = function(selection_list) {
278     JSAN.use('util.functional');
279     JSAN.use('util.window'); var win = new util.window();
280     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
281     data.cb_temp_copy_ids = js2JSON(
282         util.functional.map_list(
283             selection_list,
284             function (o) {
285                 if (typeof o.copy_id != 'undefined' && o.copy_id != null) {
286                     return o.copy_id;
287                 } else {
288                     return o;
289                 }
290             }
291         )
292     );
293     data.stash('cb_temp_copy_ids');
294     win.open( 
295         xulG.url_prefix(urls.XUL_COPY_BUCKETS_QUICK),
296         '_blank',
297         'chrome,resizable,center'
298     );
299 }
300
301 cat.util.add_titles_to_bucket = function(record_ids) {
302     JSAN.use('util.window'); var win = new util.window();
303     JSAN.use('util.functional');
304     var filtered_record_ids = util.functional.filter_list(
305         record_ids,
306         function(o) {
307             return o != -1; // don't allow the magic pre-cat bib
308         }
309     );
310     if (filtered_record_ids.length != record_ids.length) {
311         alert($("catStrings").getFormattedString(
312             'staff.cat.util.add_titles_to_bucket.number_of_precats_skipped',
313             [ record_ids.length - filtered_record_ids.length ]
314         ));
315     }
316     if (filtered_record_ids.length > 0) {
317         win.open(
318             xulG.url_prefix(urls.XUL_RECORD_BUCKETS_QUICK),
319             '_blank',
320             'chrome,resizable,modal,center',
321             {
322                 record_ids: filtered_record_ids
323             }
324         );
325     }
326 }
327
328 cat.util.spawn_copy_editor = function(params) {
329     try {
330         if (!params.copy_ids && !params.copies) return;
331         if (params.copy_ids && params.copy_ids.length == 0) return;
332         if (params.copies && params.copies.length == 0) return;
333         if (params.copy_ids) params.copy_ids = js2JSON(params.copy_ids); // legacy
334         if (!params.caller_handles_update) params.handle_update = 1; // legacy
335
336         var obj = {};
337         JSAN.use('util.network'); obj.network = new util.network();
338         JSAN.use('util.error'); obj.error = new util.error();
339     
340         var title = '';
341         if (params.copy_ids && params.copy_ids.length > 1 && params.edit == 1)
342             title = $("catStrings").getString('staff.cat.util.copy_editor.batch_edit');
343         else if(params.copies && params.copies.length > 1 && params.edit == 1)
344             title = $("catStrings").getString('staff.cat.util.copy_editor.batch_view');
345         else if(params.copy_ids && params.copy_ids.length == 1)
346             title = $("catStrings").getString('staff.cat.util.copy_editor.edit');
347         else
348             title = $("catStrings").getString('staff.cat.util.copy_editor.view');
349
350         JSAN.use('util.window'); var win = new util.window();
351         var my_xulG = win.open(
352             (urls.XUL_COPY_EDITOR),
353             title,
354             'chrome,modal,resizable',
355             params
356         );
357         if (!my_xulG.copies && params.edit) {
358         } else {
359             return my_xulG.copies;
360         }
361         return [];
362     } catch(E) {
363         JSAN.use('util.error'); var error = new util.error();
364         error.standard_unexpected_error_alert('error in cat.util.spawn_copy_editor',E);
365     }
366 }
367
368 cat.util.mark_item_damaged = function(copy_ids) {
369     var error;
370     try {
371         JSAN.use('util.error'); error = new util.error();
372         JSAN.use('util.functional'); JSAN.use('util.date');
373         JSAN.use('util.network'); var network = new util.network();
374         if (!copy_ids) { return; }
375         copy_ids = util.functional.filter_list( copy_ids, function(o) { return o != null; } );
376         if (copy_ids.length < 1) { return; }
377         var copies = network.simple_request('FM_ACP_FLESHED_BATCH_RETRIEVE.authoritative', [ copy_ids ]);
378         if (typeof copies.ilsevent != 'undefined') throw(copies);
379         var magic_status = false;
380         for (var i = 0; i < copies.length; i++) {
381             var status = copies[i].status(); if (typeof status == 'object') status = status.id();
382             if (typeof my_constants.magical_statuses[ status ] != 'undefined') 
383                 if (my_constants.magical_statuses[ status ].block_mark_item_damaged) magic_status = true;
384         }
385         if (magic_status) {
386         
387             error.yns_alert($("catStrings").getString('staff.cat.util.mark_item_damaged.af_message'),
388                 $("catStrings").getString('staff.cat.util.mark_item_damaged.af_title'),
389                 $("catStrings").getString('staff.cat.util.mark_item_damaged.af_ok_label'), null, null,
390                 $("catStrings").getString('staff.cat.util.mark_item_damaged.af_confirm_action'));
391
392         } else {
393
394             var r = error.yns_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.md_message', [util.functional.map_list( copies, function(o) { return o.barcode(); } ).join(", ")]),
395                 $("catStrings").getString('staff.cat.util.mark_item_damaged.md_title'),
396                 $("catStrings").getString('staff.cat.util.mark_item_damaged.md_ok_label'),
397                 $("catStrings").getString('staff.cat.util.mark_item_damaged.md_cancel_label'), null,
398                 $("catStrings").getString('staff.cat.util.mark_item_damaged.md_confirm_action'));
399
400             if (r == 0) {
401                 var count = 0;
402                 for (var i = 0; i < copies.length; i++) {
403                     try {
404
405                         var my_circ = network.simple_request('FM_CIRC_RETRIEVE_VIA_COPY',[ses(),copies[i].id(),1]);
406                         if (typeof my_circ.ilsevent == 'undefined') { 
407                             JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
408                             my_circ = my_circ[0];
409                             if (typeof my_circ != 'undefined') {
410                                 if (! my_circ.checkin_time() ) {
411                                     var due_date = my_circ.due_date() ? util.date.formatted_date( my_circ.due_date(), '%F' ) : null;
412                                     var auto_checkin = String( data.hash.aous['circ.auto_checkin_on_mark_damage'] ) == 'true';
413                                     /* short-circuit this behavior.  We don't want to mark an item damaged and still have it circulating.  At least for now.  Wait until someone asks for it. */
414                                     auto_checkin = true; 
415                                     JSAN.use('patron.util');
416                                     var patron_obj = patron.util.retrieve_fleshed_au_via_id( ses(), my_circ.usr() );
417                                     var patron_name = patron.util.format_name( patron_obj ) + ' : ' + patron_obj.card().barcode();
418                                     var msg = $("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.item_circulating_to_patron', [ 
419                                         copies[i].barcode(),
420                                         patron_name,
421                                         util.date.formatted_date( my_circ.due_date(), '%{localized}' )]);
422                                     JSAN.use('util.date'); var today = util.date.formatted_date(new Date(),'%F');
423                                     var r2 = auto_checkin ? 1 : error.yns_alert(
424                                         msg,
425                                         document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.title'),
426                                         document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.no_checkin'),
427                                         document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.normal_checkin'),
428                                         due_date ? (today > due_date ? document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.forgiving_checkin') : null) : null,
429                                         document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.confirm_action')
430                                     );
431                                     JSAN.use('circ.util');
432                                     switch(r2) {
433                                         case 1:
434                                             circ.util.checkin_via_barcode( ses(), { 'barcode' : copies[i].barcode(), 'noop' : 1 } );
435                                         break;
436                                         case 2:
437                                             circ.util.checkin_via_barcode( ses(), { 'barcode' : copies[i].barcode(), 'noop' : 1 }, due_date );
438                                         break;
439                                     }
440                                 }
441                             }
442                         }
443
444                         var robj = network.simple_request('MARK_ITEM_DAMAGED',[ses(),copies[i].id()]);
445                         if (typeof robj.ilsevent != 'undefined') {
446                             switch(robj.textcode) {
447                                 case 'DAMAGE_CHARGE' :
448                                     var params = {};
449                                     JSAN.use('util.money');
450                                     var circ_obj = robj.payload.circ;
451                                     var patron_obj = circ_obj.usr();
452                                     JSAN.use('patron.util'); 
453                                     var patron_name = patron.util.format_name( patron_obj ) + ' : ' + patron_obj.card().barcode(); 
454                                     var r1 = error.yns_alert( 
455                                         $("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.charge_patron_prompt.message', [  
456                                             copies[i].barcode(),  
457                                             patron_name,  
458                                             util.date.formatted_date( circ_obj.checkin_time(), '%{localized}' ),
459                                             util.money.sanitize(robj.payload.charge) ]), 
460                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.title'), 
461                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.ok_label'), 
462                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.change_amount_label'), 
463                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.cancel_label'), 
464                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.confirm_action')); 
465                                     if (r1 == 0) {
466                                         params.apply_fines = 'apply';
467                                     } else if (r1 == 1) { 
468                                         JSAN.use('util.window'); var win = new util.window();
469                                         var my_xulG = win.open(
470                                             urls.XUL_PATRON_BILL_WIZARD,
471                                             'billwizard',
472                                             'chrome,resizable,modal',
473                                             { 
474                                                 'patron' : patron_obj, 
475                                                 'patron_id' : patron_obj.id(), 
476                                                 'circ' : circ_obj, 
477                                                 'xact_id' : circ_obj.id(), 
478                                                 'do_not_process_bill' : true,
479                                                 /* 'override_default_billing_type' : 7, FIXME: maybe reintroduce this with an org setting for the specific btype? */
480                                                 'override_default_price' : util.money.sanitize( robj.payload.charge ) 
481                                             }
482                                         );
483
484                                         params.apply_fines = my_xulG.proceed ? 'apply' : 'noapply';
485                                         if (my_xulG.proceed) {
486                                             params.override_amount = my_xulG.amount;
487                                             params.override_btype = my_xulG.cbt_id;
488                                             params.override_note = my_xulG.note;
489                                         }
490                                     } else {
491                                         params.apply_fines = 'noapply';
492                                     }
493                                     robj = network.simple_request('MARK_ITEM_DAMAGED',[ ses(), copies[i].id(), params ]);
494                                     if (typeof robj.ilsevent != 'undefined') { throw(robj); }
495                                     break;
496                                 default: throw(robj);
497                             }
498                         }
499                         count++;
500                     } catch(E) {
501                         error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.marking_error', [copies[i].barcode()]),E);
502                     }
503                 }
504                 alert(count == 1 ? $("catStrings").getString('staff.cat.util.mark_item_damaged.one_item_damaged') :
505                     $("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.multiple_item_damaged', [count]));
506             }
507         }
508
509     } catch(E) {
510         if (error) error.standard_unexpected_error_alert('cat.util.mark_item_damaged',E); else alert('FIXME: ' + E);
511     }
512 }
513
514 cat.util.mark_item_missing = function(copy_ids) {
515     var error;
516     try {
517         JSAN.use('util.error'); error = new util.error();
518         JSAN.use('util.functional');
519         JSAN.use('util.network'); var network = new util.network();
520         if (!copy_ids) { return; }
521         copy_ids = util.functional.filter_list( copy_ids, function(o) { return o != null; } );
522         if (copy_ids.length < 1) { return; }
523         var copies = network.simple_request('FM_ACP_FLESHED_BATCH_RETRIEVE.authoritative', [ copy_ids ]);
524         if (typeof copies.ilsevent != 'undefined') throw(copies);
525         var magic_status = false;
526         for (var i = 0; i < copies.length; i++) {
527             var status = copies[i].status(); if (typeof status == 'object') status = status.id();
528             if (typeof my_constants.magical_statuses[ status ] != 'undefined') 
529                 if (my_constants.magical_statuses[ status ].block_mark_item_action) magic_status = true;
530         }
531         if (magic_status) {
532         
533             error.yns_alert($("catStrings").getString('staff.cat.util.mark_item_missing.af_message'),
534                 $("catStrings").getString('staff.cat.util.mark_item_missing.af_title'),
535                 $("catStrings").getString('staff.cat.util.mark_item_missing.af_ok_label'), null, null,
536                 $("catStrings").getString('staff.cat.util.mark_item_missing.af_confirm_action'));
537
538         } else {
539
540             var r = error.yns_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_missing.ms_message', [util.functional.map_list( copies, function(o) { return o.barcode(); } ).join(", ")]),
541                 $("catStrings").getString('staff.cat.util.mark_item_missing.ms_title'),
542                 $("catStrings").getString('staff.cat.util.mark_item_missing.ms_ok_label'),
543                 $("catStrings").getString('staff.cat.util.mark_item_missing.ms_cancel_label'), null,
544                 $("catStrings").getString('staff.cat.util.mark_item_missing.ms_confirm_action'));
545
546             if (r == 0) {
547                 var count = 0;
548                 for (var i = 0; i < copies.length; i++) {
549                     try {
550                         var robj = network.simple_request('MARK_ITEM_MISSING',[ses(),copies[i].id()]);
551                         if (typeof robj.ilsevent != 'undefined') throw(robj);
552                         count++;
553                     } catch(E) {
554                         error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_missing.marking_error', [copies[i].barcode()]),E);
555                     }
556                 }
557                 alert(count == 1 ? $("catStrings").getString('staff.cat.util.mark_item_missing.one_item_missing') :
558                     $("catStrings").getFormattedString('staff.cat.util.mark_item_missing.multiple_item_missing', [count]));
559             }
560         }
561
562     } catch(E) {
563         if (error) error.standard_unexpected_error_alert('cat.util.mark_item_missing',E); else alert('FIXME: ' + E);
564     }
565 }
566
567 cat.util.fast_item_add = function(doc_id,cn_label,cp_barcode) {
568     var error;
569     JSAN.use('OpenILS.data'); var data = new OpenILS.data();
570     try {
571
572         JSAN.use('util.error'); error = new util.error();
573         JSAN.use('util.network'); var network = new util.network();
574
575         var acn_blob = network.simple_request(
576             'FM_ACN_FIND_OR_CREATE',
577             [ ses(), cn_label, doc_id, ses('ws_ou') ]
578         );
579
580         if (typeof acn_blob.ilsevent != 'undefined') {
581             error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.volume_copy_creator.stash_and_close.problem_with_volume', [cn]), acn_blob);
582             return;
583         }
584
585         // Get the default copy status; default to available if unset, per 1.6
586         var fast_ccs = data.hash.aous['cat.default_copy_status_fast'] || 0;
587
588         var copy_obj = new acp();
589         copy_obj.id( -1 );
590         copy_obj.isnew('1');
591         copy_obj.barcode( cp_barcode );
592         copy_obj.call_number( acn_blob.acn_id );
593         copy_obj.circ_lib( ses('ws_ou') );
594         /* FIXME -- use constants */
595         copy_obj.deposit(0);
596         copy_obj.price(0);
597         copy_obj.deposit_amount(0);
598         copy_obj.fine_level(2); // Normal
599         copy_obj.loan_duration(2); // Normal
600         copy_obj.location(1); // Stacks
601         copy_obj.status(fast_ccs);
602         copy_obj.circulate(get_db_true());
603         copy_obj.holdable(get_db_true());
604         copy_obj.opac_visible(get_db_true());
605         copy_obj.ref(get_db_false());
606         copy_obj.mint_condition(get_db_true());
607
608         JSAN.use('util.window'); var win = new util.window();
609         JSAN.use('cat.util');
610
611         var unified_interface = String( data.hash.aous['ui.unified_volume_copy_editor'] ) == 'true';
612         if (unified_interface) {
613             var horizontal_interface = String( data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
614             var url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
615             var w = xulG.set_tab(
616                 url,
617                 {
618                     'tab_name' : document.getElementById('offlineStrings').getFormattedString(
619                         'cat.bib_record',
620                         [ doc_id ]
621                     )
622                 },
623                 {
624                     'doc_id' : doc_id, 
625                     'existing_copies' : [ copy_obj ],
626                     'load_opac_when_done' : true,
627                     'labels_in_new_tab' : true
628                 }
629             );
630
631         } else {
632             return cat.util.spawn_copy_editor( { 'handle_update' : 1, 'edit' : 1, 'docid' : doc_id, 'copies' : [ copy_obj ] });
633         }
634
635     } catch(E) {
636         if (error) error.standard_unexpected_error_alert('cat.util.fast_item_add',E); else alert('FIXME: ' + E);
637     }
638 }
639
640 cat.util.make_bookable = function(copy_ids) {
641     if (!copy_ids) { return; }
642     copy_ids = util.functional.filter_list( copy_ids, function(o) { return o != null; } );
643     if (copy_ids.length < 1) { return; }
644     var results = fieldmapper.standardRequest(
645         ["open-ils.booking", "open-ils.booking.resources.create_from_copies"],
646         [ses(), copy_ids]
647     );
648     if (results == null) {
649         alert(document.getElementById("catStrings").getString(
650             "staff.cat.copy_browser.make_bookable.create_failed_silent"
651         ));
652     }
653     else if (typeof results.ilsevent != "undefined") {
654         alert(document.getElementById("catStrings").getFormattedString(
655             "staff.cat.copy_browser.make_bookable.create_failed",
656             [results.ilsevent, results.textcode, results.desc, results.debug]
657         ));
658     }
659     return results;
660 }
661
662 cat.util.edit_new_brsrc = function(brsrc_list) {
663     /* Spawn new tab to allow editing new resources. */
664     try {
665         xulG.resultant_brsrc = brsrc_list.map(function(o) { return o[0]; });
666         xulG.new_tab(
667             urls.XUL_BROWSER + "?url=" + window.escape(
668                 xulG.url_prefix("/eg/conify/global/booking/resource")
669             ), {
670                 "tab_name": offlineStrings.getString(
671                     "menu.cmd_booking_resource.tab"
672                  ),
673                 "browser" : true
674             }, {
675                 "no_xulG": false,
676                 "show_print_button": false,
677                 "show_nav_buttons": true,
678                 "passthru_content_params": xulG
679             }
680         );
681     } catch(E) {
682         alert(
683             document.getElementById("catStrings").getFormattedString(
684                 "staff.cat.copy_browser.make_bookable.newtab_failed"
685             ), E
686         );
687     }
688 }
689
690 cat.util.edit_new_bresv = function(booking_results) {
691     /* Spawn new tab to allow editing new reservations. */
692     try {
693         if (xulG.auth == undefined) {
694             xulG.auth = {"session": {"key": ses()}};
695         }
696         xulG.bresv_interface_opts = {"booking_results": booking_results};
697         xulG.new_tab(
698             xulG.url_prefix("/eg/booking/reservation"),
699             {
700                 "tab_name": offlineStrings.getString(
701                     "menu.cmd_booking_reservation.tab"
702                  ),
703                 "browser" : false
704             }, xulG
705         );
706     } catch(E) {
707         alert(
708             document.getElementById("catStrings").getString(
709                 "staff.cat.copy_browser.make_bookable.newtab_failed"
710             ) + E
711         );
712     }
713 }
714
715 cat.util.batch_edit_volumes = function(fleshed_volumes) {
716     try {
717         if (!fleshed_volumes || fleshed_volumes.length < 1) { return false; }
718
719         JSAN.use('util.functional');
720         JSAN.use('util.network'); var net = new util.network();
721         JSAN.use('util.window'); var win = new util.window();
722
723         var can_edit = net.simple_request(
724             'PERM_MULTI_ORG_CHECK',
725             [
726                 ses(),
727                 ses('staff_id'),
728                 util.functional.map_list(
729                     fleshed_volumes,
730                     function(v) {
731                         return v.owning_lib();
732                     }
733                 ),
734                 ['UPDATE_VOLUME']
735             ]
736         );
737         if (!can_edit) {
738             alert(document.getElementById('catStrings').getString('staff.cat.edit_volume.permission_error'));
739             return false;
740         }
741         var title;
742         if (fleshed_volumes.length == 1) {
743             title = document.getElementById('catStrings').getString('staff.cat.edit_volume.title');
744         } else {
745             title = document.getElementById('catStrings').getString('staff.cat.edit_volume.title.plural');
746         }
747
748         function clone_list(o) {
749             var list = JSON2js( js2JSON( o ) );
750             // now that it is safe to clear copies, let's do so, otherwise may get an error from volume edit method
751             for (var i = 0; i < list.length; i++) { list[i].copies( [] ); } 
752             return list;
753         }
754
755         var my_xulG = win.open(
756             xulG.url_prefix(urls.XUL_VOLUME_EDITOR),
757             title,
758             'chrome,modal,resizable',
759             { 'volumes' : clone_list( fleshed_volumes ) }
760         );
761
762         if (typeof my_xulG.update_these_volumes == 'undefined') { return false; }
763
764         var volumes = util.functional.filter_list(
765             my_xulG.volumes,
766             function(v) {
767                 return get_bool( v.ischanged() );
768             }
769         );
770
771         if (volumes.length < 1) { return false; }
772
773         volumes = util.functional.map_list( volumes, function(o){
774             if (typeof o.suffix() == 'object') { o.suffix( o.suffix().id() ); }
775             if (typeof o.prefix() == 'object') { o.prefix( o.prefix().id() ); }
776             if (typeof o.label_class() == 'object') { o.label_class( o.label_class().id() ); }
777             return o;
778         });
779
780         var r = net.simple_request(
781             'FM_ACN_TREE_UPDATE',
782             [ ses(), volumes, false, { 'auto_merge_vols' : my_xulG.auto_merge } ],
783             null,
784             {
785                 'title' : document.getElementById('catStrings').getString('staff.cat.edit_volumes.override.confirm'),
786                 'overridable_events' : [
787                     1705 /* VOLUME_LABEL_EXISTS */
788                 ],
789                 'text' : {
790                     '1705' : function(r) {
791                         var payload_acn = util.functional.find_id_object_in_list( volumes, r.payload );
792                         return document.getElementById('catStrings').getFormattedString('staff.cat.edit_volumes.label_exists.details',[payload_acn.label()]);
793                     }
794                 }
795             }
796         );
797         if (!r) { throw('Update method returned null or false.'); }
798         if (typeof r.ilsevent != 'undefined') {
799             if (r.ilsevent == 1705 /* VOLUME_LABEL_EXISTS */) {
800                /* not overriden, but otherwise handled, so ignore */
801                 return false;
802             } else {
803                 throw(r);
804             }
805         }
806
807         return true;
808
809     } catch(E) {
810         alert('Error in cat.util.batch_edit_volumes: ' + E);
811         return false;
812     }
813 }
814
815 cat.util.render_fine_level = function(value) {
816     var text;
817     switch(Number(value)){
818         case 1: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.fine_level.low"); break;
819         case 2: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.fine_level.normal"); break;
820         case 3: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.fine_level.high"); break; 
821     }
822     return text;
823 }
824 cat.util.render_loan_duration = function(value) {
825     var text;
826     switch(Number(value)){
827         case 1: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.loan_duration.short"); break;
828         case 2: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.loan_duration.normal"); break;
829         case 3: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.loan_duration.extended"); break;
830     }
831     return text;
832 }
833
834 cat.util.mark_item_as_missing_pieces = function(copy_ids) {
835     var error;
836     try {
837         JSAN.use('util.error'); error = new util.error();
838         JSAN.use('util.functional'); JSAN.use('util.date');
839         JSAN.use('util.network'); var network = new util.network();
840         JSAN.use('util.print'); var print = new util.print();
841         JSAN.use('util.window'); var win = new util.window();
842         if (!copy_ids) { return; }
843         copy_ids = util.functional.filter_list( copy_ids, function(o) { return o != null; } );
844         if (copy_ids.length < 1) { return; }
845         var copies = network.simple_request('FM_ACP_FLESHED_BATCH_RETRIEVE.authoritative', [ copy_ids ]);
846         if (typeof copies.ilsevent != 'undefined') throw(copies);
847
848         var r = error.yns_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_missing_pieces.ms_message', [util.functional.map_list( copies, function(o) { return o.barcode(); } ).join(", ")]),
849             $("catStrings").getString('staff.cat.util.mark_item_missing_pieces.ms_title'),
850             $("catStrings").getString('staff.cat.util.mark_item_missing_pieces.ms_ok_label'),
851             $("catStrings").getString('staff.cat.util.mark_item_missing_pieces.ms_cancel_label'), null,
852             $("catStrings").getString('staff.cat.util.mark_item_missing_pieces.ms_confirm_action'));
853
854         if (r == 0) {
855             var count = 0;
856             JSAN.use('cat.util');
857             for (var i = 0; i < copies.length; i++) {
858                 try {
859                     var robj = network.simple_request('MARK_ITEM_MISSING_PIECES',[ses(),copies[i].id()]);
860                     if (typeof robj.ilsevent != 'undefined') {
861                         if (robj.ilsevent == 0 /* SUCCESS */) {
862                             count++;
863                             // Print Slip
864                             if (robj.payload && robj.payload.slip) {
865                                 print.simple( robj.payload.slip.template_output().data() );
866                             }
867                             // Item Note
868                             cat.util.spawn_copy_editor( { 'copy_ids' : [ copies[i].id() ], 'edit' : 1 } );
869                             // Patron Message
870                             var my_xulG = win.open(
871                                 urls.XUL_NEW_STANDING_PENALTY,
872                                 'new_standing_penalty',
873                                 'chrome,resizable,modal',
874                                 {}
875                             );
876                             if (my_xulG.id) {
877                                 var penalty = new ausp();
878                                 penalty.usr( robj.payload.circ.usr() );
879                                 penalty.isnew( 1 );
880                                 penalty.standing_penalty( my_xulG.id );
881                                 penalty.org_unit( ses('ws_ou') );
882                                 penalty.note( my_xulG.note );
883                                 network.simple_request(
884                                     'FM_AUSP_APPLY',
885                                     [ ses(), penalty ]
886                                 );
887                             }
888                             // Patron Letter
889
890                             var txt_file = new util.file('letter.txt');
891                             txt_file.write_content('truncate',robj.payload.letter.template_output().data());
892                             var text_path = '"' + txt_file._file.path + '"';
893                             txt_file.close();
894
895                             var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces['nsIPrefBranch']);
896                             var key = 'oils.text_editor.external.cmd';
897                             var has_key = prefs.prefHasUserValue(key);
898                             var oils_external_letter_opener_cmd = has_key ? prefs.getCharPref(key) : 'C:\\Windows\\notepad.exe %letter.txt%';
899
900                             var cmd = oils_external_letter_opener_cmd.replace('%letter.txt%',text_path);
901
902                             var file = new util.file('letter.bat');
903                             file.write_content('truncate+exec',cmd);
904                             file.close();
905                             file = new util.file('letter.bat');
906
907                             dump('letter exec: ' + cmd + '\n');
908                             var process = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
909                             process.init(file._file);
910
911                             var args = [];
912
913                             dump('process.run = ' + process.run(false, args, args.length) + '\n');
914
915                             file.close();
916
917                         } else if (robj.ilsevent == 1500 /* ACTION_CIRCULATION_NOT_FOUND */) {
918                             alert( $("catStrings").getFormattedString('staff.cat.util.mark_item_missing_pieces.circ_not_found',[ copies[i].barcode() ]) );
919                         } else {
920                             throw(robj);
921                         }
922                     } else {
923                         throw(robj);
924                     }
925                 } catch(E) {
926                     error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_missing_pieces.marking_error', [copies[i].barcode()]),E);
927                 }
928             }
929             /*alert(count == 1 ? $("catStrings").getString('staff.cat.util.mark_item_missing_pieces.one_item_missing_pieces') :
930                 $("catStrings").getFormattedString('staff.cat.util.mark_item_missing_pieces.multiple_item_missing_pieces', [count]));*/
931         }
932
933         return true;
934     } catch(E) {
935         alert('Error in cat.util.mark_item_as_missing_pieces: ' + E);
936         return false;
937     }
938 }
939
940 cat.util.render_callnumbers_for_bib_menu = function(node, doc_id, label_class) {
941     try {
942         var cn_blob;
943         try {
944             cn_blob = g.network.simple_request('BLOB_MARC_CALLNUMBERS_RETRIEVE',[doc_id, label_class]);
945         } catch(E) {
946             cn_blob = [];
947         }
948         var hbox = typeof node == 'string' ? document.getElementById(node) : node;
949         JSAN.use('util.widgets');
950         JSAN.use('util.functional');
951         var ml = util.widgets.make_menulist(
952             [
953                 [ '', '' ]
954             ].concat(
955                 util.functional.map_list(
956                     cn_blob,
957                     function(o) {
958                         for (var i in o) {
959                             return [ o[i], i ];
960                         }
961                     }
962                 )
963             )
964         ); hbox.appendChild(ml);
965         ml.setAttribute('editable','true');
966         ml.setAttribute('width', '200');
967         ml.setAttribute('id', hbox.id + '_menulist');
968     } catch(E) {
969         alert('Error in cat.util.render_callnumbers_for_bib_menu: ' + E);
970     }
971 }
972
973 cat.util.render_cn_prefix_menuitems = function(menupopup,ou_id) {
974     try {
975         JSAN.use('OpenILS.data');
976         var data = new OpenILS.data(); data.stash_retrieve();
977         JSAN.use('util.network');
978         var network = new util.network();
979
980         if (typeof data.list['acnp_for_lib_'+ou_id] == 'undefined') {
981             data.list['acnp_for_lib_'+ou_id] = network.simple_request(
982                 'FM_ACNP_RETRIEVE_VIA_PCRUD',
983                 [ ses(), {"owning_lib":{"=":ou_id}}, {"order_by":{"acnp":"label_sortkey"}} ]
984             );
985             data.stash('list');
986         }
987         for (var i = 0; i < data.list['acnp_for_lib_'+ou_id].length; i++) {
988             var my_acnp = data.list['acnp_for_lib_'+ou_id][i];
989             var menuitem = document.createElement('menuitem');
990             menupopup.appendChild(menuitem);
991                 menuitem.setAttribute(
992                     'label',
993                     my_acnp.id() == -1 ? '' :
994                     $('catStrings').getFormattedString(
995                         'staff.cat.volume_copy_creator.call_number_prefix.menuitem_label',
996                         [
997                             my_acnp.label(),
998                             data.hash.aou[ ou_id ].shortname()
999                         ]
1000                     )
1001                 );
1002                 menuitem.setAttribute('value',my_acnp.id());
1003         }
1004     } catch(E) {
1005         alert('Error in cat.util.render_cn_prefix_menuitems: ' + E);
1006     }
1007 }
1008
1009 cat.util.render_cn_suffix_menuitems = function(menupopup,ou_id) {
1010     try {
1011         JSAN.use('OpenILS.data');
1012         var data = new OpenILS.data(); data.stash_retrieve();
1013         JSAN.use('util.network');
1014         var network = new util.network();
1015
1016         if (typeof data.list['acns_for_lib_'+ou_id] == 'undefined') {
1017             data.list['acns_for_lib_'+ou_id] = network.simple_request(
1018                 'FM_ACNS_RETRIEVE_VIA_PCRUD',
1019                 [ ses(), {"owning_lib":{"=":ou_id}}, {"order_by":{"acns":"label_sortkey"}} ]
1020             );
1021             data.stash('list');
1022         }
1023         for (var i = 0; i < data.list['acns_for_lib_'+ou_id].length; i++) {
1024             var my_acns = data.list['acns_for_lib_'+ou_id][i];
1025             var menuitem = document.createElement('menuitem');
1026             menupopup.appendChild(menuitem);
1027                 menuitem.setAttribute(
1028                     'label',
1029                     my_acns.id() == -1 ? '' :
1030                     $('catStrings').getFormattedString(
1031                         'staff.cat.volume_copy_creator.call_number_suffix.menuitem_label',
1032                         [
1033                             my_acns.label(),
1034                             data.hash.aou[ ou_id ].shortname()
1035                         ]
1036                     )
1037                 );
1038                 menuitem.setAttribute('value',my_acns.id());
1039         }
1040     } catch(E) {
1041         alert('Error in cat.util.render_cn_suffix_menuitems: ' + E);
1042     }
1043 }
1044
1045 cat.util.render_cn_class_menu = function(extra_menuitems,menu_default) {
1046     try {
1047         JSAN.use('util.widgets');
1048         JSAN.use('OpenILS.data');
1049         var data = new OpenILS.data(); data.stash_retrieve();
1050
1051         var menulist = util.widgets.make_menulist(
1052             (extra_menuitems || []).concat(
1053                 util.functional.map_list(
1054                     data.list.acnc,
1055                     function(o) {
1056                         return [ o.name(), o.id() ];
1057                     }
1058                 )
1059             )
1060         );
1061
1062         if (typeof menu_default != 'undefined') {
1063             menulist.setAttribute('value',menu_default);
1064         }
1065         return menulist;
1066
1067     } catch(E) {
1068         alert('Error in cat.util.render_cn_class_menu: ' + E);
1069     }
1070 }
1071
1072 cat.util.render_cn_prefix_menu = function(ou_ids,extra_menuitems,menu_default) {
1073     try {
1074         JSAN.use('util.widgets');
1075         var menulist = util.widgets.make_menulist(extra_menuitems||[],menu_default);
1076             var menupopup = menulist.firstChild;
1077             var org_list;
1078             if (ou_ids.length == 1) {
1079                 JSAN.use('OpenILS.data');
1080                 var data = new OpenILS.data(); data.stash_retrieve();
1081                 var org = data.hash.aou[ ou_ids[0] ];
1082                 org_list = []; // order from top of consortium to owning lib
1083                 while(org) {
1084                     org_list.unshift(org.id());
1085                     org = org.parent_ou();
1086                     if (org && typeof org != 'object') {
1087                         org = data.hash.aou[ org ];
1088                     }
1089                 }
1090             } else {
1091                 org_list = ou_ids;
1092             }
1093             for (var i = 0; i < org_list.length; i++) {
1094                 cat.util.render_cn_prefix_menuitems(menupopup,org_list[i]);
1095             }
1096         if (typeof menu_default != 'undefined') {
1097             menulist.setAttribute('value',menu_default);
1098         }
1099         return menulist;
1100     } catch(E) {
1101         alert('Error in cat.util.render_cn_prefix_menu('+ou_id+'): ' + E);
1102     }
1103 }
1104
1105 cat.util.render_cn_suffix_menu = function(ou_ids,extra_menuitems,menu_default) {
1106     try {
1107         JSAN.use('util.widgets');
1108         var menulist = util.widgets.make_menulist(extra_menuitems||[],menu_default);
1109             var menupopup = menulist.firstChild;
1110             var org_list;
1111             if (ou_ids.length == 1) {
1112                 JSAN.use('OpenILS.data');
1113                 var data = new OpenILS.data(); data.stash_retrieve();
1114                 var org = data.hash.aou[ ou_ids[0] ];
1115                 org_list = []; // order from top of consortium to owning lib
1116                 while(org) {
1117                     org_list.unshift(org.id());
1118                     org = org.parent_ou();
1119                     if (org && typeof org != 'object') {
1120                         org = data.hash.aou[ org ];
1121                     }
1122                 }
1123             } else {
1124                 org_list = ou_ids;
1125             }
1126             for (var i = 0; i < org_list.length; i++) {
1127                 cat.util.render_cn_suffix_menuitems(menupopup,org_list[i]);
1128             }
1129         if (typeof menu_default != 'undefined') {
1130             menulist.setAttribute('value',menu_default);
1131         }
1132         return menulist;
1133     } catch(E) {
1134         alert('Error in cat.util.render_cn_suffix_menu('+ou_id+'): ' + E);
1135     }
1136 }
1137
1138 cat.util.request_items = function(copy_ids) {
1139     var error;
1140     try {
1141         JSAN.use('util.error');
1142         error = new util.error();
1143
1144         JSAN.use('util.functional');
1145         if (!copy_ids) { return; }
1146         copy_ids = util.functional.filter_list(
1147             copy_ids,
1148             function(o) { return o != null; }
1149         );
1150         if (copy_ids.length < 1) { return; }
1151
1152         xulG.new_tab(
1153             urls.XUL_HOLD_PLACEMENT,
1154             {},
1155             {
1156                 'copy_ids' : copy_ids
1157             }
1158         );
1159
1160     } catch(E) {
1161         alert('Error in cat.util.request_items: ' + E);
1162     }
1163 }
1164
1165 cat.util.mark_for_overlay = function(doc_id,doc_mvr) {
1166
1167     try {
1168
1169         JSAN.use('OpenILS.data'); var data = new OpenILS.data();
1170         data.stash_retrieve();
1171         JSAN.use('util.network'); var network = new util.network();
1172
1173         function gen_statusbar_click_handler(data_key) {
1174             return function (ev) {
1175
1176                 if (! data[data_key]) {
1177                     return;
1178                 }
1179
1180                 if (ev.button == 0 /* left click, spawn opac */) {
1181                     var opac_url = xulG.url_prefix( urls.opac_rdetail )
1182                         + data[data_key];
1183                     var content_params = {
1184                         'session' : ses(),
1185                         'authtime' : ses('authtime'),
1186                         'opac_url' : opac_url,
1187                     };
1188                     xulG.new_tab(
1189                         xulG.url_prefix(urls.XUL_OPAC_WRAPPER),
1190                         {'tab_name':'Retrieving title...'},
1191                         content_params
1192                     );
1193                 }
1194
1195                 if (ev.button == 2 /* right click, remove mark */) {
1196                     if ( window.confirm( $('offlineStrings').getString(
1197                             'cat.opac.clear_statusbar')
1198                     ) ) {
1199                         data[data_key] = null;
1200                         data.stash(data_key);
1201                         ev.target.setAttribute('label','');
1202                         if (ev.target.hasAttribute('tooltiptext')) {
1203                             ev.target.removeAttribute('tooltiptext');
1204                         }
1205                     }
1206                 }
1207             }
1208         }
1209
1210         data.marked_record = doc_id;
1211         data.stash('marked_record');
1212         if (!doc_mvr) {
1213             var robj = network.simple_request(
1214                 'MODS_SLIM_RECORD_RETRIEVE.authoritative',[doc_id]);
1215             if (typeof robj.ilsevent == 'undefined') {
1216                 data.marked_record_mvr = robj;
1217             } else {
1218                 data.marked_record_mvr = null;
1219                 alert('Error in cat.util.mark_for_overlay #2: ', js2JSON(robj));
1220             }
1221         } else {
1222             data.marked_record_mvr = doc_mvr;
1223         }
1224         data.stash('marked_record_mvr');
1225         if (data.marked_record_mvr) {
1226             alert(
1227                 $('offlineStrings').getFormattedString(
1228                     'cat.opac.record_marked_for_overlay.tcn.alert',
1229                     [ data.marked_record_mvr.tcn() ]
1230                 )
1231             );
1232             xulG.set_statusbar(
1233                 1,
1234                 $("offlineStrings").getFormattedString(
1235                     'staff.cat.z3950.marked_record_for_overlay_indicator.tcn.label',
1236                     [data.marked_record_mvr.tcn()]
1237                 ),
1238                 $("offlineStrings").getFormattedString(
1239                     'staff.cat.z3950.marked_record_for_overlay_indicator.record_id.label',
1240                     [data.marked_record]
1241                 ),
1242                 gen_statusbar_click_handler('marked_record')
1243             );
1244         } else {
1245             alert(
1246                 $('offlineStrings').getFormattedString(
1247                     'cat.opac.record_marked_for_overlay.record_id.alert',
1248                     [ data.marked_record  ]
1249                 )
1250             );
1251             xulG.set_statusbar(
1252                 1,
1253                 $("offlineStrings").getFormattedString(
1254                     'staff.cat.z3950.marked_record_for_overlay_indicator.record_id.label',
1255                     [data.marked_record]
1256                 ),
1257                 '',
1258                 gen_statusbar_click_handler('marked_record')
1259             );
1260         }
1261     } catch(E) {
1262         alert('Error in cat.util.mark_for_overlay(): ' + E);
1263     }
1264 }
1265
1266 cat.util.get_cbs_for_bre_id = function(doc_id) {
1267     try {
1268         JSAN.use('util.network'); var network = new util.network();
1269         var bibObj = network.simple_request(
1270             'FM_BRE_RETRIEVE_VIA_ID',
1271             [ ses(), [ doc_id ] ]
1272         );
1273         bibObj = bibObj[0];
1274         var cbsObj = network.simple_request(
1275             'FM_CBS_RETRIEVE_VIA_PCRUD',
1276             [ ses(), bibObj.source() ]
1277         );
1278         return cbsObj;
1279     } catch(E) {
1280         alert('Error in cat.util.cbs_can_have_copies(): ' + E);
1281     }
1282 }
1283
1284 dump('exiting cat/util.js\n');