]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/patron/holds.js
wire up un-cancel hold action in the staff client
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / patron / holds.js
1 dump('entering patron.holds.js\n');
2
3 function $(id) { return document.getElementById(id); }
4
5 if (typeof patron == 'undefined') patron = {};
6 patron.holds = function (params) {
7
8     JSAN.use('util.error'); this.error = new util.error();
9     JSAN.use('util.network'); this.network = new util.network();
10     JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
11 }
12
13 patron.holds.prototype = {
14
15     'hold_interface_type' : null,
16
17     'pull_from_shelf_interface' : {
18         '_default' : { 'limit' : 50, 'offset' : 0 },
19         'current' : { 'limit' : 50, 'offset' : 0 }
20     },
21
22     'filter_lib' : null,
23
24     'retrieve_ids' : [],
25
26     'holds_map' : {},
27
28     'flatten_copy' : function(hold) {
29         try { if ( hold.current_copy() && typeof hold.current_copy() == 'object') hold.current_copy( hold.current_copy().id() ); } catch(E) { alert('FIXME: Error flattening hold before hold update: ' + E); }
30         return hold;
31     },
32
33     'init' : function( params ) {
34
35         var obj = this;
36
37         obj.patron_id = params['patron_id'];
38         obj.patron_barcode = params['patron_barcode'];
39         obj.docid = params['docid'];
40         obj.shelf = params['shelf'];
41         obj.tree_id = params['tree_id'];
42
43         var progressmeter = document.getElementById('progress');
44
45         JSAN.use('circ.util');
46         var columns = circ.util.hold_columns(
47             {
48                 'title' : { 'hidden' : false, 'flex' : '3' },
49                 'request_time' : { 'hidden' : false },
50                 'pickup_lib_shortname' : { 'hidden' : false },
51                 'hold_type' : { 'hidden' : false },
52                 'current_copy' : { 'hidden' : false },
53                 'capture_time' : { 'hidden' : false },
54                 'notify_time' : { 'hidden' : false },
55                 'notify_count' : { 'hidden' : false },
56                 'cancel_cause' : { 'hidden' : ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) },
57                 'cancel_note' : { 'hidden' :  ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) },
58                 'cancel_time' : { 'hidden' :  ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) }
59             }
60         );
61
62         JSAN.use('util.list'); obj.list = new util.list( obj.tree_id || 'holds_list');
63         obj.list.init(
64             {
65                 'columns' : columns,
66                 'map_row_to_columns' : circ.util.std_map_row_to_columns(),
67                 'retrieve_row' : function(params) {
68                     var row = params.row;
69                     try {
70                         obj.network.simple_request('FM_AHR_BLOB_RETRIEVE.authoritative', [ ses(), row.my.hold_id ],
71                             function(blob_req) {
72                                 try {
73                                     var blob = blob_req.getResultObject();
74                                     if (typeof blob.ilsevent != 'undefined') throw(blob);
75                                     row.my.ahr = blob.hold;
76                                     row.my.status = blob.status;
77                                                                         row.my.ahr.status( blob.status );
78                                     row.my.acp = blob.copy;
79                                     row.my.acn = blob.volume;
80                                     row.my.mvr = blob.mvr;
81                                     row.my.patron_family_name = blob.patron_last;
82                                     row.my.patron_first_given_name = blob.patron_first;
83                                     row.my.patron_barcode = blob.patron_barcode;
84                                                                         row.my.total_holds = blob.total_holds;
85                                                                         row.my.queue_position = blob.queue_position;
86                                                                         row.my.potential_copies = blob.potential_copies;
87                                                                         row.my.estimated_wait = blob.estimated_wait;
88                                                                         row.my.ahrn_count = blob.hold.notes().length;
89
90                                     var copy_id = row.my.ahr.current_copy();
91                                     if (typeof copy_id == 'object') {
92                                         if (copy_id == null) {
93                                             if (typeof row.my.acp == 'object' && row.my.acp != null) copy_id = row.my.acp.id();
94                                         } else {
95                                             copy_id = copy_id.id();
96                                         }
97                                     } else {
98                                         copy_id = row.my.acp.id();
99                                     }
100
101                                     obj.holds_map[ row.my.ahr.id() ] = blob;
102                                     params.row_node.setAttribute('retrieve_id',
103                                         js2JSON({
104                                             'copy_id':copy_id,
105                                                                                         'barcode':row.my.acp ? row.my.acp.barcode() : null,
106                                             'id':row.my.ahr.id(),
107                                             'type':row.my.ahr.hold_type(),
108                                             'target':row.my.ahr.target(),
109                                             'usr':row.my.ahr.usr()
110                                         })
111                                     );
112                                     if (typeof params.on_retrieve == 'function') { params.on_retrieve(row); }
113
114                                 } catch(E) {
115                                     obj.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.holds.init.hold_num_error', [row.my.hold_id]), E);
116                                 }
117                             }
118                         );
119                     } catch(E) {
120                         obj.error.sdump('D_ERROR','retrieve_row: ' + E );
121                     }
122                     return row;
123                 },
124                 'on_select' : function(ev) {
125                     JSAN.use('util.functional');
126                     var sel = obj.list.retrieve_selection();
127                     obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
128                     obj.retrieve_ids = util.functional.map_list(
129                         sel,
130                         function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
131                     );
132                     if (obj.retrieve_ids.length > 0) {
133                         obj.controller.view.sel_mark_items_damaged.setAttribute('disabled','false');
134                         obj.controller.view.sel_mark_items_missing.setAttribute('disabled','false');
135                         obj.controller.view.sel_copy_details.setAttribute('disabled','false');
136                         obj.controller.view.sel_patron.setAttribute('disabled','false');
137                         obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','false');
138                         obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','false');
139                         obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','false');
140                         obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','false');
141                         obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','false');
142                         obj.controller.view.cmd_holds_edit_expire_time.setAttribute('disabled','false');
143                         obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','false');
144                         obj.controller.view.cmd_holds_activate.setAttribute('disabled','false');
145                         obj.controller.view.cmd_holds_suspend.setAttribute('disabled','false');
146                         obj.controller.view.cmd_alt_view.setAttribute('disabled','false');
147                         obj.controller.view.cmd_holds_retarget.setAttribute('disabled','false');
148                         obj.controller.view.cmd_holds_cancel.setAttribute('disabled','false');
149                         obj.controller.view.cmd_holds_uncancel.setAttribute('disabled','false');
150                         obj.controller.view.cmd_show_catalog.setAttribute('disabled','false');
151                     } else {
152                         obj.controller.view.sel_mark_items_damaged.setAttribute('disabled','true');
153                         obj.controller.view.sel_mark_items_missing.setAttribute('disabled','true');
154                         obj.controller.view.sel_copy_details.setAttribute('disabled','true');
155                         obj.controller.view.sel_patron.setAttribute('disabled','true');
156                         obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
157                         obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
158                         obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
159                         obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
160                         obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
161                         obj.controller.view.cmd_holds_edit_expire_time.setAttribute('disabled','true');
162                         obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','true');
163                         obj.controller.view.cmd_holds_activate.setAttribute('disabled','true');
164                         obj.controller.view.cmd_holds_suspend.setAttribute('disabled','true');
165                         obj.controller.view.cmd_alt_view.setAttribute('disabled','true');
166                         obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
167                         obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
168                         obj.controller.view.cmd_holds_uncancel.setAttribute('disabled','true');
169                         obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
170                     }
171                 }
172             }
173         );
174
175         JSAN.use('util.controller'); obj.controller = new util.controller();
176         obj.controller.init(
177             {
178                 'control_map' : {
179                     'save_columns' : [ [ 'command' ], function() { obj.list.save_columns(); } ],
180                     'sel_clip' : [
181                         ['command'],
182                         function() { obj.list.clipboard(); }
183                     ],
184                     'cmd_broken' : [
185                         ['command'],
186                         function() { alert($("commonStrings").getString('common.unimplemented')); }
187                     ],
188                     'sel_patron' : [
189                         ['command'],
190                         function() {
191                             JSAN.use('circ.util');
192                             circ.util.show_last_few_circs(obj.retrieve_ids);
193                         }
194                     ],
195                     'alt_view_btn' : [
196                         ['render'],
197                         function(e) {
198                             e.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.label'));
199                             e.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.accesskey'));
200                         }
201                     ],
202                     'cmd_alt_view' : [
203                         ['command'],
204                         function(ev) {
205                             try {
206                                 var n = obj.controller.view.alt_view_btn;
207                                 if (n.getAttribute('toggle') == '1') {
208                                     document.getElementById('deck').selectedIndex = 0;
209                                     n.setAttribute('toggle','0');
210                                     n.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.label'));
211                                     n.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.accesskey'));
212                                 } else {
213                                     document.getElementById('deck').selectedIndex = 1;
214                                     n.setAttribute('toggle','1');
215                                     n.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.list_view.label'));
216                                     n.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.list_view.accesskey'));
217                                     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
218                                     if (obj.retrieve_ids.length == 0) return;
219                                     var f = obj.browser.get_content();
220                                     xulG.ahr_id = obj.retrieve_ids[0].id;
221                                     xulG.blob = obj.holds_map[ xulG.ahr_id ];
222                                     xulG.patron_rendered_elsewhere = (obj.hold_interface_type == 'patron');
223                                     xulG.bib_rendered_elsewhere = (obj.hold_interface_type == 'record');
224                                     f.xulG = xulG;
225                                     f.fetch_and_render_all();
226                                 }
227                             } catch(E) {
228                                 alert('Error in holds.js, cmd_alt_view handler: ' + E);
229                             }
230                         },
231                     ],
232                     'sel_mark_items_damaged' : [
233                         ['command'],
234                         function() {
235                             JSAN.use('cat.util'); JSAN.use('util.functional');
236                             cat.util.mark_item_damaged( util.functional.map_list( obj.retrieve_ids, function(o) { return o.copy_id; } ) );
237                         }
238                     ],
239                     'sel_mark_items_missing' : [
240                         ['command'],
241                         function() {
242                             JSAN.use('cat.util'); JSAN.use('util.functional');
243                             cat.util.mark_item_missing( util.functional.map_list( obj.retrieve_ids, function(o) { return o.copy_id; } ) );
244                         }
245                     ],
246                     'sel_copy_details' : [
247                         ['command'],
248                         function() {
249                             JSAN.use('circ.util');
250                             for (var i = 0; i < obj.retrieve_ids.length; i++) {
251                                 if (obj.retrieve_ids[i].copy_id) circ.util.show_copy_details( obj.retrieve_ids[i].copy_id );
252                             }
253                         }
254                     ],
255
256                     'cmd_holds_print' : [
257                         ['command'],
258                         function() {
259                             try {
260                                 JSAN.use('patron.util');
261                                 var params = {
262                                     'patron' : patron.util.retrieve_au_via_id(ses(),obj.patron_id),
263                                     'template' : 'holds'
264                                 };
265                                 obj.list.print(params);
266                             } catch(E) {
267                                 obj.error.standard_unexpected_error_alert('print 1',E);
268                             }
269                         }
270                     ],
271                     'cmd_csv_to_clipboard' : [ ['command'], function() { obj.list.dump_csv_to_clipboard(); } ],
272                     'cmd_csv_to_printer' : [ ['command'], function() { obj.list.dump_csv_to_printer(); } ],
273                     'cmd_csv_to_file' : [ ['command'], function() { obj.list.dump_csv_to_file( { 'defaultFileName' : 'holds.txt' } ); } ],
274
275                     'cmd_holds_edit_selection_depth' : [
276                         ['command'],
277                         function() {
278                             try {
279                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
280                                 var ws_type = obj.data.hash.aout[ obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ].ou_type() ];
281                                 var list = util.functional.map_list(
282                                     util.functional.filter_list(
283                                         obj.data.list.aout,
284                                         function(o) {
285                                             if (o.depth() > ws_type.depth()) return false;
286                                             if (o.depth() < ws_type.depth()) return true;
287                                             return (o.id() == ws_type.id());
288                                         }
289                                     ),
290                                     function(o) {
291                                         return [
292                                             o.opac_label(),
293                                             o.id(),
294                                             false,
295                                             ( o.depth() * 2),
296                                         ];
297                                     }
298                                 );
299                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
300                                 ml.setAttribute('id','selection');
301                                 ml.setAttribute('name','fancy_data');
302                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
303                                 xml += '<description>' + $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.choose_hold_range') + '</description>';
304                                 xml += util.widgets.serialize_node(ml);
305                                 xml += '</vbox>';
306                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
307                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.done.label') +'"';
308                                 bot_xml += 'accesskey="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.done.accesskey') +'" name="fancy_submit"/>';
309                                 bot_xml += '<button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.cancel.label') +'"';
310                                 bot_xml += 'accesskey="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.cancel.accesskey') +'" name="fancy_cancel"/></hbox>';
311                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
312                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
313                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
314                                 JSAN.use('util.window'); var win = new util.window();
315                                 var fancy_prompt_data = win.open(
316                                     urls.XUL_FANCY_PROMPT,
317                                     //+ '?xml_in_stash=temp_mid'
318                                     //+ '&bottom_xml_in_stash=temp_bot'
319                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
320                                     'fancy_prompt', 'chrome,resizable,modal',
321                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.choose_library') }
322                                 );
323                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
324                                 var selection = fancy_prompt_data.selection;
325
326                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
327                                 var msg = '';
328                                 if(obj.retrieve_ids.length > 1) {
329                                     msg = $("patronStrings").getformattedString('staff.patron.holds.holds_edit_selection_depth.modify_holds_message.plural', [hold_list.join(', '), obj.data.hash.aout[selection].opac_label()])
330                                 } else {
331                                     msg = $("patronStrings").getformattedString('staff.patron.holds.holds_edit_selection_depth.modify_holds_message.singular', [hold_list.join(', '), obj.data.hash.aout[selection].opac_label()])
332                                 }
333
334                                 var r = obj.error.yns_alert(msg,
335                                         $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.modify_holds_title'),
336                                         $("commonStrings").getString('common.yes'),
337                                         $("commonStrings").getString('common.no'),
338                                         null,
339                                         $("commonStrings").getString('common.check_to_confirm')
340                                 );
341                                 if (r == 0) {
342                                     circ.util.batch_hold_update(hold_list, { 'selection_depth' : obj.data.hash.aout[selection].depth() }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
343                                 }
344                             } catch(E) {
345                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
346                             }
347                         }
348                     ],
349
350                     'cmd_holds_edit_pickup_lib' : [
351                         ['command'],
352                         function() {
353                             try {
354                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
355
356                                 var deny_edit_because_of_transit = false;
357                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
358                                     var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
359                                     if (hold.status() == 3 /* In-Transit */) deny_edit_because_of_transit = true;
360                                 }
361                                 if (deny_edit_because_of_transit) {
362                                     alert(document.getElementById('circStrings').getString('staff.circ.holds.error.may_not_edit_pickup_lib_for_hold_intransit'));
363                                     return;
364                                 }
365
366                                 var list = util.functional.map_list(
367                                     obj.data.list.aou,
368                                     function(o) {
369                                         var sname = o.shortname(); for (i = sname.length; i < 20; i++) sname += ' ';
370                                         return [
371                                             o.name() ? sname + ' ' + o.name() : o.shortname(),
372                                             o.id(),
373                                             ( obj.data.hash.aout[ o.ou_type() ].can_have_users() == 0),
374                                             ( obj.data.hash.aout[ o.ou_type() ].depth() * 2),
375                                         ];
376                                     }
377                                 );
378                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
379                                 ml.setAttribute('id','lib');
380                                 ml.setAttribute('name','fancy_data');
381                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
382                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.new_pickup_lib.description')+'</description>';
383                                 xml += util.widgets.serialize_node(ml);
384                                 xml += '</vbox>';
385                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
386                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.done.label') +'"';
387                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.done.accesskey')+'" name="fancy_submit"/>';
388                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.cancel.label')+'"';
389                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
390                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
391                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
392                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
393                                 JSAN.use('util.window'); var win = new util.window();
394                                 var fancy_prompt_data = win.open(
395                                     urls.XUL_FANCY_PROMPT,
396                                     //+ '?xml_in_stash=temp_mid'
397                                     //+ '&bottom_xml_in_stash=temp_bot'
398                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
399                                     'fancy_prompt', 'chrome,resizable,modal',
400                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.choose_lib') }
401                                 );
402                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
403                                 var pickup_lib = fancy_prompt_data.lib;
404
405                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
406                                 var msg = '';
407                                 if(obj.retrieve_ids.length > 1) {
408                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_pickup_lib.change_pickup_lib_message.plural',[hold_list.join(', '), obj.data.hash.aou[pickup_lib].shortname()]);
409                                 } else {
410                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_pickup_lib.change_pickup_lib_message.singular',[hold_list.join(', '), obj.data.hash.aou[pickup_lib].shortname()]);
411                                 }
412                                 var r = obj.error.yns_alert(msg,
413                                         $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.change_pickup_lib_title'),
414                                         $("commonStrings").getString('common.yes'),
415                                         $("commonStrings").getString('common.no'),
416                                         null,
417                                         $("commonStrings").getString('common.check_to_confirm')
418                                 );
419                                 if (r == 0) {
420                                     circ.util.batch_hold_update(hold_list, { 'pickup_lib' : pickup_lib }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
421                                 }
422                             } catch(E) {
423                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
424                             }
425                         }
426                     ],
427                     'cmd_holds_edit_phone_notify' : [
428                         ['command'],
429                         function() {
430                             try {
431                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
432                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.new_phone_number')+'</description>';
433                                 xml += '<textbox id="phone" name="fancy_data" context="clipboard"/>';
434                                 xml += '</vbox>';
435                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
436                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_done.label')+'"';
437                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_done.accesskey')+'" name="fancy_submit"/>';
438                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_cancel.label')+'"';
439                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
440                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
441                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
442                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
443                                 JSAN.use('util.window'); var win = new util.window();
444                                 var fancy_prompt_data = win.open(
445                                     urls.XUL_FANCY_PROMPT,
446                                     //+ '?xml_in_stash=temp_mid'
447                                     //+ '&bottom_xml_in_stash=temp_bot'
448                                     //+ '&title=' + window.escape('Choose a Hold Notification Phone Number')
449                                     //+ '&focus=phone',
450                                     'fancy_prompt', 'chrome,resizable,modal',
451                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.choose_phone_number'), 'focus' : 'phone' }
452                                 );
453                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
454                                 var phone = fancy_prompt_data.phone;
455
456                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
457                                 var msg = '';
458                                 if(obj.retrieve_ids.length > 1) {
459                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_phone_notify.confirm_phone_number_change.plural',[hold_list.join(', '), phone]);
460                                 } else {
461                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_phone_notify.confirm_phone_number_change.singular',[hold_list.join(', '), phone]);
462                                 }
463                                 var r = obj.error.yns_alert(msg,
464                                         $("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.modifying_holds_title'),
465                                         $("commonStrings").getString('common.yes'),
466                                         $("commonStrings").getString('common.no'),
467                                         null,
468                                         $("commonStrings").getString('common.check_to_confirm')
469                                 );
470                                 if (r == 0) {
471                                     circ.util.batch_hold_update(hold_list, { 'phone_notify' : phone }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
472                                 }
473                             } catch(E) {
474                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
475                             }
476                         }
477                     ],
478                     'cmd_holds_edit_email_notify' : [
479                         ['command'],
480                         function() {
481                             try {
482                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
483                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.description')+'</description>';
484                                 xml += '<hbox><button value="email" label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_email.label')+'"';
485                                 xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_email.accesskey')+'" name="fancy_submit"/>';
486                                 xml += '<button value="noemail" label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_no_email.label')+'"';
487                                 xml += '  accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_no_email.accesskey')+'" name="fancy_submit"/></hbox>';
488                                 xml += '</vbox>';
489                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
490                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_cancel.label')+'"';
491                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
492                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
493                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
494                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
495                                 JSAN.use('util.window'); var win = new util.window();
496                                 var fancy_prompt_data = win.open(
497                                     urls.XUL_FANCY_PROMPT,
498                                     //+ '?xml_in_stash=temp_mid'
499                                     //+ '&bottom_xml_in_stash=temp_bot'
500                                     //+ '&title=' + window.escape('Set Email Notification for Holds'),
501                                     'fancy_prompt', 'chrome,resizable,modal',
502                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.set_notifs') }
503                                 );
504                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
505                                 var email = fancy_prompt_data.fancy_submit == 'email' ? get_db_true() : get_db_false();
506
507                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
508                                 var msg = '';
509                                 if(get_bool(email)) {
510                                     if(obj.retrieve_ids.length > 1) {
511                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.enable_email.plural', [hold_list.join(', ')]);
512                                     } else {
513                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.enable_email.singular', [hold_list.join(', ')]);
514                                     }
515                                 } else {
516                                     if(obj.retrieve_ids.length > 1) {
517                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.disable_email.plural', [hold_list.join(', ')]);
518                                     } else {
519                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.disable_email.singular', [hold_list.join(', ')]);
520                                     }
521                                 }
522
523                                 var r = obj.error.yns_alert(msg,
524                                         $("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.mod_holds_title'),
525                                         $("commonStrings").getString('common.yes'),
526                                         $("commonStrings").getString('common.no'),
527                                         null,
528                                         $("commonStrings").getString('common.check_to_confirm')
529                                 );
530                                 if (r == 0) {
531                                     circ.util.batch_hold_update(hold_list, { 'email_notify' : email }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
532                                 }
533                             } catch(E) {
534                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
535                             }
536                         }
537                     ],
538                     'cmd_holds_suspend' : [
539                         ['command'],
540                         function() {
541                             try {
542                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
543                                 var r = obj.error.yns_alert(
544                                     obj.retrieve_ids.length > 1 ?
545                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.suspend.prompt.plural',[hold_list.join(', ')]) :
546                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.suspend.prompt',[hold_list.join(', ')]),
547                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds'),
548                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.yes'),
549                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.no'),
550                                     null,
551                                     document.getElementById('commonStrings').getString('common.confirm')
552                                 );
553                                 if (r == 0) {
554                                     var already_suspended = []; var filtered_hold_list = [];
555                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
556                                         var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
557                                         if ( get_bool( hold.frozen() ) ) {
558                                             already_suspended.push( hold.id() );
559                                             continue;
560                                         }
561                                         filtered_hold_list.push( hold.id() );
562                                     }
563                                     circ.util.batch_hold_update(filtered_hold_list, { 'frozen' : 't', 'thaw_date' : null }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { 
564                                         if (already_suspended.length == 1) {
565                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_suspended',[already_suspended[0]]) );
566                                         } else if (already_suspended.length > 1) {
567                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_suspended.plural',[already_suspended.join(', ')]) );
568                                         }
569                                         obj.clear_and_retrieve(true); 
570                                     } });
571                                 }
572                             } catch(E) {
573                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_suspended'),E);
574                             }
575                         }
576                     ],
577                     'cmd_holds_activate' : [
578                         ['command'],
579                         function() {
580                             try {
581                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
582                                 var r = obj.error.yns_alert(
583                                     obj.retrieve_ids.length > 1 ?
584                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.activate.prompt.plural',[hold_list.join(', ')]) :
585                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.activate.prompt',[hold_list.join(', ')]),
586                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds'),
587                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.yes'),
588                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.no'),
589                                     null,
590                                     document.getElementById('commonStrings').getString('common.confirm')
591                                 );
592                                 if (r == 0) {
593                                     var already_activated = []; var filtered_hold_list = [];
594                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
595                                         var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
596                                         if ( ! get_bool( hold.frozen() ) ) {
597                                             already_activated.push( hold.id() );
598                                             continue;
599                                         }
600                                         filtered_hold_list.push( hold.id() );
601                                     }
602                                     circ.util.batch_hold_update(filtered_hold_list, { 'frozen' : 'f', 'thaw_date' : null }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { 
603                                         if (already_activated.length == 1) {
604                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_activated',[already_activated[0]]) );
605                                         } else if (already_activated.length > 1) {
606                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_activated.plural',[already_activated.join(', ')]) );
607                                         }
608                                         obj.clear_and_retrieve(true); 
609                                     } });
610                                 }
611                             } catch(E) {
612                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_activated'),E);
613                             }
614                         }
615                     ],
616                     'cmd_holds_edit_thaw_date' : [
617                         ['command'],
618                         function() {
619                             try {
620                                 JSAN.use('util.date');
621                                 function check_date(value) {
622                                     try {
623                                         if (! util.date.check('YYYY-MM-DD',value) ) { throw(document.getElementById('circStrings').getString('staff.circ.holds.activation_date.invalid_date')); }
624                                         if (util.date.check_past('YYYY-MM-DD',value) || util.date.formatted_date(new Date(),'%F') == value ) {
625                                             throw(document.getElementById('circStrings').getString('staff.circ.holds.activation_date.too_early.error'));
626                                         }
627                                         return true;
628                                     } catch(E) {
629                                         alert(E);
630                                         return false;
631                                     }
632                                 }
633
634                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
635                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.activation_date.prompt',[hold_list.join(', ')]);
636                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.activation_date.prompt',[hold_list.join(', ')]);
637                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
638                                 var value = 'YYYY-MM-DD';
639                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
640                                 var thaw_date; var invalid = true;
641                                 while(invalid) {
642                                     thaw_date = window.prompt(msg,value,title);
643                                     if (thaw_date) {
644                                         invalid = ! check_date(thaw_date);
645                                     } else {
646                                         invalid = false;
647                                     }
648                                 }
649                                 if (thaw_date || thaw_date == '') {
650                                     circ.util.batch_hold_update(
651                                         hold_list, 
652                                         { 'frozen' : 't', 'thaw_date' : thaw_date == '' ? null : util.date.formatted_date(thaw_date + ' 00:00:00','%{iso8601}') }, 
653                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
654                                     );
655                                 }
656                             } catch(E) {
657                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
658                             }
659                         }
660                     ],
661                     'cmd_holds_edit_expire_time' : [
662                         ['command'],
663                         function() {
664                             try {
665                                 JSAN.use('util.date');
666                                 function check_date(value) {
667                                     try {
668                                         if (! util.date.check('YYYY-MM-DD',value) ) { throw(document.getElementById('circStrings').getString('staff.circ.holds.expire_time.invalid_date')); }
669                                         if (util.date.check_past('YYYY-MM-DD',value) || util.date.formatted_date(new Date(),'%F') == value ) {
670                                             throw(document.getElementById('circStrings').getString('staff.circ.holds.expire_time.too_early.error'));
671                                         }
672                                         return true;
673                                     } catch(E) {
674                                         alert(E);
675                                         return false;
676                                     }
677                                 }
678
679                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
680                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.expire_time.prompt',[hold_list.join(', ')]);
681                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.expire_time.prompt',[hold_list.join(', ')]);
682                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
683                                 var value = 'YYYY-MM-DD';
684                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
685                                 var expire_time; var invalid = true;
686                                 while(invalid) {
687                                     expire_time = window.prompt(msg,value,title);
688                                     if (expire_time) {
689                                         invalid = ! check_date(expire_time);
690                                     } else {
691                                         invalid = false;
692                                     }
693                                 }
694                                 if (expire_time || expire_time == '') {
695                                     circ.util.batch_hold_update(
696                                         hold_list, 
697                                         { 'expire_time' : expire_time == '' ? null : util.date.formatted_date(expire_time + ' 00:00:00','%{iso8601}') }, 
698                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
699                                     );
700                                 }
701                             } catch(E) {
702                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
703                             }
704                         }
705                     ],
706
707
708
709                     'cmd_holds_retarget' : [
710                         ['command'],
711                         function() {
712                             try {
713                                 JSAN.use('util.functional');
714
715                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
716                                 var msg = '';
717                                 if(obj.retrieve_ids.length > 1) {
718                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_retarget.reset_hold_message.plural',[hold_list.join(', ')]);
719                                 } else {
720                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_retarget.reset_hold_message.singular',[hold_list.join(', ')]);
721                                 }
722                                 var r = obj.error.yns_alert(msg,
723                                         $("patronStrings").getString('staff.patron.holds.holds_retarget.reset_hold_title'),
724                                         $("commonStrings").getString('common.yes'),
725                                         $("commonStrings").getString('common.no'),
726                                         null,
727                                         $("commonStrings").getString('common.check_to_confirm')
728                                 );
729                                 if (r == 0) {
730                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
731                                         var robj = obj.network.simple_request('FM_AHR_RESET',[ ses(), obj.retrieve_ids[i].id]);
732                                         if (typeof robj.ilsevent != 'undefined') throw(robj);
733                                     }
734                                     obj.clear_and_retrieve();
735                                 }
736                             } catch(E) {
737                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_retarget.holds_not_reset'),E);
738                             }
739
740                         }
741                     ],
742
743                     'cmd_holds_cancel' : [
744                         ['command'],
745                         function() {
746                             try {
747                                 JSAN.use('util.functional');
748
749                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
750                                 var msg = '';
751                                 if(obj.retrieve_ids.length > 1 ) {
752                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_hold_message.plural', [hold_list.join(', ')]);
753                                 } else {
754                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_hold_message.singular', [hold_list.join(', ')]);
755                                 }
756
757                                 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
758                                 JSAN.use('util.window');
759                                 var win = new util.window();
760                                 var my_xulG = win.open(
761                                     urls.XUL_HOLD_CANCEL,
762                                     'hold_cancel',
763                                     'chrome,resizable,modal',
764                                     {}
765                                 );
766                                 /*var r = obj.error.yns_alert(msg,
767                                         $("patronStrings").getString('staff.patron.holds.holds_cancel.cancel_hold_title'),
768                                         $("commonStrings").getString('common.yes'),
769                                         $("commonStrings").getString('common.no'),
770                                         null,
771                                         $("commonStrings").getString('common.check_to_confirm')
772                                 );*/
773
774                                 if (my_xulG.proceed) { 
775                                     var transits = [];
776                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
777                                         if (obj.holds_map[ obj.retrieve_ids[i].id ].hold.transit()) {
778                                             transits.push( obj.retrieve_ids[i].barcode );
779                                         }
780                                         var robj = obj.network.simple_request('FM_AHR_CANCEL',[ ses(), obj.retrieve_ids[i].id, my_xulG.cancel_reason, my_xulG.note]);
781                                         if (typeof robj.ilsevent != 'undefined') throw(robj);
782                                     }
783                                     if (transits.length > 0) {
784                                         var msg2 = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_for_barcodes', [transits.join(', ')]);
785                                         var r2 = obj.error.yns_alert(msg2,
786                                             $("patronStrings").getString('staff.patron.holds.holds_cancel.cancel_for_barcodes.title'),
787                                             $("commonStrings").getString('common.yes'),
788                                             $("commonStrings").getString('common.no'),
789                                             null,
790                                             $("commonStrings").getString('common.check_to_confirm'));
791                                         if (r2 == 0) {
792                                             try {
793                                                 for (var i = 0; i < transits.length; i++) {
794                                                     var robj = obj.network.simple_request('FM_ATC_VOID',[ ses(), { 'barcode' : transits[i] } ]);
795                                                     if (typeof robj.ilsevent != 'undefined') {
796                                                         switch(Number(robj.ilsevent)) {
797                                                             case 1225 /* TRANSIT_ABORT_NOT_ALLOWED */ :
798                                                                 alert(robj.desc);
799                                                             break;
800                                                             case 5000 /* PERM_FAILURE */ :
801                                                             break;
802                                                             default:
803                                                                 throw(robj);
804                                                             break;
805                                                         }
806                                                     }
807                                                 }
808                                             } catch(E) {
809                                                obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_cancel.hold_transits_not_cancelled'),E);
810                                             }
811                                         }
812                                     }
813                                     obj.clear_and_retrieve();
814                                 }
815                             } catch(E) {
816                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_cancel.hold_not_cancelled'),E);
817                             }
818                         }
819                     ],
820                     'cmd_holds_uncancel' : [
821                         ['command'],
822                         function() {
823                             try {
824                                 JSAN.use('util.functional');
825                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
826                                     var robj = obj.network.simple_request('FM_AHR_UNCANCEL',[ ses(), obj.retrieve_ids[i].id]);
827                                     if (typeof robj.ilsevent != 'undefined') throw(robj);
828                                 }
829                                 obj.clear_and_retrieve();
830                             } catch(E) {
831                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_uncancel.hold_not_uncancelled'),E);
832                             }
833                         }
834                     ],
835
836                     'cmd_retrieve_patron' : [
837                         ['command'],
838                         function() {
839                             try {
840                                 var seen = {};
841                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
842                                     var patron_id = obj.retrieve_ids[i].usr;
843                                     if (seen[patron_id]) continue; seen[patron_id] = true;
844                                     xulG.new_patron_tab(
845                                         {},
846                                         { 'id' : patron_id }
847                                     );
848                                 }
849                             } catch(E) {
850                                 obj.error.standard_unexpected_error_alert('',E);
851                             }
852                         }
853                     ],
854                     'cmd_show_catalog' : [
855                         ['command'],
856                         function() {
857                             try {
858                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
859                                     var htarget = obj.retrieve_ids[i].target;
860                                     var htype = obj.retrieve_ids[i].type;
861                                     var opac_url;
862                                     switch(htype) {
863                                         case 'M' :
864                                             opac_url = xulG.url_prefix( urls.opac_rresult ) + '?m=' + htarget;
865                                         break;
866                                         case 'T' :
867                                             opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + htarget;
868                                         break;
869                                         case 'V' :
870                                             var my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative', [ htarget ]);
871                                             opac_url = xulG.url_prefix( urls.opac_rdetail) + '?r=' + my_acn.record();
872                                         break;
873                                         case 'C' :
874                                             var my_acp = obj.network.simple_request( 'FM_ACP_RETRIEVE', [ htarget ]);
875                                             var my_acn;
876                                             if (typeof my_acp.call_number() == 'object') {
877                                                 my_acn = my.acp.call_number();
878                                             } else {
879                                                 my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative',
880                                                     [ my_acp.call_number() ]);
881                                             }
882                                             opac_url = xulG.url_prefix( urls.opac_rdetail) + '?r=' + my_acn.record();
883                                         break;
884                                         default:
885                                             obj.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.holds.show_catalog.unknown_htype', [htype]), obj.retrieve_ids[i]);
886                                             continue;
887                                         break;
888                                     }
889                                     var content_params = {
890                                         'session' : ses(),
891                                         'authtime' : ses('authtime'),
892                                         'opac_url' : opac_url
893                                     };
894                                     xulG.new_tab(
895                                         xulG.url_prefix(urls.XUL_OPAC_WRAPPER),
896                                         {'tab_name': htype == 'M' ? 'Catalog' : $("patronStrings").getString('staff.patron.holds.show_catalog.retrieving_title') },
897                                         content_params
898                                     );
899                                 }
900                             } catch(E) {
901                                 obj.error.standard_unexpected_error_alert('',E);
902                             }
903                         }
904                     ],
905                     'fetch_more' : [
906                         ['command'],
907                         function() {
908                             obj.pull_from_shelf_interface.current.offset += obj.pull_from_shelf_interface.current.limit;
909                             obj.retrieve(true);
910                         }
911                     ],
912                     'lib_filter_checkbox' : [
913                         ['command'],
914                         function(ev) {
915                             var x_lib_type_menu = document.getElementById('lib_type_menu');
916                             if (x_lib_type_menu) x_lib_type_menu.disabled = ! ev.target.checked;
917                             if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = ! ev.target.checked;
918                             obj.clear_and_retrieve();
919                             ev.target.setAttribute('checked',ev.target.checked);
920                         }
921                     ],
922                     'cmd_search_opac' : [
923                         ['command'],
924                         function(ev) {
925                             try {
926                                 var content_params = {
927                                     'show_nav_buttons' : false,
928                                     'show_print_button' : true,
929                                     'passthru_content_params' : {
930                                         'authtoken' : ses(),
931                                         'authtime' : ses('authtime'),
932                                         'window_open' : function(a,b,c) {
933                                             try {
934                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
935                                                 return window.open(a,b,c);
936                                             } catch(E) {
937                                                 obj.error.standard_unexpected_error_alert('window_open',E);
938                                             }
939                                         },
940                                         'opac_hold_placed' : function(hold) {
941                                             try {
942                                                 obj.list.append(
943                                                     {
944                                                         'row' : {
945                                                             'my' : {
946                                                                 'hold_id' : typeof hold == 'object' ? hold.id() : hold
947                                                             }
948                                                         }
949                                                     }
950                                                 );
951                                                 if (window.xulG && typeof window.xulG.on_list_change == 'function') {
952                                                     window.xulG.on_list_change(); 
953                                                 }
954                                             } catch(E) {
955                                                 obj.error.standard_unexpected_error_alert('holds.js, opac_hold_placed(): ',E);
956                                             }
957                                         },
958                                         'patron_barcode' : obj.patron_barcode
959                                     },
960                                     'url_prefix' : xulG.url_prefix,
961                                     'url' : xulG.url_prefix( urls.browser )
962                                 };
963                                 xulG.display_window.g.patron.right_deck.set_iframe( urls.XUL_REMOTE_BROWSER + '?patron_hold=1', {}, content_params);
964                             } catch(E) {
965                                 obj.error.sdump('D_ERROR','cmd_search_opac: ' + E);
966                             }
967
968                         }
969                     ]
970                 }
971             }
972         );
973
974         obj.determine_hold_interface_type();
975         var x_fetch_more = document.getElementById('fetch_more');
976         var x_lib_type_menu = document.getElementById('lib_type_menu');
977         var x_lib_menu_placeholder = document.getElementById('lib_menu_placeholder');
978         var x_lib_filter_checkbox = document.getElementById('lib_filter_checkbox');
979         switch(obj.hold_interface_type) {
980             case 'shelf':
981                 obj.render_lib_menus({'pickup_lib':true});
982                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
983                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
984             break;
985             case 'pull' :
986                 if (x_fetch_more) x_fetch_more.hidden = false;
987                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
988                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
989             break;
990             case 'record' :
991                 obj.render_lib_menus({'pickup_lib':true,'request_lib':true});
992                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.hidden = false;
993                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
994                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
995             break;
996             default:
997                 if (obj.controller.view.cmd_search_opac) obj.controller.view.cmd_search_opac.setAttribute('hidden', false);
998                 if (x_fetch_more) x_fetch_more.hidden = true;
999                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
1000                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
1001             break;
1002         }
1003         setTimeout( // We do this because render_lib_menus above creates and appends a DOM node, but until this thread exits, it doesn't really happen
1004             function() {
1005                 if (x_lib_filter_checkbox) if (!x_lib_filter_checkbox.checked) {
1006                     if (x_lib_type_menu) x_lib_type_menu.disabled = true;
1007                     if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = true;
1008                 }
1009                 obj.controller.render();
1010                 obj.retrieve(true);
1011
1012                 obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
1013                 obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
1014                 obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
1015                 obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
1016                 obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','true');
1017                 obj.controller.view.cmd_holds_activate.setAttribute('disabled','true');
1018                 obj.controller.view.cmd_holds_suspend.setAttribute('disabled','true');
1019                 obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
1020                 obj.controller.view.cmd_alt_view.setAttribute('disabled','true');
1021                 obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
1022                 obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
1023                 obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
1024             }, 0
1025         );
1026
1027         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
1028         JSAN.use('util.browser');
1029         obj.browser = new util.browser();
1030         obj.browser.init(
1031             {
1032                 'url' : urls.XUL_HOLD_DETAILS,
1033                 'push_xulG' : true,
1034                 'alt_print' : false,
1035                 'browser_id' : 'hold_detail_frame',
1036                 'passthru_content_params' : xulG,
1037             }
1038         );
1039
1040     },
1041
1042     'determine_hold_interface_type' : function() {
1043         var obj = this;
1044         if (obj.patron_id) { /*************************************************** PATRON ******************************/
1045             obj.hold_interface_type = 'patron';
1046         } else if (obj.docid) { /*************************************************** RECORD ******************************/
1047             obj.hold_interface_type = 'record';
1048         } else if (obj.pull) { /*************************************************** PULL ******************************/
1049             obj.hold_interface_type = 'pull';
1050         } else if (obj.shelf) { /*************************************************** HOLD SHELF ******************************/
1051             obj.hold_interface_type = 'shelf';
1052         } else { /*************************************************** PULL ******************************/
1053             obj.hold_interface_type = 'pull';
1054         }
1055     },
1056
1057     'clear_and_retrieve' : function() {
1058         try {
1059             this.list.clear();
1060             this.pull_from_shelf_interface.current.offset = this.pull_from_shelf_interface._default.offset;
1061             this.retrieve();
1062             if (window.xulG && typeof window.xulG.on_list_change == 'function') {
1063                 window.xulG.on_list_change(); 
1064             }
1065         } catch(E) {
1066             this.error.standard_unexpected_error_alert('holds.js, clear_and_retrieve(): ',E);
1067         }
1068     },
1069
1070     'retrieve' : function() {
1071         var obj = this; var holds = [];
1072         if (window.xulG && window.xulG.holds) {
1073             holds = window.xulG.holds;
1074         } else {
1075             var method; var params = [ ses() ];
1076             switch(obj.hold_interface_type) {
1077                 case 'patron' :
1078                     method = 'FM_AHR_ID_LIST_RETRIEVE_VIA_AU.authoritative';
1079                     params.push( obj.patron_id );
1080                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','true');
1081                 break;
1082                 case 'record' :
1083                     method = 'FM_AHR_RETRIEVE_ALL_VIA_BRE';
1084                     params.push( obj.docid );
1085                     var x_lib_filter = document.getElementById('lib_filter_checkbox');
1086                     var x_lib_type_menu = document.getElementById('lib_type_menu');
1087                     if (x_lib_filter) {
1088                         if (x_lib_filter.checked) {
1089                             if (x_lib_type_menu && obj.controller.view.lib_menu) {
1090                                 var x = {};
1091                                 x[ x_lib_type_menu.value ] = obj.controller.view.lib_menu.value;
1092                                 params.push( x );
1093                             }
1094                         }
1095                     }
1096                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1097                 break;
1098                 case 'shelf' :
1099                     method = 'FM_AHR_ID_LIST_ONSHELF_RETRIEVE';
1100                     params.push( obj.filter_lib || obj.data.list.au[0].ws_ou() );
1101                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1102                 break;
1103                 case 'pull' :
1104                 default:
1105                     method = 'FM_AHR_ID_LIST_PULL_LIST';
1106                     params.push( obj.pull_from_shelf_interface.current.limit ); params.push( obj.pull_from_shelf_interface.current.offset );
1107                     //obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1108                 break;
1109             }
1110             var robj = obj.network.simple_request( method, params );
1111             if (robj != null && typeof robj.ilsevent != 'undefined') throw(robj);
1112             if (method == 'FM_AHR_RETRIEVE_ALL_VIA_BRE') {
1113                 holds = [];
1114                 if (robj != null) {
1115                     holds = holds.concat( robj.copy_holds );
1116                     holds = holds.concat( robj.volume_holds );
1117                     holds = holds.concat( robj.title_holds );
1118                     holds = holds.concat( robj.metarecord_holds );
1119                     holds = holds.sort();
1120                 }
1121             } else {
1122                 if (robj == null ) {
1123                     holds = [];
1124                 } else {
1125                     if (typeof robj.length == 'undefined') {
1126                         holds = [ robj ];
1127                     } else {
1128                         holds = robj;
1129                     }
1130                 }
1131             }
1132             //alert('method = ' + method + ' params = ' + js2JSON(params));
1133         }
1134
1135         var x_fetch_more = document.getElementById('fetch_more');
1136         if (holds.length == 0) {
1137             if (x_fetch_more) x_fetch_more.disabled = true;
1138         } else {
1139             if (x_fetch_more) x_fetch_more.disabled = false;
1140             obj.render(holds);
1141         }
1142
1143     },
1144
1145     'render' : function(holds) {
1146         try {
1147             var obj = this;
1148
1149             function list_append(hold_id) {
1150                 obj.list.append(
1151                     {
1152                         'row' : {
1153                             'my' : {
1154                                 'hold_id' : hold_id
1155                             }
1156                         }
1157                     }
1158                 );
1159             }
1160
1161             function gen_list_append(hold) {
1162                 return function() {
1163                     if (typeof obj.controller.view.lib_menu == 'undefined') {
1164                         list_append(typeof hold == 'object' ? hold.id() : hold);
1165                     } else {
1166                         list_append(typeof hold == 'object' ? hold.id() : hold);
1167                     }
1168                 };
1169             }
1170
1171             //obj.list.clear();
1172
1173             JSAN.use('util.exec'); var exec = new util.exec(2);
1174             var rows = [];
1175             for (var i in holds) {
1176                 rows.push( gen_list_append(holds[i]) );
1177             }
1178             exec.chain( rows );
1179
1180         } catch(E) {
1181             this.error.standard_unexpected_error_alert('holds.js, render():',E);
1182         }
1183     },
1184
1185     'render_lib_menus' : function(types) {
1186         try {
1187             var obj = this;
1188             JSAN.use('util.widgets'); JSAN.use('util.functional'); JSAN.use('util.fm_utils');
1189
1190             var x = document.getElementById('lib_type_menu');
1191             if (types) {
1192                 var nodes = x.firstChild.childNodes;
1193                 for (var i = 0; i < nodes.length; i++) nodes[i].hidden = true;
1194                 for (var i in types) document.getElementById(i).hidden = false;
1195             }
1196             x.setAttribute('oncommand','g.holds.clear_and_retrieve()');
1197
1198             x = document.getElementById('lib_menu_placeholder');
1199             util.widgets.remove_children( x );
1200
1201             JSAN.use('util.file');
1202             var file = new util.file('offline_ou_list');
1203             if (file._file.exists()) {
1204                 var list_data = file.get_object(); file.close();
1205                 var ml = util.widgets.make_menulist( list_data[0], obj.data.list.au[0].ws_ou() );
1206                 ml.setAttribute('id','lib_menu');
1207                 x.appendChild( ml );
1208                 ml.addEventListener(
1209                     'command',
1210                     function(ev) {
1211                         obj.filter_lib = ev.target.value;
1212                         obj.clear_and_retrieve();
1213                     },
1214                     false
1215                 );
1216                 obj.controller.view.lib_menu = ml;
1217             } else {
1218                 throw($("patronStrings").getString('staff.patron.holds.lib_menus.missing_library_list'));
1219             }
1220
1221         } catch(E) {
1222             this.error.standard_unexpected_error_alert('rendering lib menu',E);
1223         }
1224     }
1225 }
1226
1227 dump('exiting patron.holds.js\n');