]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/xul/staff_client/server/patron/holds.js
lp945091 save columns independently for hold lists
[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' : 100, 'offset' : 0 },
19         'current' : { 'limit' : 100, 'offset' : 0 }
20     },
21
22     'filter_lib' : null,
23
24     'hold_subscription_map' : {},
25     'hold_part_map' : {},
26
27     'expired' : false,
28     'post_clear_shelf_hold_action_map' : {},
29
30     'retrieve_ids' : [],
31
32     'holds_map' : {},
33
34     'flatten_copy' : function(hold) {
35         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); }
36         return hold;
37     },
38
39     'init' : function( params ) {
40
41         var obj = this;
42
43         dojo.require("openils.Util");
44
45         obj.patron_id = params['patron_id'];
46         obj.patron_barcode = params['patron_barcode'];
47         obj.docid = params['docid'];
48         obj.shelf = params['shelf'];
49         obj.tree_id = params['tree_id'];
50
51         obj.determine_hold_interface_type();
52
53         var progressmeter = document.getElementById('progress');
54
55         JSAN.use('circ.util');
56         var columns = circ.util.hold_columns(
57             {
58                 'title' : { 'hidden' : false, 'flex' : '3' },
59                 'request_time' : { 'hidden' : false },
60                 'pickup_lib_shortname' : { 'hidden' : false },
61                 'hold_type' : { 'hidden' : false },
62                 'current_copy' : { 'hidden' : false },
63                 'capture_time' : { 'hidden' : false },
64                 'notify_time' : { 'hidden' : false },
65                 'notify_count' : { 'hidden' : false },
66                 'cancel_cause' : { 'hidden' : ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) },
67                 'cancel_note' : { 'hidden' :  ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) },
68                 'cancel_time' : { 'hidden' :  ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) },
69                 'post_clear_shelf_action' : { 'hidden' : obj.shelf ? false : true }
70             }
71         );
72
73         JSAN.use('util.list'); obj.list = new util.list( obj.tree_id || 'holds_list');
74         obj.list.init(
75             {
76                 'columns_saved_under' : 'holds_' + obj.hold_interface_type,
77                 'columns' : columns.concat(
78                     obj.list.fm_columns('acp', {
79                         '*' : { 'expanded_label' : true, 'hidden' : true },
80                         // example of unhiding some columns by default
81                         // 'acp_circ_modifier' : { 'hidden' : false }
82                     })
83                 ),
84                 'retrieve_row' : function(params) {
85                     var row = params.row;
86                     try {
87                         obj.network.simple_request('FM_AHR_BLOB_RETRIEVE.authoritative', [ ses(), row.my.hold_id ],
88                             function(blob_req) {
89                                 try {
90                                     var blob = blob_req.getResultObject();
91                                     if (typeof blob.ilsevent != 'undefined') throw(blob);
92                                     row.my.ahr = blob.hold;
93                                     row.my.status = blob.status;
94                                     row.my.ahr.status( blob.status );
95                                     row.my.acp = blob.copy;
96                                     row.my.acn = blob.volume;
97                                     row.my.mvr = blob.mvr;
98                                     row.my.part = blob.part;
99                                     if (blob.part) {
100                                         obj.hold_part_map[ row.my.hold_id ] = row.my.part;
101                                     }
102                                     row.my.issuance = blob.issuance;
103                                     if (blob.issuance) {
104                                         row.my.subscription = blob.issuance.subscription();
105                                         obj.hold_subscription_map[ row.my.hold_id ] = row.my.subscription;
106                                     }
107                                     row.my.patron_family_name = blob.patron_last;
108                                     row.my.patron_first_given_name = blob.patron_first;
109                                     row.my.patron_barcode = blob.patron_barcode;
110                                     row.my.patron_alias = blob.patron_alias;
111                                     row.my.total_holds = blob.total_holds;
112                                     row.my.queue_position = blob.queue_position;
113                                     row.my.potential_copies = blob.potential_copies;
114                                     row.my.estimated_wait = blob.estimated_wait;
115                                     row.my.ahrn_count = blob.hold.notes().length;
116
117                                     var copy_id = row.my.ahr.current_copy();
118                                     if (typeof copy_id == 'object') {
119                                         if (copy_id == null) {
120                                             if (typeof row.my.acp == 'object' && row.my.acp != null) copy_id = row.my.acp.id();
121                                         } else {
122                                             copy_id = copy_id.id();
123                                         }
124                                     } else {
125                                         copy_id = row.my.acp.id();
126                                     }
127
128                                     obj.holds_map[ row.my.ahr.id() ] = blob;
129                                     params.row_node.setAttribute('retrieve_id',
130                                         js2JSON({
131                                             'copy_id':copy_id,
132                                             'barcode':row.my.acp ? row.my.acp.barcode() : null,
133                                             'id':row.my.ahr.id(),
134                                             'type':row.my.ahr.hold_type(),
135                                             'target':row.my.ahr.target(),
136                                             'usr':row.my.ahr.usr()
137                                         })
138                                     );
139                                     if (typeof params.on_retrieve == 'function') { params.on_retrieve(row); }
140
141                                 } catch(E) {
142                                     obj.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.holds.init.hold_num_error', [row.my.hold_id]), E);
143                                 }
144                             }
145                         );
146                     } catch(E) {
147                         obj.error.sdump('D_ERROR','retrieve_row: ' + E );
148                     }
149                     return row;
150                 },
151                 'on_select' : function(ev) {
152                     JSAN.use('util.functional');
153                     var sel = obj.list.retrieve_selection();
154                     obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
155                     obj.retrieve_ids = util.functional.map_list(
156                         sel,
157                         function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
158                     );
159                     if (obj.retrieve_ids.length > 0) {
160                         obj.controller.view.sel_mark_items_damaged.setAttribute('disabled','false');
161                         obj.controller.view.sel_mark_items_missing.setAttribute('disabled','false');
162                         obj.controller.view.sel_copy_details.setAttribute('disabled','false');
163                         obj.controller.view.sel_patron.setAttribute('disabled','false');
164                         obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','false');
165                         obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','false');
166                         obj.controller.view.cmd_holds_edit_desire_mint_condition.setAttribute('disabled','false');
167                         obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','false');
168                         obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','false');
169                         obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','false');
170                         obj.controller.view.cmd_holds_edit_expire_time.setAttribute('disabled','false');
171                         obj.controller.view.cmd_holds_edit_shelf_expire_time.setAttribute('disabled','false');
172                         obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','false');
173                         obj.controller.view.cmd_holds_edit_request_date.setAttribute('disabled','false');
174                         obj.controller.view.cmd_holds_activate.setAttribute('disabled','false');
175                         obj.controller.view.cmd_holds_suspend.setAttribute('disabled','false');
176                         obj.controller.view.cmd_alt_view.setAttribute('rendering_rows','false');
177                         if (obj.controller.view.cmd_alt_view.getAttribute('ready')=='true') {
178                             obj.controller.view.cmd_alt_view.setAttribute('disabled','false');
179                         }
180                         obj.controller.view.cmd_holds_retarget.setAttribute('disabled','false');
181                         obj.controller.view.cmd_holds_cancel.setAttribute('disabled','false');
182                         obj.controller.view.cmd_holds_uncancel.setAttribute('disabled','false');
183                         obj.controller.view.cmd_show_catalog.setAttribute('disabled','false');
184                     } else {
185                         obj.controller.view.sel_mark_items_damaged.setAttribute('disabled','true');
186                         obj.controller.view.sel_mark_items_missing.setAttribute('disabled','true');
187                         obj.controller.view.sel_copy_details.setAttribute('disabled','true');
188                         obj.controller.view.sel_patron.setAttribute('disabled','true');
189                         obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
190                         obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
191                         obj.controller.view.cmd_holds_edit_desire_mint_condition.setAttribute('disabled','true');
192                         obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
193                         obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
194                         obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
195                         obj.controller.view.cmd_holds_edit_expire_time.setAttribute('disabled','true');
196                         obj.controller.view.cmd_holds_edit_shelf_expire_time.setAttribute('disabled','true');
197                         obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','true');
198                         obj.controller.view.cmd_holds_edit_request_date.setAttribute('disabled','true');
199                         obj.controller.view.cmd_holds_activate.setAttribute('disabled','true');
200                         obj.controller.view.cmd_holds_suspend.setAttribute('disabled','true');
201                         obj.controller.view.cmd_alt_view.setAttribute('disabled','true');
202                         obj.controller.view.cmd_alt_view.setAttribute('rendering_rows','true');
203                         obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
204                         obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
205                         obj.controller.view.cmd_holds_uncancel.setAttribute('disabled','true');
206                         obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
207                     }
208                 }
209             }
210         );
211
212         JSAN.use('util.controller'); obj.controller = new util.controller();
213         obj.controller.init(
214             {
215                 'control_map' : {
216                     'save_columns' : [ [ 'command' ], function() { obj.list.save_columns(); } ],
217                     'sel_clip' : [
218                         ['command'],
219                         function() { obj.list.clipboard(); }
220                     ],
221                     'cmd_broken' : [
222                         ['command'],
223                         function() { alert($("commonStrings").getString('common.unimplemented')); }
224                     ],
225                     'sel_patron' : [
226                         ['command'],
227                         function() {
228                             JSAN.use('circ.util');
229                             circ.util.show_last_few_circs(obj.retrieve_ids);
230                         }
231                     ],
232                     'alt_view_btn' : [
233                         ['render'],
234                         function(e) {
235                             e.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.label'));
236                             e.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.accesskey'));
237                         }
238                     ],
239                     'cmd_alt_view' : [
240                         ['command'],
241                         function(ev) {
242                             try {
243                                 var n = obj.controller.view.alt_view_btn;
244                                 if (n.getAttribute('toggle') == '1') {
245                                     document.getElementById('deck').selectedIndex = 0;
246                                     n.setAttribute('toggle','0');
247                                     n.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.label'));
248                                     n.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.accesskey'));
249                                     obj.controller.view.save_columns.setAttribute('disabled','false');
250                                 } else {
251                                     document.getElementById('deck').selectedIndex = 1;
252                                     n.setAttribute('toggle','1');
253                                     n.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.list_view.label'));
254                                     n.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.list_view.accesskey'));
255                                     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
256                                     if (obj.retrieve_ids.length == 0) return;
257                                     var f = obj.browser.get_content();
258                                     xulG.ahr_id = obj.retrieve_ids[0].id;
259                                     xulG.blob = obj.holds_map[ xulG.ahr_id ];
260                                     xulG.patron_rendered_elsewhere = (obj.hold_interface_type == 'patron');
261                                     xulG.bib_rendered_elsewhere = (obj.hold_interface_type == 'record');
262                                     f.xulG = xulG;
263                                     f.xulG.clear_and_retrieve = function() { obj.clear_and_retrieve(); };
264                                     f.fetch_and_render_all(true);
265                                     obj.controller.view.save_columns.setAttribute('disabled','true');
266                                 }
267                             } catch(E) {
268                                 alert('Error in holds.js, cmd_alt_view handler: ' + E);
269                             }
270                         },
271                     ],
272                     'cmd_cancelled_holds_view' : [
273                         ['command'],
274                         function(ev) {
275                             document.getElementById('show_cancelled_deck').selectedIndex = 1;
276                             /* For some reason attribute propogation on the <command> element isn't working with hidden */
277                             document.getElementById('holds_cancel_btn').setAttribute('hidden','true');
278                             document.getElementById('holds_uncancel_btn').setAttribute('hidden','false');
279                             document.getElementById('holds_cancel_btn2').setAttribute('hidden','true');
280                             document.getElementById('holds_uncancel_btn2').setAttribute('hidden','false');
281                             obj.clear_and_retrieve();
282                         }
283                     ],
284                     'cmd_uncancelled_holds_view' : [
285                         ['command'],
286                         function(ev) {
287                             document.getElementById('show_cancelled_deck').selectedIndex = 0;
288                             /* For some reason attribute propogation on the <command> element isn't working with hidden */
289                             document.getElementById('holds_cancel_btn').setAttribute('hidden','false');
290                             document.getElementById('holds_uncancel_btn').setAttribute('hidden','true');
291                             document.getElementById('holds_cancel_btn2').setAttribute('hidden','false');
292                             document.getElementById('holds_uncancel_btn2').setAttribute('hidden','true');
293                             obj.clear_and_retrieve();
294                         }
295                     ],
296                     'sel_mark_items_damaged' : [
297                         ['command'],
298                         function() {
299                             JSAN.use('cat.util'); JSAN.use('util.functional');
300                             cat.util.mark_item_damaged( util.functional.map_list( obj.retrieve_ids, function(o) { return o.copy_id; } ) );
301                         }
302                     ],
303                     'sel_mark_items_missing' : [
304                         ['command'],
305                         function() {
306                             JSAN.use('cat.util'); JSAN.use('util.functional');
307                             cat.util.mark_item_missing( util.functional.map_list( obj.retrieve_ids, function(o) { return o.copy_id; } ) );
308                         }
309                     ],
310                     'sel_copy_details' : [
311                         ['command'],
312                         function() {
313                             JSAN.use('circ.util');
314                             circ.util.item_details_new(
315                                 util.functional.map_list(
316                                     obj.retrieve_ids,
317                                     function(o) { return o.barcode; }
318                                 )
319                             );
320                         }
321                     ],
322                     'cmd_holds_print_full' : [
323                         ['command'],
324                         function() {
325                             var x_print_full_pull_list = document.getElementById('print_full_btn');
326                             try {
327                                 if (progressmeter) {
328                                     progressmeter.mode = 'undetermined';
329                                     progressmeter.hidden = false;
330                                     x_print_full_pull_list.disabled = true;
331                                 }
332                                 JSAN.use('util.print');
333                                 var print = new util.print('default');
334                                 var robj = fieldmapper.standardRequest(
335                                     [ api.HTML_HOLD_PULL_LIST.app, api.HTML_HOLD_PULL_LIST.method ],
336                                     {   async: false,
337                                         timeout: 180,
338                                         params: [ses()],
339                                     }
340                                 );
341                                 if (robj != null) {
342                                     if (typeof robj.ilsevent != 'undefined') { throw(robj); }
343                                     print.simple( robj.template_output().data() );
344                                 }
345                             } catch(E) {
346                                 obj.error.standard_unexpected_error_alert('cmd_holds_print_full',E);
347                             }
348                             if (progressmeter) {
349                                 progressmeter.mode = 'determined';
350                                 progressmeter.hidden = true;
351                                 x_print_full_pull_list.disabled = false;
352                             }
353                         }
354                     ],
355                     'cmd_holds_print_alt' : [
356                         ['command'],
357                         function() {
358                             try {
359                                 var content_params = {
360                                     "session": ses(),
361                                     "authtime": ses("authtime"),
362                                     "no_xulG": false,
363                                     "show_nav_buttons": true,
364                                     "show_print_button": true
365                                 };
366                                 ["url_prefix", "new_tab", "set_tab",
367                                     "close_tab", "new_patron_tab",
368                                     "set_patron_tab", "volume_item_creator",
369                                     "get_new_session",
370                                     "holdings_maintenance_tab", "set_tab_name",
371                                     "open_chrome_window", "url_prefix",
372                                     "network_meter", "page_meter",
373                                     "set_statusbar", "set_help_context"
374                                 ].forEach(function(k) {
375                                     content_params[k] = xulG[k];
376                                 });
377
378                                 var loc = urls.XUL_BROWSER + "?url=" + window.escape(
379                                     xulG.url_prefix("/opac/extras/circ/alt_holds_print.html").replace("http:","https:")
380                                 );
381                                 xulG.new_tab(
382                                     loc, {
383                                         "tab_name": "Printable Pull List", /* XXX i18n */
384                                         "browser": false
385                                     }, content_params
386                                 );
387                             } catch (E) {
388                                 g.error.sdump("D_ERROR", E);
389                             }
390                         }
391                     ],
392                     'cmd_holds_print' : [
393                         ['command'],
394                         function() {
395                             try {
396                                 JSAN.use('patron.util');
397                                 var params = {
398                                     'patron' : patron.util.retrieve_au_via_id(ses(),obj.patron_id),
399                                     'template' : 'holds'
400                                 };
401                                 obj.list.print(params);
402                             } catch(E) {
403                                 obj.error.standard_unexpected_error_alert('print 1',E);
404                             }
405                         }
406                     ],
407                     'cmd_csv_to_clipboard' : [ ['command'], function() { obj.list.dump_csv_to_clipboard(); } ],
408                     'cmd_csv_to_printer' : [ ['command'], function() { obj.list.dump_csv_to_printer(); } ],
409                     'cmd_csv_to_file' : [ ['command'], function() { obj.list.dump_csv_to_file( { 'defaultFileName' : 'holds.txt' } ); } ],
410
411                     'cmd_holds_edit_selection_depth' : [
412                         ['command'],
413                         function() {
414                             try {
415                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
416                                 var ws_type = obj.data.hash.aout[ obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ].ou_type() ];
417                                 var list = util.functional.map_list(
418                                     util.functional.filter_list(
419                                         obj.data.list.aout,
420                                         function(o) {
421                                             if (o.depth() > ws_type.depth()) return false;
422                                             if (o.depth() < ws_type.depth()) return true;
423                                             return (o.id() == ws_type.id());
424                                         }
425                                     ),
426                                     function(o) {
427                                         return [
428                                             o.opac_label(),
429                                             o.id(),
430                                             false,
431                                             ( o.depth() * 2),
432                                         ];
433                                     }
434                                 );
435                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
436                                 ml.setAttribute('id','selection');
437                                 ml.setAttribute('name','fancy_data');
438                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
439                                 xml += '<description>' + $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.choose_hold_range') + '</description>';
440                                 xml += util.widgets.serialize_node(ml);
441                                 xml += '</vbox>';
442                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
443                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.done.label') +'"';
444                                 bot_xml += 'accesskey="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.done.accesskey') +'" name="fancy_submit"/>';
445                                 bot_xml += '<button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.cancel.label') +'"';
446                                 bot_xml += 'accesskey="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.cancel.accesskey') +'" name="fancy_cancel"/></hbox>';
447                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
448                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
449                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
450                                 JSAN.use('util.window'); var win = new util.window();
451                                 var fancy_prompt_data = win.open(
452                                     urls.XUL_FANCY_PROMPT,
453                                     //+ '?xml_in_stash=temp_mid'
454                                     //+ '&bottom_xml_in_stash=temp_bot'
455                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
456                                     'fancy_prompt', 'chrome,resizable,modal',
457                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.choose_library') }
458                                 );
459                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
460                                 var selection = fancy_prompt_data.selection;
461
462                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
463                                 var msg = '';
464                                 if(obj.retrieve_ids.length > 1) {
465                                     msg = $("patronStrings").getformattedString('staff.patron.holds.holds_edit_selection_depth.modify_holds_message.plural', [hold_list.join(', '), obj.data.hash.aout[selection].opac_label()])
466                                 } else {
467                                     msg = $("patronStrings").getformattedString('staff.patron.holds.holds_edit_selection_depth.modify_holds_message.singular', [hold_list.join(', '), obj.data.hash.aout[selection].opac_label()])
468                                 }
469
470                                 var r = obj.error.yns_alert(msg,
471                                         $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.modify_holds_title'),
472                                         $("commonStrings").getString('common.yes'),
473                                         $("commonStrings").getString('common.no'),
474                                         null,
475                                         $("commonStrings").getString('common.check_to_confirm')
476                                 );
477                                 if (r == 0) {
478                                     circ.util.batch_hold_update(hold_list, { 'selection_depth' : obj.data.hash.aout[selection].depth() }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
479                                 }
480                             } catch(E) {
481                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
482                             }
483                         }
484                     ],
485
486                     'cmd_holds_edit_pickup_lib' : [
487                         ['command'],
488                         function() {
489                             try {
490                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
491
492                                 var list = util.functional.map_list(
493                                     obj.data.list.aou,
494                                     function(o) {
495                                         var sname = o.shortname(); for (i = sname.length; i < 20; i++) sname += ' ';
496                                         return [
497                                             o.name() ? sname + ' ' + o.name() : o.shortname(),
498                                             o.id(),
499                                             ( !isTrue(obj.data.hash.aout[ o.ou_type() ].can_have_users()) ),
500                                             ( obj.data.hash.aout[ o.ou_type() ].depth() * 2),
501                                         ];
502                                     }
503                                 );
504                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
505                                 ml.setAttribute('id','lib');
506                                 ml.setAttribute('name','fancy_data');
507                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
508                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.new_pickup_lib.description')+'</description>';
509                                 xml += util.widgets.serialize_node(ml);
510                                 xml += '</vbox>';
511                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
512                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.done.label') +'"';
513                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.done.accesskey')+'" name="fancy_submit"/>';
514                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.cancel.label')+'"';
515                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
516                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
517                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
518                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
519                                 JSAN.use('util.window'); var win = new util.window();
520                                 var fancy_prompt_data = win.open(
521                                     urls.XUL_FANCY_PROMPT,
522                                     //+ '?xml_in_stash=temp_mid'
523                                     //+ '&bottom_xml_in_stash=temp_bot'
524                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
525                                     'fancy_prompt', 'chrome,resizable,modal',
526                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.choose_lib') }
527                                 );
528                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
529                                 var pickup_lib = fancy_prompt_data.lib;
530
531                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
532                                 var msg = '';
533                                 if(obj.retrieve_ids.length > 1) {
534                                     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()]);
535                                 } else {
536                                     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()]);
537                                 }
538                                 var r = obj.error.yns_alert(msg,
539                                         $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.change_pickup_lib_title'),
540                                         $("commonStrings").getString('common.yes'),
541                                         $("commonStrings").getString('common.no'),
542                                         null,
543                                         $("commonStrings").getString('common.check_to_confirm')
544                                 );
545                                 if (r == 0) {
546                                     circ.util.batch_hold_update(hold_list, { 'pickup_lib' : pickup_lib }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
547                                 }
548                             } catch(E) {
549                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
550                             }
551                         }
552                     ],
553                     'cmd_holds_edit_phone_notify' : [
554                         ['command'],
555                         function() {
556                             try {
557                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
558                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.new_phone_number')+'</description>';
559                                 xml += '<textbox id="phone" name="fancy_data" context="clipboard"/>';
560                                 xml += '</vbox>';
561                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
562                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_done.label')+'"';
563                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_done.accesskey')+'" name="fancy_submit"/>';
564                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_cancel.label')+'"';
565                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
566                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
567                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
568                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
569                                 JSAN.use('util.window'); var win = new util.window();
570                                 var fancy_prompt_data = win.open(
571                                     urls.XUL_FANCY_PROMPT,
572                                     //+ '?xml_in_stash=temp_mid'
573                                     //+ '&bottom_xml_in_stash=temp_bot'
574                                     //+ '&title=' + window.escape('Choose a Hold Notification Phone Number')
575                                     //+ '&focus=phone',
576                                     'fancy_prompt', 'chrome,resizable,modal',
577                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.choose_phone_number'), 'focus' : 'phone' }
578                                 );
579                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
580                                 var phone = fancy_prompt_data.phone;
581
582                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
583                                 var msg = '';
584                                 if(obj.retrieve_ids.length > 1) {
585                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_phone_notify.confirm_phone_number_change.plural',[hold_list.join(', '), phone]);
586                                 } else {
587                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_phone_notify.confirm_phone_number_change.singular',[hold_list.join(', '), phone]);
588                                 }
589                                 var r = obj.error.yns_alert(msg,
590                                         $("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.modifying_holds_title'),
591                                         $("commonStrings").getString('common.yes'),
592                                         $("commonStrings").getString('common.no'),
593                                         null,
594                                         $("commonStrings").getString('common.check_to_confirm')
595                                 );
596                                 if (r == 0) {
597                                     circ.util.batch_hold_update(hold_list, { 'phone_notify' : phone }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
598                                 }
599                             } catch(E) {
600                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
601                             }
602                         }
603                     ],
604
605                     'cmd_holds_edit_sms_notify' : [
606                         ['command'],
607                         function() {
608                             try {
609                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
610                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.new_phone_number')+'</description>';
611                                 xml += '<textbox id="phone" name="fancy_data" context="clipboard"/>';
612                                 xml += '</vbox>';
613                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
614                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.btn_done.label')+'"';
615                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.btn_done.accesskey')+'" name="fancy_submit"/>';
616                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.btn_cancel.label')+'"';
617                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
618                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
619                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
620                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
621                                 JSAN.use('util.window'); var win = new util.window();
622                                 var fancy_prompt_data = win.open(
623                                     urls.XUL_FANCY_PROMPT,
624                                     //+ '?xml_in_stash=temp_mid'
625                                     //+ '&bottom_xml_in_stash=temp_bot'
626                                     //+ '&title=' + window.escape('Choose a Hold Notification Phone Number')
627                                     //+ '&focus=phone',
628                                     'fancy_prompt', 'chrome,resizable,modal',
629                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.choose_phone_number'), 'focus' : 'phone' }
630                                 );
631                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
632                                 var phone = fancy_prompt_data.phone;
633
634                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
635                                 var msg = '';
636                                 if(obj.retrieve_ids.length > 1) {
637                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_sms_notify.confirm_phone_number_change.plural',[hold_list.join(', '), phone]);
638                                 } else {
639                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_sms_notify.confirm_phone_number_change.singular',[hold_list.join(', '), phone]);
640                                 }
641                                 var r = obj.error.yns_alert(msg,
642                                         $("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.modifying_holds_title'),
643                                         $("commonStrings").getString('common.yes'),
644                                         $("commonStrings").getString('common.no'),
645                                         null,
646                                         $("commonStrings").getString('common.check_to_confirm')
647                                 );
648                                 if (r == 0) {
649                                     var hparams = {
650                                         'sms_notify' : phone == '' ? null : phone 
651                                     }
652                                     if (phone == '') {
653                                         hparams.sms_carrier = null;
654                                     }
655                                     circ.util.batch_hold_update(hold_list, hparams, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
656                                 }
657                             } catch(E) {
658                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
659                             }
660                         }
661                     ],
662
663                     'cmd_holds_edit_sms_carrier' : [
664                         ['command'],
665                         function() {
666                             try {
667                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
668
669                                 var list = util.functional.map_list(
670                                     obj.data.list.csc,
671                                     function(o) {
672                                         return [
673                                             o.name() + ' (' + o.region() + ')',
674                                             o.id(),
675                                             ( !isTrue(o.active()) ),
676                                             0
677                                         ];
678                                     }
679                                 );
680                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
681                                 ml.setAttribute('id','carrier');
682                                 ml.setAttribute('name','fancy_data');
683                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
684                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.new_carrier')+'</description>';
685                                 xml += util.widgets.serialize_node(ml);
686                                 xml += '</vbox>';
687                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
688                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.btn_done.label') +'"';
689                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.btn_done.accesskey')+'" name="fancy_submit"/>';
690                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.btn_cancel.label')+'"';
691                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
692                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
693                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
694                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
695                                 JSAN.use('util.window'); var win = new util.window();
696                                 var fancy_prompt_data = win.open(
697                                     urls.XUL_FANCY_PROMPT,
698                                     //+ '?xml_in_stash=temp_mid'
699                                     //+ '&bottom_xml_in_stash=temp_bot'
700                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
701                                     'fancy_prompt', 'chrome,resizable,modal',
702                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.choose_carrier') }
703                                 );
704                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
705                                 var sms_carrier = fancy_prompt_data.carrier;
706
707                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
708                                 var msg = '';
709
710                                 if(obj.retrieve_ids.length > 1) {
711                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_sms_carrier.confirm_carrier_change.plural',[hold_list.join(', '), obj.data.hash.csc[sms_carrier].name()]);
712                                 } else {
713                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_sms_carrier.confirm_carrier_change.singular',[hold_list.join(', '), obj.data.hash.csc[sms_carrier].name()]);
714                                 }
715                                 var r = obj.error.yns_alert(msg,
716                                         $("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.modifying_holds_title'),
717                                         $("commonStrings").getString('common.yes'),
718                                         $("commonStrings").getString('common.no'),
719                                         null,
720                                         $("commonStrings").getString('common.check_to_confirm')
721                                 );
722                                 if (r == 0) {
723                                     circ.util.batch_hold_update(hold_list, { 'sms_carrier' : sms_carrier }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
724                                 }
725                             } catch(E) {
726                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
727                             }
728                         }
729                     ],
730
731                     'cmd_holds_edit_email_notify' : [
732                         ['command'],
733                         function() {
734                             try {
735                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
736                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.description')+'</description>';
737                                 xml += '<hbox><button value="email" label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_email.label')+'"';
738                                 xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_email.accesskey')+'" name="fancy_submit"/>';
739                                 xml += '<button value="noemail" label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_no_email.label')+'"';
740                                 xml += '  accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_no_email.accesskey')+'" name="fancy_submit"/></hbox>';
741                                 xml += '</vbox>';
742                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
743                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_cancel.label')+'"';
744                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
745                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
746                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
747                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
748                                 JSAN.use('util.window'); var win = new util.window();
749                                 var fancy_prompt_data = win.open(
750                                     urls.XUL_FANCY_PROMPT,
751                                     //+ '?xml_in_stash=temp_mid'
752                                     //+ '&bottom_xml_in_stash=temp_bot'
753                                     //+ '&title=' + window.escape('Set Email Notification for Holds'),
754                                     'fancy_prompt', 'chrome,resizable,modal',
755                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.set_notifs') }
756                                 );
757                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
758                                 var email = fancy_prompt_data.fancy_submit == 'email' ? get_db_true() : get_db_false();
759
760                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
761                                 var msg = '';
762                                 if(get_bool(email)) {
763                                     if(obj.retrieve_ids.length > 1) {
764                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.enable_email.plural', [hold_list.join(', ')]);
765                                     } else {
766                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.enable_email.singular', [hold_list.join(', ')]);
767                                     }
768                                 } else {
769                                     if(obj.retrieve_ids.length > 1) {
770                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.disable_email.plural', [hold_list.join(', ')]);
771                                     } else {
772                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.disable_email.singular', [hold_list.join(', ')]);
773                                     }
774                                 }
775
776                                 var r = obj.error.yns_alert(msg,
777                                         $("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.mod_holds_title'),
778                                         $("commonStrings").getString('common.yes'),
779                                         $("commonStrings").getString('common.no'),
780                                         null,
781                                         $("commonStrings").getString('common.check_to_confirm')
782                                 );
783                                 if (r == 0) {
784                                     circ.util.batch_hold_update(hold_list, { 'email_notify' : email }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
785                                 }
786                             } catch(E) {
787                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
788                             }
789                         }
790                     ],
791                     'cmd_holds_cut_in_line' : [
792                         ['command'],
793                         function() {
794                             try {
795                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
796                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.description')+'</description>';
797                                 xml += '<hbox><button value="cut" label="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_cut.label')+'"';
798                                 xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_cut.accesskey')+'" name="fancy_submit"/>';
799                                 xml += '<button value="nocut" label="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_no_cut.label')+'"';
800                                 xml += '  accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_no_cut.accesskey')+'" name="fancy_submit"/></hbox>';
801                                 xml += '</vbox>';
802                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
803                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_cancel.label')+'"';
804                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
805                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
806                                 JSAN.use('util.window'); var win = new util.window();
807                                 var fancy_prompt_data = win.open(
808                                     urls.XUL_FANCY_PROMPT,
809                                     'fancy_prompt', 'chrome,resizable,modal',
810                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_cut_in_line.set_notifs') }
811                                 );
812                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
813                                 var cut = fancy_prompt_data.fancy_submit == 'cut' ? get_db_true() : get_db_false();
814
815                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
816                                 var msg = '';
817                                 if(get_bool(cut)) {
818                                     if(obj.retrieve_ids.length > 1) {
819                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cut_in_line.enable_cut.plural', [hold_list.join(', ')]);
820                                     } else {
821                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cut_in_line.enable_cut.singular', [hold_list.join(', ')]);
822                                     }
823                                 } else {
824                                     if(obj.retrieve_ids.length > 1) {
825                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cut_in_line.disable_cut.plural', [hold_list.join(', ')]);
826                                     } else {
827                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cut_in_line.disable_cut.singular', [hold_list.join(', ')]);
828                                     }
829                                 }
830
831                                 var r = obj.error.yns_alert(msg,
832                                         $("patronStrings").getString('staff.patron.holds.holds_cut_in_line.mod_holds_title'),
833                                         $("commonStrings").getString('common.yes'),
834                                         $("commonStrings").getString('common.no'),
835                                         null,
836                                         $("commonStrings").getString('common.check_to_confirm')
837                                 );
838                                 if (r == 0) {
839                                     circ.util.batch_hold_update(hold_list, { 'cut_in_line' : cut }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
840                                 }
841                             } catch(E) {
842                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
843                             }
844                         }
845                     ],
846                     'cmd_holds_edit_desire_mint_condition' : [
847                         ['command'],
848                         function() {
849                             try {
850                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
851                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.description')+'</description>';
852                                 xml += '<hbox><button value="good" label="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_good.label')+'"';
853                                 xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_good.accesskey')+'" name="fancy_submit"/>';
854                                 xml += '<button value="nogood" label="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_mediocre.label')+'"';
855                                 xml += '  accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_mediocre.accesskey')+'" name="fancy_submit"/></hbox>';
856                                 xml += '</vbox>';
857                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
858                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_cancel.label')+'"';
859                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
860                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
861                                 JSAN.use('util.window'); var win = new util.window();
862                                 var fancy_prompt_data = win.open(
863                                     urls.XUL_FANCY_PROMPT,
864                                     'fancy_prompt', 'chrome,resizable,modal',
865                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.set_notifs') }
866                                 );
867                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
868                                 var good = fancy_prompt_data.fancy_submit == 'good' ? get_db_true() : get_db_false();
869
870                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
871                                 var msg = '';
872                                 if(get_bool(good)) {
873                                     if(obj.retrieve_ids.length > 1) {
874                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_desire_mint_condition.enable_good.plural', [hold_list.join(', ')]);
875                                     } else {
876                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_desire_mint_condition.enable_good.singular', [hold_list.join(', ')]);
877                                     }
878                                 } else {
879                                     if(obj.retrieve_ids.length > 1) {
880                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_desire_mint_condition.disable_good.plural', [hold_list.join(', ')]);
881                                     } else {
882                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_desire_mint_condition.disable_good.singular', [hold_list.join(', ')]);
883                                     }
884                                 }
885
886                                 var r = obj.error.yns_alert(msg,
887                                         $("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.mod_holds_title'),
888                                         $("commonStrings").getString('common.yes'),
889                                         $("commonStrings").getString('common.no'),
890                                         null,
891                                         $("commonStrings").getString('common.check_to_confirm')
892                                 );
893                                 if (r == 0) {
894                                     circ.util.batch_hold_update(hold_list, { 'mint_condition' : good }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
895                                 }
896                             } catch(E) {
897                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
898                             }
899                         }
900                     ],
901
902
903                     'cmd_holds_suspend' : [
904                         ['command'],
905                         function() {
906                             try {
907                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
908                                 var r = obj.error.yns_alert(
909                                     obj.retrieve_ids.length > 1 ?
910                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.suspend.prompt.plural',[hold_list.join(', ')]) :
911                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.suspend.prompt',[hold_list.join(', ')]),
912                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds'),
913                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.yes'),
914                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.no'),
915                                     null,
916                                     document.getElementById('commonStrings').getString('common.confirm')
917                                 );
918                                 if (r == 0) {
919                                     var already_suspended = []; var filtered_hold_list = [];
920                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
921                                         var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
922                                         if ( get_bool( hold.frozen() ) ) {
923                                             already_suspended.push( hold.id() );
924                                             continue;
925                                         }
926                                         filtered_hold_list.push( hold.id() );
927                                     }
928                                     circ.util.batch_hold_update(filtered_hold_list, { 'frozen' : 't', 'thaw_date' : null }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { 
929                                         if (already_suspended.length == 1) {
930                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_suspended',[already_suspended[0]]) );
931                                         } else if (already_suspended.length > 1) {
932                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_suspended.plural',[already_suspended.join(', ')]) );
933                                         }
934                                         obj.clear_and_retrieve(true); 
935                                     } });
936                                 }
937                             } catch(E) {
938                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_suspended'),E);
939                             }
940                         }
941                     ],
942                     'cmd_holds_activate' : [
943                         ['command'],
944                         function() {
945                             try {
946                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
947                                 var r = obj.error.yns_alert(
948                                     obj.retrieve_ids.length > 1 ?
949                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.activate.prompt.plural',[hold_list.join(', ')]) :
950                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.activate.prompt',[hold_list.join(', ')]),
951                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds'),
952                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.yes'),
953                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.no'),
954                                     null,
955                                     document.getElementById('commonStrings').getString('common.confirm')
956                                 );
957                                 if (r == 0) {
958                                     var already_activated = []; var filtered_hold_list = [];
959                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
960                                         var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
961                                         if ( ! get_bool( hold.frozen() ) ) {
962                                             already_activated.push( hold.id() );
963                                             continue;
964                                         }
965                                         filtered_hold_list.push( hold.id() );
966                                     }
967                                     circ.util.batch_hold_update(filtered_hold_list, { 'frozen' : 'f', 'thaw_date' : null }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { 
968                                         if (already_activated.length == 1) {
969                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_activated',[already_activated[0]]) );
970                                         } else if (already_activated.length > 1) {
971                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_activated.plural',[already_activated.join(', ')]) );
972                                         }
973                                         obj.clear_and_retrieve(true); 
974                                     } });
975                                 }
976                             } catch(E) {
977                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_activated'),E);
978                             }
979                         }
980                     ],
981                     'cmd_holds_edit_thaw_date' : [
982                         ['command'],
983                         function() {
984                             try {
985                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
986                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.activation_date.prompt',[hold_list.join(', ')]);
987                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.activation_date.prompt.plural',[hold_list.join(', ')]);
988                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
989                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
990                                 var desc = document.getElementById('circStrings').getString('staff.circ.holds.activation_date.dialog.description');
991
992                                 JSAN.use('util.window'); var win = new util.window();
993                                 var my_xulG = win.open( 
994                                     urls.XUL_TIMESTAMP_DIALOG, 'edit_thaw_date', 'chrome,resizable,modal', 
995                                     { 
996                                         'title' : title, 
997                                         'description' : desc, 
998                                         'msg' : msg, 
999                                         'allow_unset' : true,
1000                                         'disallow_future_dates' : false,
1001                                         'disallow_past_dates' : true,
1002                                         'disallow_today' : true,
1003                                         'default_time' : '00:00:00',
1004                                         'time_readonly' : false
1005                                     }
1006                                 );
1007                                 if (my_xulG.complete) {
1008                                     circ.util.batch_hold_update(
1009                                         hold_list, 
1010                                         { 'frozen' : 't', 'thaw_date' : my_xulG.timestamp }, 
1011                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
1012                                     );
1013                                 }
1014                             } catch(E) {
1015                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
1016                             }
1017                         }
1018                     ],
1019                     'cmd_holds_edit_expire_time' : [
1020                         ['command'],
1021                         function() {
1022                             try {
1023                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1024                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.expire_time.prompt',[hold_list.join(', ')]);
1025                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.expire_time.prompt.plural',[hold_list.join(', ')]);
1026                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
1027                                 var value = 'YYYY-MM-DD';
1028                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
1029                                 var desc = document.getElementById('circStrings').getString('staff.circ.holds.expire_time.dialog.description');
1030
1031                                 JSAN.use('util.window'); var win = new util.window();
1032                                 var my_xulG = win.open( 
1033                                     urls.XUL_TIMESTAMP_DIALOG, 'edit_expire_time', 'chrome,resizable,modal', 
1034                                     { 
1035                                         'title' : title, 
1036                                         'description' : desc, 
1037                                         'msg' : msg, 
1038                                         'allow_unset' : true,
1039                                         'disallow_future_dates' : false,
1040                                         'disallow_past_dates' : true,
1041                                         'disallow_today' : true,
1042                                         'default_time' : '00:00:00',
1043                                         'time_readonly' : false
1044                                     }
1045                                 );
1046                                 if (my_xulG.complete) {
1047                                     circ.util.batch_hold_update(
1048                                         hold_list, 
1049                                         { 'expire_time' : my_xulG.timestamp }, 
1050                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
1051                                     );
1052                                 }
1053                             } catch(E) {
1054                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
1055                             }
1056                         }
1057                     ],
1058                     'cmd_holds_edit_shelf_expire_time' : [
1059                         ['command'],
1060                         function() {
1061                             try {
1062                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1063                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.shelf_expire_time.prompt',[hold_list.join(', ')]);
1064                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.shelf_expire_time.prompt.plural',[hold_list.join(', ')]);
1065                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
1066                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
1067                                 var desc = document.getElementById('circStrings').getString('staff.circ.holds.shelf_expire_time.dialog.description');
1068
1069                                 JSAN.use('util.window'); var win = new util.window();
1070                                 var my_xulG = win.open( 
1071                                     urls.XUL_TIMESTAMP_DIALOG, 'edit_shelf_expire_time', 'chrome,resizable,modal', 
1072                                     { 
1073                                         'title' : title, 
1074                                         'description' : desc, 
1075                                         'msg' : msg, 
1076                                         'allow_unset' : false,
1077                                         'disallow_future_dates' : false,
1078                                         'disallow_past_dates' : false,
1079                                         'disallow_today' : false
1080                                     }
1081                                 );
1082                                 if (my_xulG.complete) {
1083                                     circ.util.batch_hold_update(
1084                                         hold_list, 
1085                                         { 'shelf_expire_time' : my_xulG.timestamp }, 
1086                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
1087                                     );
1088                                 }
1089                             } catch(E) {
1090                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
1091                             }
1092                         }
1093                     ],
1094                     'cmd_holds_edit_request_date' : [
1095                         ['command'],
1096                         function() {
1097                             try {
1098                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1099                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.request_date.prompt',[hold_list.join(', ')]);
1100                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.request_date.prompt.plural',[hold_list.join(', ')]);
1101                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
1102                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
1103                                 var desc = document.getElementById('circStrings').getString('staff.circ.holds.request_date.dialog.description');
1104
1105                                 JSAN.use('util.window'); var win = new util.window();
1106                                 var my_xulG = win.open( 
1107                                     urls.XUL_TIMESTAMP_DIALOG, 'edit_request_date', 'chrome,resizable,modal', 
1108                                     { 
1109                                         'title' : title, 
1110                                         'description' : desc, 
1111                                         'msg' : msg, 
1112                                         'allow_unset' : false,
1113                                         'disallow_future_dates' : true,
1114                                         'disallow_past_dates' : false,
1115                                         'disallow_today' : false
1116                                     }
1117                                 );
1118                                 if (my_xulG.complete) {
1119                                     circ.util.batch_hold_update(
1120                                         hold_list, 
1121                                         { 'request_time' : my_xulG.timestamp }, 
1122                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
1123                                     );
1124                                 }
1125                             } catch(E) {
1126                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
1127                             }
1128                         }
1129                     ],
1130                     'cmd_holds_retarget' : [
1131                         ['command'],
1132                         function() {
1133                             try {
1134                                 JSAN.use('util.functional');
1135
1136                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1137                                 var msg = '';
1138                                 if(obj.retrieve_ids.length > 1) {
1139                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_retarget.reset_hold_message.plural',[hold_list.join(', ')]);
1140                                 } else {
1141                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_retarget.reset_hold_message.singular',[hold_list.join(', ')]);
1142                                 }
1143                                 var r = obj.error.yns_alert(msg,
1144                                         $("patronStrings").getString('staff.patron.holds.holds_retarget.reset_hold_title'),
1145                                         $("commonStrings").getString('common.yes'),
1146                                         $("commonStrings").getString('common.no'),
1147                                         null,
1148                                         $("commonStrings").getString('common.check_to_confirm')
1149                                 );
1150                                 if (r == 0) {
1151                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
1152                                         var robj = obj.network.simple_request('FM_AHR_RESET',[ ses(), obj.retrieve_ids[i].id]);
1153                                         if (typeof robj.ilsevent != 'undefined') throw(robj);
1154                                     }
1155                                     obj.clear_and_retrieve();
1156                                 }
1157                             } catch(E) {
1158                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_retarget.holds_not_reset'),E);
1159                             }
1160
1161                         }
1162                     ],
1163
1164                     'cmd_holds_cancel' : [
1165                         ['command'],
1166                         function() {
1167                             try {
1168                                 JSAN.use('util.functional');
1169
1170                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1171                                 var msg = '';
1172                                 if(obj.retrieve_ids.length > 1 ) {
1173                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_hold_message.plural', [hold_list.join(', ')]);
1174                                 } else {
1175                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_hold_message.singular', [hold_list.join(', ')]);
1176                                 }
1177
1178                                 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
1179                                 JSAN.use('util.window');
1180                                 var win = new util.window();
1181                                 var my_xulG = win.open(
1182                                     urls.XUL_HOLD_CANCEL,
1183                                     'hold_cancel',
1184                                     'chrome,resizable,modal',
1185                                     {}
1186                                 );
1187                                 /*var r = obj.error.yns_alert(msg,
1188                                         $("patronStrings").getString('staff.patron.holds.holds_cancel.cancel_hold_title'),
1189                                         $("commonStrings").getString('common.yes'),
1190                                         $("commonStrings").getString('common.no'),
1191                                         null,
1192                                         $("commonStrings").getString('common.check_to_confirm')
1193                                 );*/
1194
1195                                 if (my_xulG.proceed) { 
1196                                     var transits = [];
1197                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
1198                                         var transit = obj.holds_map[ obj.retrieve_ids[i].id ].hold.transit();
1199                                         if (transit && ! transit.dest_recv_time() ) {
1200                                             transits.push( obj.retrieve_ids[i].barcode );
1201                                         }
1202                                         var robj = obj.network.simple_request('FM_AHR_CANCEL',[ ses(), obj.retrieve_ids[i].id, my_xulG.cancel_reason, my_xulG.note]);
1203                                         if (typeof robj.ilsevent != 'undefined') throw(robj);
1204                                     }
1205                                     if (transits.length > 0) {
1206                                         var msg2 = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_for_barcodes', [transits.join(', ')]);
1207                                         var r2 = obj.error.yns_alert(msg2,
1208                                             $("patronStrings").getString('staff.patron.holds.holds_cancel.cancel_for_barcodes.title'),
1209                                             $("commonStrings").getString('common.yes'),
1210                                             $("commonStrings").getString('common.no'),
1211                                             null,
1212                                             $("commonStrings").getString('common.check_to_confirm'));
1213                                         if (r2 == 0) {
1214                                             try {
1215                                                 for (var i = 0; i < transits.length; i++) {
1216                                                     var robj = obj.network.simple_request('FM_ATC_VOID',[ ses(), { 'barcode' : transits[i] } ]);
1217                                                     if (typeof robj.ilsevent != 'undefined') {
1218                                                         switch(Number(robj.ilsevent)) {
1219                                                             case 1225 /* TRANSIT_ABORT_NOT_ALLOWED */ :
1220                                                                 alert(robj.desc);
1221                                                             break;
1222                                                             case 5000 /* PERM_FAILURE */ :
1223                                                             break;
1224                                                             default:
1225                                                                 throw(robj);
1226                                                             break;
1227                                                         }
1228                                                     }
1229                                                 }
1230                                             } catch(E) {
1231                                                obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_cancel.hold_transits_not_cancelled'),E);
1232                                             }
1233                                         }
1234                                     }
1235                                     obj.clear_and_retrieve();
1236                                 }
1237                             } catch(E) {
1238                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_cancel.hold_not_cancelled'),E);
1239                             }
1240                         }
1241                     ],
1242                     'cmd_holds_uncancel' : [
1243                         ['command'],
1244                         function() {
1245                             try {
1246                                 JSAN.use('util.functional');
1247                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
1248                                     var robj = obj.network.simple_request('FM_AHR_UNCANCEL',[ ses(), obj.retrieve_ids[i].id]);
1249                                     if (typeof robj.ilsevent != 'undefined') throw(robj);
1250                                 }
1251                                 obj.clear_and_retrieve();
1252                             } catch(E) {
1253                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_uncancel.hold_not_uncancelled'),E);
1254                             }
1255                         }
1256                     ],
1257
1258                     'cmd_retrieve_patron' : [
1259                         ['command'],
1260                         function() {
1261                             try {
1262                                 var seen = {};
1263                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
1264                                     var patron_id = obj.retrieve_ids[i].usr;
1265                                     if (seen[patron_id]) continue; seen[patron_id] = true;
1266                                     xulG.new_patron_tab(
1267                                         {},
1268                                         { 'id' : patron_id }
1269                                     );
1270                                 }
1271                             } catch(E) {
1272                                 obj.error.standard_unexpected_error_alert('',E);
1273                             }
1274                         }
1275                     ],
1276                     'cmd_show_catalog' : [
1277                         ['command'],
1278                         function() {
1279                             try {
1280                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
1281                                     var htarget = obj.retrieve_ids[i].target;
1282                                     var htype = obj.retrieve_ids[i].type;
1283                                     var opac_url;
1284                                     switch(htype) {
1285                                         case 'M' :
1286                                             opac_url = xulG.url_prefix( urls.opac_rresult_metarecord ) + htarget;
1287                                         break;
1288                                         case 'T' :
1289                                             opac_url = xulG.url_prefix( urls.opac_rdetail ) + htarget;
1290                                         break;
1291                                         case 'P' :
1292                                             opac_url = xulG.url_prefix( urls.opac_rdetail )
1293                                             + obj.hold_part_map[ obj.retrieve_ids[i].id ].record();
1294                                         break;
1295                                         case 'I' :
1296                                             opac_url = xulG.url_prefix( urls.opac_rdetail )
1297                                             + obj.hold_subscription_map[ obj.retrieve_ids[i].id ].record_entry();
1298                                         break;
1299                                         case 'V' :
1300                                             var my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative', [ htarget ]);
1301                                             opac_url = xulG.url_prefix( urls.opac_rdetail) + my_acn.record();
1302                                         break;
1303                                         case 'C' :
1304                                         case 'R' :
1305                                         case 'F' :
1306                                             var my_acp = obj.network.simple_request( 'FM_ACP_RETRIEVE', [ htarget ]);
1307                                             var my_acn;
1308                                             if (typeof my_acp.call_number() == 'object') {
1309                                                 my_acn = my.acp.call_number();
1310                                             } else {
1311                                                 my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative',
1312                                                     [ my_acp.call_number() ]);
1313                                             }
1314                                             opac_url = xulG.url_prefix( urls.opac_rdetail) + my_acn.record();
1315                                         break;
1316                                         default:
1317                                             obj.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.holds.show_catalog.unknown_htype', [htype]), obj.retrieve_ids[i]);
1318                                             continue;
1319                                         break;
1320                                     }
1321                                     var content_params = {
1322                                         'session' : ses(),
1323                                         'authtime' : ses('authtime'),
1324                                         'opac_url' : opac_url
1325                                     };
1326                                     xulG.new_tab(
1327                                         xulG.url_prefix(urls.XUL_OPAC_WRAPPER),
1328                                         {'tab_name': htype == 'M' ? 'Catalog' : $("patronStrings").getString('staff.patron.holds.show_catalog.retrieving_title') },
1329                                         content_params
1330                                     );
1331                                 }
1332                             } catch(E) {
1333                                 obj.error.standard_unexpected_error_alert('',E);
1334                             }
1335                         }
1336                     ],
1337                     'cmd_holds_title_transfer' : [
1338                         ['command'],
1339                         function() {
1340                             try {
1341                                 var hids = [];
1342                                 var unique_targets = [];
1343                                 var seen_target = {};
1344                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
1345                                     var hid = obj.retrieve_ids[i].id;
1346                                     var htarget = obj.retrieve_ids[i].id;
1347                                     var htype = obj.retrieve_ids[i].type;
1348                                     switch(htype) {
1349                                         case 'M' :
1350                                             continue; // not supported
1351                                         break;
1352                                         case 'T' :
1353                                             hids.push( hid );
1354                                             if (! seen_target[htarget]) {
1355                                                 unique_targets.push( htarget );
1356                                                 seen_target[htarget] = 1;
1357                                             }
1358                                         break;
1359                                         case 'V' :
1360                                             continue; // not supported
1361                                         break;
1362                                         case 'C' :
1363                                             continue; // not supported
1364                                         break;
1365                                         default:
1366                                             continue; // not supported
1367                                         break;
1368                                     }
1369                                 }
1370                                 JSAN.use('cat.util');
1371                                 cat.util.transfer_specific_title_holds(hids,unique_targets);
1372                                 obj.clear_and_retrieve();
1373                             } catch(E) {
1374                                 obj.error.standard_unexpected_error_alert('',E);
1375                             }
1376                         }
1377                     ],
1378
1379                     'fetch_more' : [
1380                         ['command'],
1381                         function() {
1382                             obj.pull_from_shelf_interface.current.offset += obj.pull_from_shelf_interface.current.limit;
1383                             obj.retrieve(true);
1384                         }
1385                     ],
1386                     'lib_filter_checkbox' : [
1387                         ['command'],
1388                         function(ev) {
1389                             var x_lib_type_menu = document.getElementById('lib_type_menu');
1390                             if (x_lib_type_menu) x_lib_type_menu.disabled = ! ev.target.checked;
1391                             if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = ! ev.target.checked;
1392                             obj.clear_and_retrieve();
1393                             ev.target.setAttribute('checked',ev.target.checked);
1394                         }
1395                     ],
1396                     'cmd_view_expired_onshelf_holds' : [
1397                         ['command'],
1398                         function(ev) {
1399                             var x = document.getElementById('expired_checkbox'); // can't trust ev.explicitOriginalTarget, sometimes gives a "button"
1400                             obj.expired = x.checked;
1401                             obj.controller.view.cmd_clear_expired_onshelf_holds.setAttribute('disabled', !obj.expired);
1402                             obj.clear_and_retrieve();
1403                         }
1404                     ],
1405                     'cmd_clear_expired_onshelf_holds' : [
1406                         ['command'],
1407                         function(ev) {
1408                             obj.cmd_clear_expired_onshelf_holds();
1409                         }
1410                     ],
1411                     'cmd_search_opac' : [
1412                         ['command'],
1413                         function(ev) {
1414                             try {
1415                                 var use_url = urls.browser;
1416                                 use_url += use_url.match(/\?/) ? "&" : "?";
1417                                 use_url += "patron_barcode=" + obj.patron_barcode;
1418                                 var content_params = {
1419                                     'show_nav_buttons' : false,
1420                                     'show_print_button' : true,
1421                                     'passthru_content_params' : {
1422                                         'authtoken' : ses(),
1423                                         'authtime' : ses('authtime'),
1424                                         'window_open' : function(a,b,c) {
1425                                             try {
1426                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
1427                                                 return window.open(a,b,c);
1428                                             } catch(E) {
1429                                                 obj.error.standard_unexpected_error_alert('window_open',E);
1430                                             }
1431                                         },
1432                                         'opac_hold_placed' : function(hold) {
1433                                             try {
1434                                                 obj.list.append(
1435                                                     {
1436                                                         'row' : {
1437                                                             'my' : {
1438                                                                 'hold_id' : typeof hold == 'object' ? hold.id() : hold
1439                                                             }
1440                                                         }
1441                                                     }
1442                                                 );
1443                                                 if (window.xulG && typeof window.xulG.on_list_change == 'function') {
1444                                                     window.xulG.on_list_change(); 
1445                                                 }
1446                                             } catch(E) {
1447                                                 obj.error.standard_unexpected_error_alert('holds.js, opac_hold_placed(): ',E);
1448                                             }
1449                                         },
1450                                         'patron_barcode' : obj.patron_barcode
1451                                     },
1452                                     'url_prefix' : xulG.url_prefix,
1453                                     'url' : xulG.url_prefix(use_url)
1454                                 };
1455                                 xulG.display_window.g.patron.right_deck.set_iframe( urls.XUL_REMOTE_BROWSER + '?patron_hold=1', {}, content_params);
1456                             } catch(E) {
1457                                 obj.error.sdump('D_ERROR','cmd_search_opac: ' + E);
1458                             }
1459
1460                         }
1461                     ]
1462                 }
1463             }
1464         );
1465
1466         obj.determine_hold_interface_type();
1467         var x_fetch_more = document.getElementById('fetch_more');
1468         var x_lib_type_menu = document.getElementById('lib_type_menu');
1469         var x_lib_menu_placeholder = document.getElementById('lib_menu_placeholder');
1470         var x_lib_filter_checkbox = document.getElementById('lib_filter_checkbox');
1471         var x_show_cancelled_deck = document.getElementById('show_cancelled_deck');
1472         var x_clear_shelf_widgets = document.getElementById('clear_shelf_widgets');
1473         var x_expired_checkbox = document.getElementById('expired_checkbox');
1474         var x_print_full_pull_list = document.getElementById('print_full_btn');
1475         var x_print_full_pull_list_alt = document.getElementById('print_alt_btn');
1476         switch(obj.hold_interface_type) {
1477             case 'shelf':
1478                 obj.render_lib_menus({'pickup_lib':true});
1479                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.checked = true;
1480                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
1481                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
1482                 if (x_clear_shelf_widgets) x_clear_shelf_widgets.hidden = false;
1483                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = true;
1484             break;
1485             case 'pull' :
1486                 if (x_fetch_more) x_fetch_more.hidden = false;
1487                 if (x_print_full_pull_list) x_print_full_pull_list.hidden = false;
1488                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = false;
1489                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
1490                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
1491             break;
1492             case 'record' :
1493                 obj.render_lib_menus({'pickup_lib':true,'request_lib':true});
1494                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.hidden = false;
1495                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
1496                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = true;
1497                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
1498             break;
1499             default:
1500                 if (obj.controller.view.cmd_search_opac) obj.controller.view.cmd_search_opac.setAttribute('hidden', false);
1501                 if (x_fetch_more) x_fetch_more.hidden = true;
1502                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
1503                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
1504                 if (x_show_cancelled_deck) x_show_cancelled_deck.hidden = false;
1505                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = true;
1506             break;
1507         }
1508         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
1509             function() {
1510                 if (x_lib_filter_checkbox) if (!x_lib_filter_checkbox.checked) {
1511                     if (x_lib_type_menu) x_lib_type_menu.disabled = true;
1512                     if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = true;
1513                 }
1514                 obj.controller.render();
1515                 obj.retrieve(true);
1516
1517                 obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
1518                 obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
1519                 obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
1520                 obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
1521                 obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','true');
1522                 obj.controller.view.cmd_holds_activate.setAttribute('disabled','true');
1523                 obj.controller.view.cmd_holds_suspend.setAttribute('disabled','true');
1524                 obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
1525                 obj.controller.view.cmd_alt_view.setAttribute('disabled','true');
1526                 obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
1527                 obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
1528                 obj.controller.view.cmd_holds_uncancel.setAttribute('disabled','true');
1529                 obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
1530             }, 0
1531         );
1532
1533         $('cmd_alt_view').setAttribute('disabled','true');
1534         xulG.when_done = function() {
1535             $('cmd_alt_view').setAttribute('ready','true');
1536             if ($('cmd_alt_view').getAttribute('rendering_rows') != 'true') {
1537                 $('cmd_alt_view').setAttribute('disabled','false');
1538             }
1539             dump('hold details UI ready\n');
1540         }
1541         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
1542         JSAN.use('util.browser');
1543         obj.browser = new util.browser();
1544         obj.browser.init(
1545             {
1546                 'url' : urls.XUL_HOLD_DETAILS,
1547                 'push_xulG' : true,
1548                 'alt_print' : false,
1549                 'browser_id' : 'hold_detail_frame',
1550                 'passthru_content_params' : xulG
1551             }
1552         );
1553
1554     },
1555
1556     'determine_hold_interface_type' : function() {
1557         var obj = this;
1558         if (obj.patron_id) { /*************************************************** PATRON ******************************/
1559             obj.hold_interface_type = 'patron';
1560         } else if (obj.docid) { /*************************************************** RECORD ******************************/
1561             obj.hold_interface_type = 'record';
1562         } else if (obj.pull) { /*************************************************** PULL ******************************/
1563             obj.hold_interface_type = 'pull';
1564         } else if (obj.shelf) { /*************************************************** HOLD SHELF ******************************/
1565             obj.hold_interface_type = 'shelf';
1566         } else { /*************************************************** PULL ******************************/
1567             obj.hold_interface_type = 'pull';
1568         }
1569     },
1570
1571     'clear_and_retrieve' : function() {
1572         try {
1573             this.list.clear();
1574             this.pull_from_shelf_interface.current.offset = this.pull_from_shelf_interface._default.offset;
1575             this.retrieve();
1576             if (window.xulG && typeof window.xulG.on_list_change == 'function') {
1577                 window.xulG.on_list_change(); 
1578             }
1579         } catch(E) {
1580             this.error.standard_unexpected_error_alert('holds.js, clear_and_retrieve(): ',E);
1581         }
1582     },
1583
1584     'retrieve' : function() {
1585         var obj = this; var holds = [];
1586         if (window.xulG && window.xulG.holds) {
1587             holds = window.xulG.holds;
1588         } else {
1589             var method; var params = [ ses() ];
1590             switch(obj.hold_interface_type) {
1591                 case 'patron' :
1592                     if (document.getElementById('show_cancelled_deck').selectedIndex == 0) {
1593                         method = 'FM_AHR_ID_LIST_RETRIEVE_VIA_AU.authoritative';
1594                     } else {
1595                         method = 'FM_AHR_CANCELLED_ID_LIST_RETRIEVE_VIA_AU.authoritative';
1596                     }
1597                     params.push( obj.patron_id );
1598                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','true');
1599                 break;
1600                 case 'record' :
1601                     method = 'FM_AHR_RETRIEVE_ALL_VIA_BRE';
1602                     params.push( obj.docid );
1603                     var x_lib_filter = document.getElementById('lib_filter_checkbox');
1604                     var x_lib_type_menu = document.getElementById('lib_type_menu');
1605                     if (x_lib_filter) {
1606                         if (x_lib_filter.checked) {
1607                             if (x_lib_type_menu && obj.controller.view.lib_menu) {
1608                                 var x = {};
1609                                 x[ x_lib_type_menu.value ] = obj.controller.view.lib_menu.value;
1610                                 params.push( x );
1611                             }
1612                         }
1613                     }
1614                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1615                 break;
1616                 case 'shelf' :
1617                     if (obj.expired) {
1618                         method = 'FM_AHR_ID_LIST_EXPIRED_ONSHELF_RETRIEVE';
1619                     } else {
1620                         method = 'FM_AHR_ID_LIST_ONSHELF_RETRIEVE';
1621                     }
1622                     params.push( obj.filter_lib || obj.data.list.au[0].ws_ou() );
1623                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1624                 break;
1625                 case 'pull' :
1626                 default:
1627                     method = 'FM_AHR_ID_LIST_PULL_LIST';
1628                     params.push( obj.pull_from_shelf_interface.current.limit ); params.push( obj.pull_from_shelf_interface.current.offset );
1629                     var x = document.getElementById('hold_count');
1630                     if (x) {
1631                         obj.network.simple_request('FM_AHR_PULL_LIST_COUNT',[ses()],function(req) {
1632                             var count = req.getResultObject();
1633                             if (typeof count.ilsevent == 'undefined' && count != null) {
1634                                 x.setAttribute('value', document.getElementById('patronStrings').getFormattedString(
1635                                     'staff.patron.holds.total_count',
1636                                     [ count ]
1637                                 ));
1638                                 x.hidden = false;
1639                             }
1640                         });
1641                     }
1642                 break;
1643             }
1644             var robj = obj.network.simple_request( method, params );
1645             if (robj != null && typeof robj.ilsevent != 'undefined') throw(robj);
1646             if (method == 'FM_AHR_RETRIEVE_ALL_VIA_BRE') {
1647                 holds = [];
1648                 if (robj != null) {
1649                     holds = holds.concat( robj.copy_holds );
1650                     holds = holds.concat( robj.recall_holds );
1651                     holds = holds.concat( robj.force_holds );
1652                     holds = holds.concat( robj.volume_holds );
1653                     holds = holds.concat( robj.title_holds );
1654                     holds = holds.concat( robj.part_holds );
1655                     holds = holds.concat( robj.issuance_holds );
1656                     holds = holds.concat( robj.metarecord_holds );
1657                     holds = holds.sort();
1658                 }
1659             } else {
1660                 if (robj == null ) {
1661                     holds = [];
1662                 } else {
1663                     if (typeof robj.length == 'undefined') {
1664                         holds = [ robj ];
1665                     } else {
1666                         holds = robj;
1667                     }
1668                 }
1669             }
1670             holds.reverse();
1671             //alert('method = ' + method + ' params = ' + js2JSON(params));
1672         }
1673
1674         var x_fetch_more = document.getElementById('fetch_more');
1675         if (holds.length == 0) {
1676             if (x_fetch_more) x_fetch_more.disabled = true;
1677         } else {
1678             if (x_fetch_more) x_fetch_more.disabled = false;
1679             obj.render(holds);
1680         }
1681
1682     },
1683
1684     'render' : function(holds) {
1685         try {
1686             var obj = this;
1687
1688             function list_append(hold_id) {
1689                 obj.list.append(
1690                     {
1691                         'row' : {
1692                             'my' : {
1693                                 'hold_id' : hold_id,
1694                                 'post_clear_shelf_action' : obj.post_clear_shelf_hold_action_map[ hold_id ]
1695                             }
1696                         },
1697                         'to_bottom' : true
1698                     }
1699                 );
1700             }
1701
1702             function gen_list_append(hold) {
1703                 return function() {
1704                     if (typeof obj.controller.view.lib_menu == 'undefined') {
1705                         list_append(typeof hold == 'object' ? hold.id() : hold);
1706                     } else {
1707                         list_append(typeof hold == 'object' ? hold.id() : hold);
1708                     }
1709                 };
1710             }
1711
1712             //obj.list.clear();
1713
1714             JSAN.use('util.exec'); var exec = new util.exec(2);
1715             var rows = [];
1716             for (var i in holds) {
1717                 rows.push( gen_list_append(holds[i]) );
1718             }
1719             exec.chain( rows );
1720
1721         } catch(E) {
1722             this.error.standard_unexpected_error_alert('holds.js, render():',E);
1723         }
1724     },
1725
1726     'render_lib_menus' : function(types) {
1727         try {
1728             var obj = this;
1729             JSAN.use('util.widgets'); JSAN.use('util.functional'); JSAN.use('util.fm_utils');
1730
1731             var x = document.getElementById('lib_type_menu');
1732             if (types) {
1733                 var nodes = x.firstChild.childNodes;
1734                 for (var i = 0; i < nodes.length; i++) nodes[i].hidden = true;
1735                 for (var i in types) document.getElementById(i).hidden = false;
1736             }
1737             x.setAttribute('oncommand','g.holds.clear_and_retrieve()');
1738
1739             x = document.getElementById('lib_menu_placeholder');
1740             util.widgets.remove_children( x );
1741
1742             JSAN.use('util.file');
1743             var file = new util.file('offline_ou_list');
1744             if (file._file.exists()) {
1745                 var list_data = file.get_object(); file.close();
1746                 var ml = util.widgets.make_menulist( list_data[0], obj.data.list.au[0].ws_ou() );
1747                 ml.setAttribute('id','lib_menu');
1748                 x.appendChild( ml );
1749                 ml.addEventListener(
1750                     'command',
1751                     function(ev) {
1752                         obj.filter_lib = ev.target.value;
1753                         obj.clear_and_retrieve();
1754                     },
1755                     false
1756                 );
1757                 obj.controller.view.lib_menu = ml;
1758             } else {
1759                 throw($("patronStrings").getString('staff.patron.holds.lib_menus.missing_library_list'));
1760             }
1761
1762         } catch(E) {
1763             this.error.standard_unexpected_error_alert('rendering lib menu',E);
1764         }
1765     },
1766
1767     'cmd_clear_expired_onshelf_holds' : function() {
1768         var obj = this;
1769         try {
1770             // Disable anything such as filters that can have us accidentally
1771             // lose these non-repeatable results.  Well, now that they're cached
1772             // it's less of an issue.
1773             if ($('lib_filter_checkbox')) {
1774                 $('lib_filter_checkbox').checked = false;
1775             }
1776             if ($('lib_type_menu')) {
1777                 $('lib_type_menu').disabled = true;
1778             }
1779             if ($('lib_menu_placeholder')) {
1780                 $('lib_menu_placeholder').firstChild.disabled = true;
1781             }
1782             obj.controller.view.cmd_view_expired_onshelf_holds.setAttribute(
1783                 'disabled', 'true');
1784             obj.controller.view.cmd_clear_expired_onshelf_holds.setAttribute(
1785                 'disabled', 'true');
1786
1787             // I could put this with the "retrieval" methods, but since it has
1788             // side effects, seems cleaner to invoke it here
1789             var robj = obj.network.simple_request(
1790                 'CLEAR_HOLD_SHELF',
1791                 [
1792                     ses(),
1793                     obj.filter_lib || obj.data.list.au[0].ws_ou()
1794                 ]
1795             );
1796             if (typeof robj.ilsevent != 'undefined') { throw(robj); }
1797             if (typeof robj.cache_key == 'undefined') { throw(robj); }
1798
1799             var cache_key = robj.cache_key;
1800
1801             // id's in xulG.holds will prevent the normal retrieval method from
1802             // firing.  Let's put our affected hold.id's in here:
1803             xulG.holds = [];
1804
1805             // Start the progress meter
1806             $('progress').value = 0;
1807             $('progress').hidden = false;
1808
1809             // Fetch the affected holds
1810             fieldmapper.standardRequest(
1811                 [ 'open-ils.circ', 'open-ils.circ.hold.clear_shelf.get_cache' ],
1812                 {
1813                     'async' : true,
1814                     'params' : [ ses(), cache_key ],
1815                     'onresponse' : function(r) {
1816                         dojo.forEach(
1817                             openils.Util.readResponse(r),
1818                             function(resp) {
1819                                 if (resp.maximum) {
1820                                     $('progress').value = Number(resp.progress)
1821                                         * 100/resp.maximum;
1822                                     return;
1823                                 }
1824                                 obj.post_clear_shelf_hold_action_map[
1825                                     resp.hold_details.id
1826                                 ] = resp.action;
1827                                 xulG.holds.push( resp.hold_details.id );
1828                             }
1829                         )
1830                     },
1831                     'oncomplete' : function() {
1832                         obj.clear_and_retrieve();
1833                         $('progress').hidden = true;
1834                     }
1835                 }
1836             );
1837
1838         } catch(E) {
1839             if (E.ilsevent == 5000 /* PERM_FAILURE */ ) {
1840                 return; /* handled by network.js */
1841             }
1842             obj.error.standard_unexpected_error_alert(
1843                 'Error in holds.js, cmd_clear_expired_onshelf_holds', E);
1844         }
1845     }
1846 }
1847
1848 dump('exiting patron.holds.js\n');