]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/xul/staff_client/server/patron/holds.js
Stop saving patron barcode in cookies
[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.treeitem_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                                 };
400                                 switch(obj.hold_interface_type) {
401                                     case 'patron':
402                                         params.template = 'holds_for_patron';
403                                     break;
404                                     case 'record':
405                                         params.template = 'holds_on_bib';
406                                     break;
407                                     case 'shelf':
408                                         params.template = 'holds_shelf';
409                                     break;
410                                     case 'pull':
411                                     default:
412                                         params.template = 'holds_pull_list';
413                                     break;
414                                 }
415                                 obj.list.print(params);
416                             } catch(E) {
417                                 obj.error.standard_unexpected_error_alert('print 1',E);
418                             }
419                         }
420                     ],
421                     'cmd_csv_to_clipboard' : [ ['command'], function() { obj.list.dump_csv_to_clipboard(); } ],
422                     'cmd_csv_to_printer' : [ ['command'], function() { obj.list.dump_csv_to_printer(); } ],
423                     'cmd_csv_to_file' : [ ['command'], function() { obj.list.dump_csv_to_file( { 'defaultFileName' : 'holds.txt' } ); } ],
424
425                     'cmd_holds_edit_selection_depth' : [
426                         ['command'],
427                         function() {
428                             try {
429                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
430                                 var ws_type = obj.data.hash.aout[ obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ].ou_type() ];
431                                 var list = util.functional.map_list(
432                                     util.functional.filter_list(
433                                         obj.data.list.aout,
434                                         function(o) {
435                                             if (o.depth() > ws_type.depth()) return false;
436                                             if (o.depth() < ws_type.depth()) return true;
437                                             return (o.id() == ws_type.id());
438                                         }
439                                     ),
440                                     function(o) {
441                                         return [
442                                             o.opac_label(),
443                                             o.id(),
444                                             false,
445                                             ( o.depth() * 2),
446                                         ];
447                                     }
448                                 );
449                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
450                                 ml.setAttribute('id','selection');
451                                 ml.setAttribute('name','fancy_data');
452                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
453                                 xml += '<description>' + $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.choose_hold_range') + '</description>';
454                                 xml += util.widgets.serialize_node(ml);
455                                 xml += '</vbox>';
456                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
457                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.done.label') +'"';
458                                 bot_xml += 'accesskey="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.done.accesskey') +'" name="fancy_submit"/>';
459                                 bot_xml += '<button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.cancel.label') +'"';
460                                 bot_xml += 'accesskey="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.cancel.accesskey') +'" name="fancy_cancel"/></hbox>';
461                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
462                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
463                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
464                                 JSAN.use('util.window'); var win = new util.window();
465                                 var fancy_prompt_data = win.open(
466                                     urls.XUL_FANCY_PROMPT,
467                                     //+ '?xml_in_stash=temp_mid'
468                                     //+ '&bottom_xml_in_stash=temp_bot'
469                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
470                                     'fancy_prompt', 'chrome,resizable,modal',
471                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.choose_library') }
472                                 );
473                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
474                                 var selection = fancy_prompt_data.selection;
475
476                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
477                                 var msg = '';
478                                 if(obj.retrieve_ids.length > 1) {
479                                     msg = $("patronStrings").getformattedString('staff.patron.holds.holds_edit_selection_depth.modify_holds_message.plural', [hold_list.join(', '), obj.data.hash.aout[selection].opac_label()])
480                                 } else {
481                                     msg = $("patronStrings").getformattedString('staff.patron.holds.holds_edit_selection_depth.modify_holds_message.singular', [hold_list.join(', '), obj.data.hash.aout[selection].opac_label()])
482                                 }
483
484                                 var r = obj.error.yns_alert(msg,
485                                         $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.modify_holds_title'),
486                                         $("commonStrings").getString('common.yes'),
487                                         $("commonStrings").getString('common.no'),
488                                         null,
489                                         $("commonStrings").getString('common.check_to_confirm')
490                                 );
491                                 if (r == 0) {
492                                     circ.util.batch_hold_update(hold_list, { 'selection_depth' : obj.data.hash.aout[selection].depth() }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
493                                 }
494                             } catch(E) {
495                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
496                             }
497                         }
498                     ],
499
500                     'cmd_holds_edit_pickup_lib' : [
501                         ['command'],
502                         function() {
503                             try {
504                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
505
506                                 var list = util.functional.map_list(
507                                     obj.data.list.aou,
508                                     function(o) {
509                                         var sname = o.shortname(); for (i = sname.length; i < 20; i++) sname += ' ';
510                                         return [
511                                             o.name() ? sname + ' ' + o.name() : o.shortname(),
512                                             o.id(),
513                                             ( !isTrue(obj.data.hash.aout[ o.ou_type() ].can_have_users()) ),
514                                             ( obj.data.hash.aout[ o.ou_type() ].depth() * 2),
515                                         ];
516                                     }
517                                 );
518                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
519                                 ml.setAttribute('id','lib');
520                                 ml.setAttribute('name','fancy_data');
521                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
522                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.new_pickup_lib.description')+'</description>';
523                                 xml += util.widgets.serialize_node(ml);
524                                 xml += '</vbox>';
525                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
526                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.done.label') +'"';
527                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.done.accesskey')+'" name="fancy_submit"/>';
528                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.cancel.label')+'"';
529                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
530                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
531                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
532                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
533                                 JSAN.use('util.window'); var win = new util.window();
534                                 var fancy_prompt_data = win.open(
535                                     urls.XUL_FANCY_PROMPT,
536                                     //+ '?xml_in_stash=temp_mid'
537                                     //+ '&bottom_xml_in_stash=temp_bot'
538                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
539                                     'fancy_prompt', 'chrome,resizable,modal',
540                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.choose_lib') }
541                                 );
542                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
543                                 var pickup_lib = fancy_prompt_data.lib;
544
545                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
546                                 var msg = '';
547                                 if(obj.retrieve_ids.length > 1) {
548                                     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()]);
549                                 } else {
550                                     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()]);
551                                 }
552                                 var r = obj.error.yns_alert(msg,
553                                         $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.change_pickup_lib_title'),
554                                         $("commonStrings").getString('common.yes'),
555                                         $("commonStrings").getString('common.no'),
556                                         null,
557                                         $("commonStrings").getString('common.check_to_confirm')
558                                 );
559                                 if (r == 0) {
560                                     circ.util.batch_hold_update(hold_list, { 'pickup_lib' : pickup_lib }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
561                                 }
562                             } catch(E) {
563                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
564                             }
565                         }
566                     ],
567                     'cmd_holds_edit_phone_notify' : [
568                         ['command'],
569                         function() {
570                             try {
571                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
572                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.new_phone_number')+'</description>';
573                                 xml += '<textbox id="phone" name="fancy_data" context="clipboard"/>';
574                                 xml += '</vbox>';
575                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
576                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_done.label')+'"';
577                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_done.accesskey')+'" name="fancy_submit"/>';
578                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_cancel.label')+'"';
579                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
580                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
581                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
582                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
583                                 JSAN.use('util.window'); var win = new util.window();
584                                 var fancy_prompt_data = win.open(
585                                     urls.XUL_FANCY_PROMPT,
586                                     //+ '?xml_in_stash=temp_mid'
587                                     //+ '&bottom_xml_in_stash=temp_bot'
588                                     //+ '&title=' + window.escape('Choose a Hold Notification Phone Number')
589                                     //+ '&focus=phone',
590                                     'fancy_prompt', 'chrome,resizable,modal',
591                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.choose_phone_number'), 'focus' : 'phone' }
592                                 );
593                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
594                                 var phone = fancy_prompt_data.phone;
595
596                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
597                                 var msg = '';
598                                 if(obj.retrieve_ids.length > 1) {
599                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_phone_notify.confirm_phone_number_change.plural',[hold_list.join(', '), phone]);
600                                 } else {
601                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_phone_notify.confirm_phone_number_change.singular',[hold_list.join(', '), phone]);
602                                 }
603                                 var r = obj.error.yns_alert(msg,
604                                         $("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.modifying_holds_title'),
605                                         $("commonStrings").getString('common.yes'),
606                                         $("commonStrings").getString('common.no'),
607                                         null,
608                                         $("commonStrings").getString('common.check_to_confirm')
609                                 );
610                                 if (r == 0) {
611                                     circ.util.batch_hold_update(hold_list, { 'phone_notify' : phone }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
612                                 }
613                             } catch(E) {
614                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
615                             }
616                         }
617                     ],
618
619                     'cmd_holds_edit_sms_notify' : [
620                         ['command'],
621                         function() {
622                             try {
623                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
624                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.new_phone_number')+'</description>';
625                                 xml += '<textbox id="phone" name="fancy_data" context="clipboard"/>';
626                                 xml += '</vbox>';
627                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
628                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.btn_done.label')+'"';
629                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.btn_done.accesskey')+'" name="fancy_submit"/>';
630                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.btn_cancel.label')+'"';
631                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
632                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
633                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
634                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
635                                 JSAN.use('util.window'); var win = new util.window();
636                                 var fancy_prompt_data = win.open(
637                                     urls.XUL_FANCY_PROMPT,
638                                     //+ '?xml_in_stash=temp_mid'
639                                     //+ '&bottom_xml_in_stash=temp_bot'
640                                     //+ '&title=' + window.escape('Choose a Hold Notification Phone Number')
641                                     //+ '&focus=phone',
642                                     'fancy_prompt', 'chrome,resizable,modal',
643                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.choose_phone_number'), 'focus' : 'phone' }
644                                 );
645                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
646                                 var phone = fancy_prompt_data.phone;
647
648                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
649                                 var msg = '';
650                                 if(obj.retrieve_ids.length > 1) {
651                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_sms_notify.confirm_phone_number_change.plural',[hold_list.join(', '), phone]);
652                                 } else {
653                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_sms_notify.confirm_phone_number_change.singular',[hold_list.join(', '), phone]);
654                                 }
655                                 var r = obj.error.yns_alert(msg,
656                                         $("patronStrings").getString('staff.patron.holds.holds_edit_sms_notify.modifying_holds_title'),
657                                         $("commonStrings").getString('common.yes'),
658                                         $("commonStrings").getString('common.no'),
659                                         null,
660                                         $("commonStrings").getString('common.check_to_confirm')
661                                 );
662                                 if (r == 0) {
663                                     var hparams = {
664                                         'sms_notify' : phone == '' ? null : phone 
665                                     }
666                                     if (phone == '') {
667                                         hparams.sms_carrier = null;
668                                     }
669                                     circ.util.batch_hold_update(hold_list, hparams, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
670                                 }
671                             } catch(E) {
672                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
673                             }
674                         }
675                     ],
676
677                     'cmd_holds_edit_sms_carrier' : [
678                         ['command'],
679                         function() {
680                             try {
681                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
682
683                                 var list = util.functional.map_list(
684                                     obj.data.list.csc,
685                                     function(o) {
686                                         return [
687                                             o.name() + ' (' + o.region() + ')',
688                                             o.id(),
689                                             ( !isTrue(o.active()) ),
690                                             0
691                                         ];
692                                     }
693                                 );
694                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
695                                 ml.setAttribute('id','carrier');
696                                 ml.setAttribute('name','fancy_data');
697                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
698                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.new_carrier')+'</description>';
699                                 xml += util.widgets.serialize_node(ml);
700                                 xml += '</vbox>';
701                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
702                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.btn_done.label') +'"';
703                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.btn_done.accesskey')+'" name="fancy_submit"/>';
704                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.btn_cancel.label')+'"';
705                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
706                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
707                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
708                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
709                                 JSAN.use('util.window'); var win = new util.window();
710                                 var fancy_prompt_data = win.open(
711                                     urls.XUL_FANCY_PROMPT,
712                                     //+ '?xml_in_stash=temp_mid'
713                                     //+ '&bottom_xml_in_stash=temp_bot'
714                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
715                                     'fancy_prompt', 'chrome,resizable,modal',
716                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.choose_carrier') }
717                                 );
718                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
719                                 var sms_carrier = fancy_prompt_data.carrier;
720
721                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
722                                 var msg = '';
723
724                                 if(obj.retrieve_ids.length > 1) {
725                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_sms_carrier.confirm_carrier_change.plural',[hold_list.join(', '), obj.data.hash.csc[sms_carrier].name()]);
726                                 } else {
727                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_sms_carrier.confirm_carrier_change.singular',[hold_list.join(', '), obj.data.hash.csc[sms_carrier].name()]);
728                                 }
729                                 var r = obj.error.yns_alert(msg,
730                                         $("patronStrings").getString('staff.patron.holds.holds_edit_sms_carrier.modifying_holds_title'),
731                                         $("commonStrings").getString('common.yes'),
732                                         $("commonStrings").getString('common.no'),
733                                         null,
734                                         $("commonStrings").getString('common.check_to_confirm')
735                                 );
736                                 if (r == 0) {
737                                     circ.util.batch_hold_update(hold_list, { 'sms_carrier' : sms_carrier }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
738                                 }
739                             } catch(E) {
740                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
741                             }
742                         }
743                     ],
744
745                     'cmd_holds_edit_email_notify' : [
746                         ['command'],
747                         function() {
748                             try {
749                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
750                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.description')+'</description>';
751                                 xml += '<hbox><button value="email" label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_email.label')+'"';
752                                 xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_email.accesskey')+'" name="fancy_submit"/>';
753                                 xml += '<button value="noemail" label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_no_email.label')+'"';
754                                 xml += '  accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_no_email.accesskey')+'" name="fancy_submit"/></hbox>';
755                                 xml += '</vbox>';
756                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
757                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_cancel.label')+'"';
758                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
759                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
760                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
761                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
762                                 JSAN.use('util.window'); var win = new util.window();
763                                 var fancy_prompt_data = win.open(
764                                     urls.XUL_FANCY_PROMPT,
765                                     //+ '?xml_in_stash=temp_mid'
766                                     //+ '&bottom_xml_in_stash=temp_bot'
767                                     //+ '&title=' + window.escape('Set Email Notification for Holds'),
768                                     'fancy_prompt', 'chrome,resizable,modal',
769                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.set_notifs') }
770                                 );
771                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
772                                 var email = fancy_prompt_data.fancy_submit == 'email' ? get_db_true() : get_db_false();
773
774                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
775                                 var msg = '';
776                                 if(get_bool(email)) {
777                                     if(obj.retrieve_ids.length > 1) {
778                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.enable_email.plural', [hold_list.join(', ')]);
779                                     } else {
780                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.enable_email.singular', [hold_list.join(', ')]);
781                                     }
782                                 } else {
783                                     if(obj.retrieve_ids.length > 1) {
784                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.disable_email.plural', [hold_list.join(', ')]);
785                                     } else {
786                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.disable_email.singular', [hold_list.join(', ')]);
787                                     }
788                                 }
789
790                                 var r = obj.error.yns_alert(msg,
791                                         $("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.mod_holds_title'),
792                                         $("commonStrings").getString('common.yes'),
793                                         $("commonStrings").getString('common.no'),
794                                         null,
795                                         $("commonStrings").getString('common.check_to_confirm')
796                                 );
797                                 if (r == 0) {
798                                     circ.util.batch_hold_update(hold_list, { 'email_notify' : email }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
799                                 }
800                             } catch(E) {
801                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
802                             }
803                         }
804                     ],
805                     'cmd_holds_cut_in_line' : [
806                         ['command'],
807                         function() {
808                             try {
809                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
810                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.description')+'</description>';
811                                 xml += '<hbox><button value="cut" label="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_cut.label')+'"';
812                                 xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_cut.accesskey')+'" name="fancy_submit"/>';
813                                 xml += '<button value="nocut" label="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_no_cut.label')+'"';
814                                 xml += '  accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_no_cut.accesskey')+'" name="fancy_submit"/></hbox>';
815                                 xml += '</vbox>';
816                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
817                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_cancel.label')+'"';
818                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_cut_in_line.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
819                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
820                                 JSAN.use('util.window'); var win = new util.window();
821                                 var fancy_prompt_data = win.open(
822                                     urls.XUL_FANCY_PROMPT,
823                                     'fancy_prompt', 'chrome,resizable,modal',
824                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_cut_in_line.set_notifs') }
825                                 );
826                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
827                                 var cut = fancy_prompt_data.fancy_submit == 'cut' ? get_db_true() : get_db_false();
828
829                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
830                                 var msg = '';
831                                 if(get_bool(cut)) {
832                                     if(obj.retrieve_ids.length > 1) {
833                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cut_in_line.enable_cut.plural', [hold_list.join(', ')]);
834                                     } else {
835                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cut_in_line.enable_cut.singular', [hold_list.join(', ')]);
836                                     }
837                                 } else {
838                                     if(obj.retrieve_ids.length > 1) {
839                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cut_in_line.disable_cut.plural', [hold_list.join(', ')]);
840                                     } else {
841                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cut_in_line.disable_cut.singular', [hold_list.join(', ')]);
842                                     }
843                                 }
844
845                                 var r = obj.error.yns_alert(msg,
846                                         $("patronStrings").getString('staff.patron.holds.holds_cut_in_line.mod_holds_title'),
847                                         $("commonStrings").getString('common.yes'),
848                                         $("commonStrings").getString('common.no'),
849                                         null,
850                                         $("commonStrings").getString('common.check_to_confirm')
851                                 );
852                                 if (r == 0) {
853                                     circ.util.batch_hold_update(hold_list, { 'cut_in_line' : cut }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
854                                 }
855                             } catch(E) {
856                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
857                             }
858                         }
859                     ],
860                     'cmd_holds_edit_desire_mint_condition' : [
861                         ['command'],
862                         function() {
863                             try {
864                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
865                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.description')+'</description>';
866                                 xml += '<hbox><button value="good" label="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_good.label')+'"';
867                                 xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_good.accesskey')+'" name="fancy_submit"/>';
868                                 xml += '<button value="nogood" label="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_mediocre.label')+'"';
869                                 xml += '  accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_mediocre.accesskey')+'" name="fancy_submit"/></hbox>';
870                                 xml += '</vbox>';
871                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
872                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_cancel.label')+'"';
873                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
874                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
875                                 JSAN.use('util.window'); var win = new util.window();
876                                 var fancy_prompt_data = win.open(
877                                     urls.XUL_FANCY_PROMPT,
878                                     'fancy_prompt', 'chrome,resizable,modal',
879                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.set_notifs') }
880                                 );
881                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
882                                 var good = fancy_prompt_data.fancy_submit == 'good' ? get_db_true() : get_db_false();
883
884                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
885                                 var msg = '';
886                                 if(get_bool(good)) {
887                                     if(obj.retrieve_ids.length > 1) {
888                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_desire_mint_condition.enable_good.plural', [hold_list.join(', ')]);
889                                     } else {
890                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_desire_mint_condition.enable_good.singular', [hold_list.join(', ')]);
891                                     }
892                                 } else {
893                                     if(obj.retrieve_ids.length > 1) {
894                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_desire_mint_condition.disable_good.plural', [hold_list.join(', ')]);
895                                     } else {
896                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_desire_mint_condition.disable_good.singular', [hold_list.join(', ')]);
897                                     }
898                                 }
899
900                                 var r = obj.error.yns_alert(msg,
901                                         $("patronStrings").getString('staff.patron.holds.holds_desire_mint_condition.mod_holds_title'),
902                                         $("commonStrings").getString('common.yes'),
903                                         $("commonStrings").getString('common.no'),
904                                         null,
905                                         $("commonStrings").getString('common.check_to_confirm')
906                                 );
907                                 if (r == 0) {
908                                     circ.util.batch_hold_update(hold_list, { 'mint_condition' : good }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
909                                 }
910                             } catch(E) {
911                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
912                             }
913                         }
914                     ],
915
916
917                     'cmd_holds_suspend' : [
918                         ['command'],
919                         function() {
920                             try {
921                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
922                                 var r = obj.error.yns_alert(
923                                     obj.retrieve_ids.length > 1 ?
924                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.suspend.prompt.plural',[hold_list.join(', ')]) :
925                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.suspend.prompt',[hold_list.join(', ')]),
926                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds'),
927                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.yes'),
928                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.no'),
929                                     null,
930                                     document.getElementById('commonStrings').getString('common.confirm')
931                                 );
932                                 if (r == 0) {
933                                     var already_suspended = []; var filtered_hold_list = [];
934                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
935                                         var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
936                                         if ( get_bool( hold.frozen() ) ) {
937                                             already_suspended.push( hold.id() );
938                                             continue;
939                                         }
940                                         filtered_hold_list.push( hold.id() );
941                                     }
942                                     circ.util.batch_hold_update(filtered_hold_list, { 'frozen' : 't', 'thaw_date' : null }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { 
943                                         if (already_suspended.length == 1) {
944                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_suspended',[already_suspended[0]]) );
945                                         } else if (already_suspended.length > 1) {
946                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_suspended.plural',[already_suspended.join(', ')]) );
947                                         }
948                                         obj.clear_and_retrieve(true); 
949                                     } });
950                                 }
951                             } catch(E) {
952                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_suspended'),E);
953                             }
954                         }
955                     ],
956                     'cmd_holds_activate' : [
957                         ['command'],
958                         function() {
959                             try {
960                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
961                                 var r = obj.error.yns_alert(
962                                     obj.retrieve_ids.length > 1 ?
963                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.activate.prompt.plural',[hold_list.join(', ')]) :
964                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.activate.prompt',[hold_list.join(', ')]),
965                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds'),
966                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.yes'),
967                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.no'),
968                                     null,
969                                     document.getElementById('commonStrings').getString('common.confirm')
970                                 );
971                                 if (r == 0) {
972                                     var already_activated = []; var filtered_hold_list = [];
973                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
974                                         var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
975                                         if ( ! get_bool( hold.frozen() ) ) {
976                                             already_activated.push( hold.id() );
977                                             continue;
978                                         }
979                                         filtered_hold_list.push( hold.id() );
980                                     }
981                                     circ.util.batch_hold_update(filtered_hold_list, { 'frozen' : 'f', 'thaw_date' : null }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { 
982                                         if (already_activated.length == 1) {
983                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_activated',[already_activated[0]]) );
984                                         } else if (already_activated.length > 1) {
985                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_activated.plural',[already_activated.join(', ')]) );
986                                         }
987                                         obj.clear_and_retrieve(true); 
988                                     } });
989                                 }
990                             } catch(E) {
991                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_activated'),E);
992                             }
993                         }
994                     ],
995                     'cmd_holds_edit_thaw_date' : [
996                         ['command'],
997                         function() {
998                             try {
999                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1000                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.activation_date.prompt',[hold_list.join(', ')]);
1001                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.activation_date.prompt.plural',[hold_list.join(', ')]);
1002                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
1003                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
1004                                 var desc = document.getElementById('circStrings').getString('staff.circ.holds.activation_date.dialog.description');
1005
1006                                 JSAN.use('util.window'); var win = new util.window();
1007                                 var my_xulG = win.open( 
1008                                     urls.XUL_TIMESTAMP_DIALOG, 'edit_thaw_date', 'chrome,resizable,modal', 
1009                                     { 
1010                                         'title' : title, 
1011                                         'description' : desc, 
1012                                         'msg' : msg, 
1013                                         'allow_unset' : true,
1014                                         'disallow_future_dates' : false,
1015                                         'disallow_past_dates' : true,
1016                                         'disallow_today' : true,
1017                                         'default_time' : '00:00:00',
1018                                         'time_readonly' : false
1019                                     }
1020                                 );
1021                                 if (my_xulG.complete) {
1022                                     circ.util.batch_hold_update(
1023                                         hold_list, 
1024                                         { 'frozen' : 't', 'thaw_date' : my_xulG.timestamp }, 
1025                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
1026                                     );
1027                                 }
1028                             } catch(E) {
1029                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
1030                             }
1031                         }
1032                     ],
1033                     'cmd_holds_edit_expire_time' : [
1034                         ['command'],
1035                         function() {
1036                             try {
1037                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1038                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.expire_time.prompt',[hold_list.join(', ')]);
1039                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.expire_time.prompt.plural',[hold_list.join(', ')]);
1040                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
1041                                 var value = 'YYYY-MM-DD';
1042                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
1043                                 var desc = document.getElementById('circStrings').getString('staff.circ.holds.expire_time.dialog.description');
1044
1045                                 JSAN.use('util.window'); var win = new util.window();
1046                                 var my_xulG = win.open( 
1047                                     urls.XUL_TIMESTAMP_DIALOG, 'edit_expire_time', 'chrome,resizable,modal', 
1048                                     { 
1049                                         'title' : title, 
1050                                         'description' : desc, 
1051                                         'msg' : msg, 
1052                                         'allow_unset' : true,
1053                                         'disallow_future_dates' : false,
1054                                         'disallow_past_dates' : true,
1055                                         'disallow_today' : true,
1056                                         'default_time' : '00:00:00',
1057                                         'time_readonly' : false
1058                                     }
1059                                 );
1060                                 if (my_xulG.complete) {
1061                                     circ.util.batch_hold_update(
1062                                         hold_list, 
1063                                         { 'expire_time' : my_xulG.timestamp }, 
1064                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
1065                                     );
1066                                 }
1067                             } catch(E) {
1068                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
1069                             }
1070                         }
1071                     ],
1072                     'cmd_holds_edit_shelf_expire_time' : [
1073                         ['command'],
1074                         function() {
1075                             try {
1076                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1077                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.shelf_expire_time.prompt',[hold_list.join(', ')]);
1078                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.shelf_expire_time.prompt.plural',[hold_list.join(', ')]);
1079                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
1080                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
1081                                 var desc = document.getElementById('circStrings').getString('staff.circ.holds.shelf_expire_time.dialog.description');
1082
1083                                 JSAN.use('util.window'); var win = new util.window();
1084                                 var my_xulG = win.open( 
1085                                     urls.XUL_TIMESTAMP_DIALOG, 'edit_shelf_expire_time', 'chrome,resizable,modal', 
1086                                     { 
1087                                         'title' : title, 
1088                                         'description' : desc, 
1089                                         'msg' : msg, 
1090                                         'allow_unset' : false,
1091                                         'disallow_future_dates' : false,
1092                                         'disallow_past_dates' : false,
1093                                         'disallow_today' : false
1094                                     }
1095                                 );
1096                                 if (my_xulG.complete) {
1097                                     circ.util.batch_hold_update(
1098                                         hold_list, 
1099                                         { 'shelf_expire_time' : my_xulG.timestamp }, 
1100                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
1101                                     );
1102                                 }
1103                             } catch(E) {
1104                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
1105                             }
1106                         }
1107                     ],
1108                     'cmd_holds_edit_request_date' : [
1109                         ['command'],
1110                         function() {
1111                             try {
1112                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1113                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.request_date.prompt',[hold_list.join(', ')]);
1114                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.request_date.prompt.plural',[hold_list.join(', ')]);
1115                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
1116                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
1117                                 var desc = document.getElementById('circStrings').getString('staff.circ.holds.request_date.dialog.description');
1118
1119                                 JSAN.use('util.window'); var win = new util.window();
1120                                 var my_xulG = win.open( 
1121                                     urls.XUL_TIMESTAMP_DIALOG, 'edit_request_date', 'chrome,resizable,modal', 
1122                                     { 
1123                                         'title' : title, 
1124                                         'description' : desc, 
1125                                         'msg' : msg, 
1126                                         'allow_unset' : false,
1127                                         'disallow_future_dates' : true,
1128                                         'disallow_past_dates' : false,
1129                                         'disallow_today' : false
1130                                     }
1131                                 );
1132                                 if (my_xulG.complete) {
1133                                     circ.util.batch_hold_update(
1134                                         hold_list, 
1135                                         { 'request_time' : my_xulG.timestamp }, 
1136                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
1137                                     );
1138                                 }
1139                             } catch(E) {
1140                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
1141                             }
1142                         }
1143                     ],
1144                     'cmd_holds_retarget' : [
1145                         ['command'],
1146                         function() {
1147                             try {
1148                                 JSAN.use('util.functional');
1149
1150                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1151                                 var msg = '';
1152                                 if(obj.retrieve_ids.length > 1) {
1153                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_retarget.reset_hold_message.plural',[hold_list.join(', ')]);
1154                                 } else {
1155                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_retarget.reset_hold_message.singular',[hold_list.join(', ')]);
1156                                 }
1157                                 var r = obj.error.yns_alert(msg,
1158                                         $("patronStrings").getString('staff.patron.holds.holds_retarget.reset_hold_title'),
1159                                         $("commonStrings").getString('common.yes'),
1160                                         $("commonStrings").getString('common.no'),
1161                                         null,
1162                                         $("commonStrings").getString('common.check_to_confirm')
1163                                 );
1164                                 if (r == 0) {
1165                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
1166                                         var robj = obj.network.simple_request('FM_AHR_RESET',[ ses(), obj.retrieve_ids[i].id]);
1167                                         if (typeof robj.ilsevent != 'undefined') throw(robj);
1168                                     }
1169                                     obj.clear_and_retrieve();
1170                                 }
1171                             } catch(E) {
1172                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_retarget.holds_not_reset'),E);
1173                             }
1174
1175                         }
1176                     ],
1177
1178                     'cmd_holds_cancel' : [
1179                         ['command'],
1180                         function() {
1181                             try {
1182                                 JSAN.use('util.functional');
1183
1184                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
1185                                 var msg = '';
1186                                 if(obj.retrieve_ids.length > 1 ) {
1187                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_hold_message.plural', [hold_list.join(', ')]);
1188                                 } else {
1189                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_hold_message.singular', [hold_list.join(', ')]);
1190                                 }
1191
1192                                 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
1193                                 JSAN.use('util.window');
1194                                 var win = new util.window();
1195                                 var my_xulG = win.open(
1196                                     urls.XUL_HOLD_CANCEL,
1197                                     'hold_cancel',
1198                                     'chrome,resizable,modal',
1199                                     {}
1200                                 );
1201                                 /*var r = obj.error.yns_alert(msg,
1202                                         $("patronStrings").getString('staff.patron.holds.holds_cancel.cancel_hold_title'),
1203                                         $("commonStrings").getString('common.yes'),
1204                                         $("commonStrings").getString('common.no'),
1205                                         null,
1206                                         $("commonStrings").getString('common.check_to_confirm')
1207                                 );*/
1208
1209                                 if (my_xulG.proceed) { 
1210                                     var transits = [];
1211                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
1212                                         var transit = obj.holds_map[ obj.retrieve_ids[i].id ].hold.transit();
1213                                         if (transit && ! transit.dest_recv_time() ) {
1214                                             transits.push( obj.retrieve_ids[i].barcode );
1215                                         }
1216                                         var robj = obj.network.simple_request('FM_AHR_CANCEL',[ ses(), obj.retrieve_ids[i].id, my_xulG.cancel_reason, my_xulG.note]);
1217                                         if (typeof robj.ilsevent != 'undefined') throw(robj);
1218                                     }
1219                                     if (transits.length > 0) {
1220                                         var msg2 = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_for_barcodes', [transits.join(', ')]);
1221                                         var r2 = obj.error.yns_alert(msg2,
1222                                             $("patronStrings").getString('staff.patron.holds.holds_cancel.cancel_for_barcodes.title'),
1223                                             $("commonStrings").getString('common.yes'),
1224                                             $("commonStrings").getString('common.no'),
1225                                             null,
1226                                             $("commonStrings").getString('common.check_to_confirm'));
1227                                         if (r2 == 0) {
1228                                             try {
1229                                                 for (var i = 0; i < transits.length; i++) {
1230                                                     var robj = obj.network.simple_request('FM_ATC_VOID',[ ses(), { 'barcode' : transits[i] } ]);
1231                                                     if (typeof robj.ilsevent != 'undefined') {
1232                                                         switch(Number(robj.ilsevent)) {
1233                                                             case 1225 /* TRANSIT_ABORT_NOT_ALLOWED */ :
1234                                                                 alert(robj.desc);
1235                                                             break;
1236                                                             case 5000 /* PERM_FAILURE */ :
1237                                                             break;
1238                                                             default:
1239                                                                 throw(robj);
1240                                                             break;
1241                                                         }
1242                                                     }
1243                                                 }
1244                                             } catch(E) {
1245                                                obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_cancel.hold_transits_not_cancelled'),E);
1246                                             }
1247                                         }
1248                                     }
1249                                     obj.clear_and_retrieve();
1250                                 }
1251                             } catch(E) {
1252                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_cancel.hold_not_cancelled'),E);
1253                             }
1254                         }
1255                     ],
1256                     'cmd_holds_uncancel' : [
1257                         ['command'],
1258                         function() {
1259                             try {
1260                                 JSAN.use('util.functional');
1261                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
1262                                     var robj = obj.network.simple_request('FM_AHR_UNCANCEL',[ ses(), obj.retrieve_ids[i].id]);
1263                                     if (typeof robj.ilsevent != 'undefined') throw(robj);
1264                                 }
1265                                 obj.clear_and_retrieve();
1266                             } catch(E) {
1267                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_uncancel.hold_not_uncancelled'),E);
1268                             }
1269                         }
1270                     ],
1271
1272                     'cmd_retrieve_patron' : [
1273                         ['command'],
1274                         function() {
1275                             try {
1276                                 var seen = {};
1277                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
1278                                     var patron_id = obj.retrieve_ids[i].usr;
1279                                     if (seen[patron_id]) continue; seen[patron_id] = true;
1280                                     xulG.new_patron_tab(
1281                                         {},
1282                                         { 'id' : patron_id }
1283                                     );
1284                                 }
1285                             } catch(E) {
1286                                 obj.error.standard_unexpected_error_alert('',E);
1287                             }
1288                         }
1289                     ],
1290                     'cmd_show_catalog' : [
1291                         ['command'],
1292                         function() {
1293                             try {
1294                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
1295                                     var htarget = obj.retrieve_ids[i].target;
1296                                     var htype = obj.retrieve_ids[i].type;
1297                                     var opac_url;
1298                                     switch(htype) {
1299                                         case 'M' :
1300                                             opac_url = xulG.url_prefix( urls.opac_rresult_metarecord ) + htarget;
1301                                         break;
1302                                         case 'T' :
1303                                             opac_url = xulG.url_prefix( urls.opac_rdetail ) + htarget;
1304                                         break;
1305                                         case 'P' :
1306                                             opac_url = xulG.url_prefix( urls.opac_rdetail )
1307                                             + obj.hold_part_map[ obj.retrieve_ids[i].id ].record();
1308                                         break;
1309                                         case 'I' :
1310                                             opac_url = xulG.url_prefix( urls.opac_rdetail )
1311                                             + obj.hold_subscription_map[ obj.retrieve_ids[i].id ].record_entry();
1312                                         break;
1313                                         case 'V' :
1314                                             var my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative', [ htarget ]);
1315                                             opac_url = xulG.url_prefix( urls.opac_rdetail) + my_acn.record();
1316                                         break;
1317                                         case 'C' :
1318                                         case 'R' :
1319                                         case 'F' :
1320                                             var my_acp = obj.network.simple_request( 'FM_ACP_RETRIEVE', [ htarget ]);
1321                                             var my_acn;
1322                                             if (typeof my_acp.call_number() == 'object') {
1323                                                 my_acn = my.acp.call_number();
1324                                             } else {
1325                                                 my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative',
1326                                                     [ my_acp.call_number() ]);
1327                                             }
1328                                             opac_url = xulG.url_prefix( urls.opac_rdetail) + my_acn.record();
1329                                         break;
1330                                         default:
1331                                             obj.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.holds.show_catalog.unknown_htype', [htype]), obj.retrieve_ids[i]);
1332                                             continue;
1333                                         break;
1334                                     }
1335                                     var content_params = {
1336                                         'session' : ses(),
1337                                         'authtime' : ses('authtime'),
1338                                         'opac_url' : opac_url
1339                                     };
1340                                     xulG.new_tab(
1341                                         xulG.url_prefix(urls.XUL_OPAC_WRAPPER),
1342                                         {'tab_name': htype == 'M' ? 'Catalog' : $("patronStrings").getString('staff.patron.holds.show_catalog.retrieving_title') },
1343                                         content_params
1344                                     );
1345                                 }
1346                             } catch(E) {
1347                                 obj.error.standard_unexpected_error_alert('',E);
1348                             }
1349                         }
1350                     ],
1351                     'cmd_holds_title_transfer' : [
1352                         ['command'],
1353                         function() {
1354                             try {
1355                                 var hids = [];
1356                                 var unique_targets = [];
1357                                 var seen_target = {};
1358                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
1359                                     var hid = obj.retrieve_ids[i].id;
1360                                     var htarget = obj.retrieve_ids[i].id;
1361                                     var htype = obj.retrieve_ids[i].type;
1362                                     switch(htype) {
1363                                         case 'M' :
1364                                             continue; // not supported
1365                                         break;
1366                                         case 'T' :
1367                                             hids.push( hid );
1368                                             if (! seen_target[htarget]) {
1369                                                 unique_targets.push( htarget );
1370                                                 seen_target[htarget] = 1;
1371                                             }
1372                                         break;
1373                                         case 'V' :
1374                                             continue; // not supported
1375                                         break;
1376                                         case 'C' :
1377                                             continue; // not supported
1378                                         break;
1379                                         default:
1380                                             continue; // not supported
1381                                         break;
1382                                     }
1383                                 }
1384                                 JSAN.use('cat.util');
1385                                 cat.util.transfer_specific_title_holds(hids,unique_targets);
1386                                 obj.clear_and_retrieve();
1387                             } catch(E) {
1388                                 obj.error.standard_unexpected_error_alert('',E);
1389                             }
1390                         }
1391                     ],
1392
1393                     'fetch_more' : [
1394                         ['command'],
1395                         function() {
1396                             obj.pull_from_shelf_interface.current.offset += obj.pull_from_shelf_interface.current.limit;
1397                             obj.retrieve(true);
1398                         }
1399                     ],
1400                     'lib_filter_checkbox' : [
1401                         ['command'],
1402                         function(ev) {
1403                             var x_lib_type_menu = document.getElementById('lib_type_menu');
1404                             if (x_lib_type_menu) x_lib_type_menu.disabled = ! ev.target.checked;
1405                             if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = ! ev.target.checked;
1406                             obj.clear_and_retrieve();
1407                             ev.target.setAttribute('checked',ev.target.checked);
1408                         }
1409                     ],
1410                     'cmd_view_expired_onshelf_holds' : [
1411                         ['command'],
1412                         function(ev) {
1413                             var x = document.getElementById('expired_checkbox'); // can't trust ev.explicitOriginalTarget, sometimes gives a "button"
1414                             obj.expired = x.checked;
1415                             obj.controller.view.cmd_clear_expired_onshelf_holds.setAttribute('disabled', !obj.expired);
1416                             obj.clear_and_retrieve();
1417                         }
1418                     ],
1419                     'cmd_clear_expired_onshelf_holds' : [
1420                         ['command'],
1421                         function(ev) {
1422                             obj.cmd_clear_expired_onshelf_holds();
1423                         }
1424                     ],
1425                     'cmd_search_opac' : [
1426                         ['command'],
1427                         function(ev) {
1428                             try {
1429                                 var content_params = {
1430                                     'show_nav_buttons' : false,
1431                                     'show_print_button' : true,
1432                                     'passthru_content_params' : {
1433                                         'authtoken' : ses(),
1434                                         'authtime' : ses('authtime'),
1435                                         'window_open' : function(a,b,c) {
1436                                             try {
1437                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
1438                                                 return window.open(a,b,c);
1439                                             } catch(E) {
1440                                                 obj.error.standard_unexpected_error_alert('window_open',E);
1441                                             }
1442                                         },
1443                                         'opac_hold_placed' : function(hold) {
1444                                             try {
1445                                                 obj.list.append(
1446                                                     {
1447                                                         'row' : {
1448                                                             'my' : {
1449                                                                 'hold_id' : typeof hold == 'object' ? hold.id() : hold
1450                                                             }
1451                                                         }
1452                                                     }
1453                                                 );
1454                                                 if (window.xulG && typeof window.xulG.on_list_change == 'function') {
1455                                                     window.xulG.on_list_change(); 
1456                                                 }
1457                                             } catch(E) {
1458                                                 obj.error.standard_unexpected_error_alert('holds.js, opac_hold_placed(): ',E);
1459                                             }
1460                                         },
1461                                         'get_barcode' : xulG.get_barcode,
1462                                         'get_barcode_and_settings' : xulG.get_barcode_and_settings,
1463                                         'patron_barcode' : obj.patron_barcode
1464                                     },
1465                                     'url_prefix' : xulG.url_prefix,
1466                                     'url' : xulG.url_prefix(urls.browser)
1467                                 };
1468                                 xulG.display_window.g.patron.right_deck.set_iframe( urls.XUL_REMOTE_BROWSER + '?patron_hold=1', {}, content_params);
1469                             } catch(E) {
1470                                 obj.error.sdump('D_ERROR','cmd_search_opac: ' + E);
1471                             }
1472
1473                         }
1474                     ]
1475                 }
1476             }
1477         );
1478
1479         obj.determine_hold_interface_type();
1480         var x_fetch_more = document.getElementById('fetch_more');
1481         var x_lib_type_menu = document.getElementById('lib_type_menu');
1482         var x_lib_menu_placeholder = document.getElementById('lib_menu_placeholder');
1483         var x_lib_filter_checkbox = document.getElementById('lib_filter_checkbox');
1484         var x_show_cancelled_deck = document.getElementById('show_cancelled_deck');
1485         var x_clear_shelf_widgets = document.getElementById('clear_shelf_widgets');
1486         var x_expired_checkbox = document.getElementById('expired_checkbox');
1487         var x_print_full_pull_list = document.getElementById('print_full_btn');
1488         var x_print_full_pull_list_alt = document.getElementById('print_alt_btn');
1489         switch(obj.hold_interface_type) {
1490             case 'shelf':
1491                 obj.render_lib_menus({'pickup_lib':true});
1492                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.checked = true;
1493                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
1494                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
1495                 if (x_clear_shelf_widgets) x_clear_shelf_widgets.hidden = false;
1496                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = true;
1497             break;
1498             case 'pull' :
1499                 if (x_fetch_more) x_fetch_more.hidden = false;
1500                 if (x_print_full_pull_list) x_print_full_pull_list.hidden = false;
1501                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = false;
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             break;
1505             case 'record' :
1506                 obj.render_lib_menus({'pickup_lib':true,'request_lib':true});
1507                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.hidden = false;
1508                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
1509                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = true;
1510                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
1511             break;
1512             default:
1513                 if (obj.controller.view.cmd_search_opac) obj.controller.view.cmd_search_opac.setAttribute('hidden', false);
1514                 if (x_fetch_more) x_fetch_more.hidden = true;
1515                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
1516                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
1517                 if (x_show_cancelled_deck) x_show_cancelled_deck.hidden = false;
1518                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = true;
1519             break;
1520         }
1521         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
1522             function() {
1523                 if (x_lib_filter_checkbox) if (!x_lib_filter_checkbox.checked) {
1524                     if (x_lib_type_menu) x_lib_type_menu.disabled = true;
1525                     if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = true;
1526                 }
1527                 obj.controller.render();
1528                 obj.retrieve(true);
1529
1530                 obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
1531                 obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
1532                 obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
1533                 obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
1534                 obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','true');
1535                 obj.controller.view.cmd_holds_activate.setAttribute('disabled','true');
1536                 obj.controller.view.cmd_holds_suspend.setAttribute('disabled','true');
1537                 obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
1538                 obj.controller.view.cmd_alt_view.setAttribute('disabled','true');
1539                 obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
1540                 obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
1541                 obj.controller.view.cmd_holds_uncancel.setAttribute('disabled','true');
1542                 obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
1543             }, 0
1544         );
1545
1546         $('cmd_alt_view').setAttribute('disabled','true');
1547         xulG.when_done = function() {
1548             $('cmd_alt_view').setAttribute('ready','true');
1549             if ($('cmd_alt_view').getAttribute('rendering_rows') != 'true') {
1550                 $('cmd_alt_view').setAttribute('disabled','false');
1551             }
1552             dump('hold details UI ready\n');
1553         }
1554         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
1555         JSAN.use('util.browser');
1556         obj.browser = new util.browser();
1557         obj.browser.init(
1558             {
1559                 'url' : urls.XUL_HOLD_DETAILS,
1560                 'push_xulG' : true,
1561                 'alt_print' : false,
1562                 'browser_id' : 'hold_detail_frame',
1563                 'passthru_content_params' : xulG
1564             }
1565         );
1566
1567     },
1568
1569     'determine_hold_interface_type' : function() {
1570         var obj = this;
1571         if (obj.patron_id) { /*************************************************** PATRON ******************************/
1572             obj.hold_interface_type = 'patron';
1573         } else if (obj.docid) { /*************************************************** RECORD ******************************/
1574             obj.hold_interface_type = 'record';
1575         } else if (obj.pull) { /*************************************************** PULL ******************************/
1576             obj.hold_interface_type = 'pull';
1577         } else if (obj.shelf) { /*************************************************** HOLD SHELF ******************************/
1578             obj.hold_interface_type = 'shelf';
1579         } else { /*************************************************** PULL ******************************/
1580             obj.hold_interface_type = 'pull';
1581         }
1582     },
1583
1584     'clear_and_retrieve' : function() {
1585         try {
1586             this.list.clear();
1587             this.pull_from_shelf_interface.current.offset = this.pull_from_shelf_interface._default.offset;
1588             this.retrieve();
1589             if (window.xulG && typeof window.xulG.on_list_change == 'function') {
1590                 window.xulG.on_list_change(); 
1591             }
1592         } catch(E) {
1593             this.error.standard_unexpected_error_alert('holds.js, clear_and_retrieve(): ',E);
1594         }
1595     },
1596
1597     'retrieve' : function() {
1598         var obj = this; var holds = [];
1599         if (window.xulG && window.xulG.holds) {
1600             holds = window.xulG.holds;
1601         } else {
1602             var method; var params = [ ses() ];
1603             switch(obj.hold_interface_type) {
1604                 case 'patron' :
1605                     if (document.getElementById('show_cancelled_deck').selectedIndex == 0) {
1606                         method = 'FM_AHR_ID_LIST_RETRIEVE_VIA_AU.authoritative';
1607                     } else {
1608                         method = 'FM_AHR_CANCELLED_ID_LIST_RETRIEVE_VIA_AU.authoritative';
1609                     }
1610                     params.push( obj.patron_id );
1611                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','true');
1612                 break;
1613                 case 'record' :
1614                     method = 'FM_AHR_RETRIEVE_ALL_VIA_BRE';
1615                     params.push( obj.docid );
1616                     var x_lib_filter = document.getElementById('lib_filter_checkbox');
1617                     var x_lib_type_menu = document.getElementById('lib_type_menu');
1618                     if (x_lib_filter) {
1619                         if (x_lib_filter.checked) {
1620                             if (x_lib_type_menu && obj.controller.view.lib_menu) {
1621                                 var x = {};
1622                                 x[ x_lib_type_menu.value ] = obj.controller.view.lib_menu.value;
1623                                 params.push( x );
1624                             }
1625                         }
1626                     }
1627                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1628                 break;
1629                 case 'shelf' :
1630                     if (obj.expired) {
1631                         method = 'FM_AHR_ID_LIST_EXPIRED_ONSHELF_RETRIEVE';
1632                     } else {
1633                         method = 'FM_AHR_ID_LIST_ONSHELF_RETRIEVE';
1634                     }
1635                     params.push( obj.filter_lib || obj.data.list.au[0].ws_ou() );
1636                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1637                 break;
1638                 case 'pull' :
1639                 default:
1640                     method = 'FM_AHR_ID_LIST_PULL_LIST';
1641                     params.push( obj.pull_from_shelf_interface.current.limit ); params.push( obj.pull_from_shelf_interface.current.offset );
1642                     var x = document.getElementById('hold_count');
1643                     if (x) {
1644                         obj.network.simple_request('FM_AHR_PULL_LIST_COUNT',[ses()],function(req) {
1645                             var count = req.getResultObject();
1646                             if (typeof count.ilsevent == 'undefined' && count != null) {
1647                                 x.setAttribute('value', document.getElementById('patronStrings').getFormattedString(
1648                                     'staff.patron.holds.total_count',
1649                                     [ count ]
1650                                 ));
1651                                 x.hidden = false;
1652                             }
1653                         });
1654                     }
1655                 break;
1656             }
1657             var robj = obj.network.simple_request( method, params );
1658             if (robj != null && typeof robj.ilsevent != 'undefined') throw(robj);
1659             if (method == 'FM_AHR_RETRIEVE_ALL_VIA_BRE') {
1660                 holds = [];
1661                 if (robj != null) {
1662                     holds = holds.concat( robj.copy_holds );
1663                     holds = holds.concat( robj.recall_holds );
1664                     holds = holds.concat( robj.force_holds );
1665                     holds = holds.concat( robj.volume_holds );
1666                     holds = holds.concat( robj.title_holds );
1667                     holds = holds.concat( robj.part_holds );
1668                     holds = holds.concat( robj.issuance_holds );
1669                     holds = holds.concat( robj.metarecord_holds );
1670                     holds = holds.sort();
1671                 }
1672             } else {
1673                 if (robj == null ) {
1674                     holds = [];
1675                 } else {
1676                     if (typeof robj.length == 'undefined') {
1677                         holds = [ robj ];
1678                     } else {
1679                         holds = robj;
1680                     }
1681                 }
1682             }
1683             holds.reverse();
1684             //alert('method = ' + method + ' params = ' + js2JSON(params));
1685         }
1686
1687         var x_fetch_more = document.getElementById('fetch_more');
1688         if (holds.length == 0) {
1689             if (x_fetch_more) x_fetch_more.disabled = true;
1690         } else {
1691             if (x_fetch_more) x_fetch_more.disabled = false;
1692             obj.render(holds);
1693         }
1694
1695     },
1696
1697     'render' : function(holds) {
1698         try {
1699             var obj = this;
1700
1701             function list_append(hold_id) {
1702                 obj.list.append(
1703                     {
1704                         'row' : {
1705                             'my' : {
1706                                 'hold_id' : hold_id,
1707                                 'post_clear_shelf_action' : obj.post_clear_shelf_hold_action_map[ hold_id ]
1708                             }
1709                         },
1710                         'to_bottom' : true
1711                     }
1712                 );
1713             }
1714
1715             function gen_list_append(hold) {
1716                 return function() {
1717                     if (typeof obj.controller.view.lib_menu == 'undefined') {
1718                         list_append(typeof hold == 'object' ? hold.id() : hold);
1719                     } else {
1720                         list_append(typeof hold == 'object' ? hold.id() : hold);
1721                     }
1722                 };
1723             }
1724
1725             //obj.list.clear();
1726
1727             JSAN.use('util.exec'); var exec = new util.exec(2);
1728             var rows = [];
1729             for (var i in holds) {
1730                 rows.push( gen_list_append(holds[i]) );
1731             }
1732             exec.chain( rows );
1733
1734         } catch(E) {
1735             this.error.standard_unexpected_error_alert('holds.js, render():',E);
1736         }
1737     },
1738
1739     'render_lib_menus' : function(types) {
1740         try {
1741             var obj = this;
1742             JSAN.use('util.widgets'); JSAN.use('util.functional'); JSAN.use('util.fm_utils');
1743
1744             var x = document.getElementById('lib_type_menu');
1745             if (types) {
1746                 var nodes = x.firstChild.childNodes;
1747                 for (var i = 0; i < nodes.length; i++) nodes[i].hidden = true;
1748                 for (var i in types) document.getElementById(i).hidden = false;
1749             }
1750             x.setAttribute('oncommand','g.holds.clear_and_retrieve()');
1751
1752             x = document.getElementById('lib_menu_placeholder');
1753             util.widgets.remove_children( x );
1754
1755             JSAN.use('util.file');
1756             var file = new util.file('offline_ou_list');
1757             if (file._file.exists()) {
1758                 var list_data = file.get_object(); file.close();
1759                 var ml = util.widgets.make_menulist( list_data[0], obj.data.list.au[0].ws_ou() );
1760                 ml.setAttribute('id','lib_menu');
1761                 x.appendChild( ml );
1762                 ml.addEventListener(
1763                     'command',
1764                     function(ev) {
1765                         obj.filter_lib = ev.target.value;
1766                         obj.clear_and_retrieve();
1767                     },
1768                     false
1769                 );
1770                 obj.controller.view.lib_menu = ml;
1771             } else {
1772                 throw($("patronStrings").getString('staff.patron.holds.lib_menus.missing_library_list'));
1773             }
1774
1775         } catch(E) {
1776             this.error.standard_unexpected_error_alert('rendering lib menu',E);
1777         }
1778     },
1779
1780     'cmd_clear_expired_onshelf_holds' : function() {
1781         var obj = this;
1782         try {
1783             // Disable anything such as filters that can have us accidentally
1784             // lose these non-repeatable results.  Well, now that they're cached
1785             // it's less of an issue.
1786             if ($('lib_filter_checkbox')) {
1787                 $('lib_filter_checkbox').checked = false;
1788             }
1789             if ($('lib_type_menu')) {
1790                 $('lib_type_menu').disabled = true;
1791             }
1792             if ($('lib_menu_placeholder')) {
1793                 $('lib_menu_placeholder').firstChild.disabled = true;
1794             }
1795             obj.controller.view.cmd_view_expired_onshelf_holds.setAttribute(
1796                 'disabled', 'true');
1797             obj.controller.view.cmd_clear_expired_onshelf_holds.setAttribute(
1798                 'disabled', 'true');
1799
1800             // I could put this with the "retrieval" methods, but since it has
1801             // side effects, seems cleaner to invoke it here
1802             var robj = obj.network.simple_request(
1803                 'CLEAR_HOLD_SHELF',
1804                 [
1805                     ses(),
1806                     obj.filter_lib || obj.data.list.au[0].ws_ou()
1807                 ]
1808             );
1809             if (typeof robj.ilsevent != 'undefined') { throw(robj); }
1810             if (typeof robj.cache_key == 'undefined') { throw(robj); }
1811
1812             var cache_key = robj.cache_key;
1813
1814             // id's in xulG.holds will prevent the normal retrieval method from
1815             // firing.  Let's put our affected hold.id's in here:
1816             xulG.holds = [];
1817
1818             // Start the progress meter
1819             $('progress').value = 0;
1820             $('progress').hidden = false;
1821
1822             // Fetch the affected holds
1823             fieldmapper.standardRequest(
1824                 [ 'open-ils.circ', 'open-ils.circ.hold.clear_shelf.get_cache' ],
1825                 {
1826                     'async' : true,
1827                     'params' : [ ses(), cache_key ],
1828                     'onresponse' : function(r) {
1829                         dojo.forEach(
1830                             openils.Util.readResponse(r),
1831                             function(resp) {
1832                                 if (resp.maximum) {
1833                                     $('progress').value = Number(resp.progress)
1834                                         * 100/resp.maximum;
1835                                     return;
1836                                 }
1837                                 obj.post_clear_shelf_hold_action_map[
1838                                     resp.hold_details.id
1839                                 ] = resp.action;
1840                                 xulG.holds.push( resp.hold_details.id );
1841                             }
1842                         )
1843                     },
1844                     'oncomplete' : function() {
1845                         obj.clear_and_retrieve();
1846                         $('progress').hidden = true;
1847                     }
1848                 }
1849             );
1850
1851         } catch(E) {
1852             if (E.ilsevent == 5000 /* PERM_FAILURE */ ) {
1853                 return; /* handled by network.js */
1854             }
1855             obj.error.standard_unexpected_error_alert(
1856                 'Error in holds.js, cmd_clear_expired_onshelf_holds', E);
1857         }
1858     }
1859 }
1860
1861 dump('exiting patron.holds.js\n');