]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/xul/staff_client/server/patron/holds.js
Vandelay-based record matching and import for Acquisitions
[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 use_url = urls.browser;
1430                                 use_url += use_url.match(/\?/) ? "&" : "?";
1431                                 use_url += "patron_barcode=" + obj.patron_barcode;
1432                                 var content_params = {
1433                                     'show_nav_buttons' : false,
1434                                     'show_print_button' : true,
1435                                     'passthru_content_params' : {
1436                                         'authtoken' : ses(),
1437                                         'authtime' : ses('authtime'),
1438                                         'window_open' : function(a,b,c) {
1439                                             try {
1440                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
1441                                                 return window.open(a,b,c);
1442                                             } catch(E) {
1443                                                 obj.error.standard_unexpected_error_alert('window_open',E);
1444                                             }
1445                                         },
1446                                         'opac_hold_placed' : function(hold) {
1447                                             try {
1448                                                 obj.list.append(
1449                                                     {
1450                                                         'row' : {
1451                                                             'my' : {
1452                                                                 'hold_id' : typeof hold == 'object' ? hold.id() : hold
1453                                                             }
1454                                                         }
1455                                                     }
1456                                                 );
1457                                                 if (window.xulG && typeof window.xulG.on_list_change == 'function') {
1458                                                     window.xulG.on_list_change(); 
1459                                                 }
1460                                             } catch(E) {
1461                                                 obj.error.standard_unexpected_error_alert('holds.js, opac_hold_placed(): ',E);
1462                                             }
1463                                         },
1464                                         'patron_barcode' : obj.patron_barcode
1465                                     },
1466                                     'url_prefix' : xulG.url_prefix,
1467                                     'url' : xulG.url_prefix(use_url)
1468                                 };
1469                                 xulG.display_window.g.patron.right_deck.set_iframe( urls.XUL_REMOTE_BROWSER + '?patron_hold=1', {}, content_params);
1470                             } catch(E) {
1471                                 obj.error.sdump('D_ERROR','cmd_search_opac: ' + E);
1472                             }
1473
1474                         }
1475                     ]
1476                 }
1477             }
1478         );
1479
1480         obj.determine_hold_interface_type();
1481         var x_fetch_more = document.getElementById('fetch_more');
1482         var x_lib_type_menu = document.getElementById('lib_type_menu');
1483         var x_lib_menu_placeholder = document.getElementById('lib_menu_placeholder');
1484         var x_lib_filter_checkbox = document.getElementById('lib_filter_checkbox');
1485         var x_show_cancelled_deck = document.getElementById('show_cancelled_deck');
1486         var x_clear_shelf_widgets = document.getElementById('clear_shelf_widgets');
1487         var x_expired_checkbox = document.getElementById('expired_checkbox');
1488         var x_print_full_pull_list = document.getElementById('print_full_btn');
1489         var x_print_full_pull_list_alt = document.getElementById('print_alt_btn');
1490         switch(obj.hold_interface_type) {
1491             case 'shelf':
1492                 obj.render_lib_menus({'pickup_lib':true});
1493                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.checked = true;
1494                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
1495                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
1496                 if (x_clear_shelf_widgets) x_clear_shelf_widgets.hidden = false;
1497                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = true;
1498             break;
1499             case 'pull' :
1500                 if (x_fetch_more) x_fetch_more.hidden = false;
1501                 if (x_print_full_pull_list) x_print_full_pull_list.hidden = false;
1502                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = false;
1503                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
1504                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
1505             break;
1506             case 'record' :
1507                 obj.render_lib_menus({'pickup_lib':true,'request_lib':true});
1508                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.hidden = false;
1509                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
1510                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = true;
1511                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
1512             break;
1513             default:
1514                 if (obj.controller.view.cmd_search_opac) obj.controller.view.cmd_search_opac.setAttribute('hidden', false);
1515                 if (x_fetch_more) x_fetch_more.hidden = true;
1516                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
1517                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
1518                 if (x_show_cancelled_deck) x_show_cancelled_deck.hidden = false;
1519                 if (x_print_full_pull_list_alt) x_print_full_pull_list_alt.hidden = true;
1520             break;
1521         }
1522         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
1523             function() {
1524                 if (x_lib_filter_checkbox) if (!x_lib_filter_checkbox.checked) {
1525                     if (x_lib_type_menu) x_lib_type_menu.disabled = true;
1526                     if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = true;
1527                 }
1528                 obj.controller.render();
1529                 obj.retrieve(true);
1530
1531                 obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
1532                 obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
1533                 obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
1534                 obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
1535                 obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','true');
1536                 obj.controller.view.cmd_holds_activate.setAttribute('disabled','true');
1537                 obj.controller.view.cmd_holds_suspend.setAttribute('disabled','true');
1538                 obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
1539                 obj.controller.view.cmd_alt_view.setAttribute('disabled','true');
1540                 obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
1541                 obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
1542                 obj.controller.view.cmd_holds_uncancel.setAttribute('disabled','true');
1543                 obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
1544             }, 0
1545         );
1546
1547         $('cmd_alt_view').setAttribute('disabled','true');
1548         xulG.when_done = function() {
1549             $('cmd_alt_view').setAttribute('ready','true');
1550             if ($('cmd_alt_view').getAttribute('rendering_rows') != 'true') {
1551                 $('cmd_alt_view').setAttribute('disabled','false');
1552             }
1553             dump('hold details UI ready\n');
1554         }
1555         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
1556         JSAN.use('util.browser');
1557         obj.browser = new util.browser();
1558         obj.browser.init(
1559             {
1560                 'url' : urls.XUL_HOLD_DETAILS,
1561                 'push_xulG' : true,
1562                 'alt_print' : false,
1563                 'browser_id' : 'hold_detail_frame',
1564                 'passthru_content_params' : xulG
1565             }
1566         );
1567
1568     },
1569
1570     'determine_hold_interface_type' : function() {
1571         var obj = this;
1572         if (obj.patron_id) { /*************************************************** PATRON ******************************/
1573             obj.hold_interface_type = 'patron';
1574         } else if (obj.docid) { /*************************************************** RECORD ******************************/
1575             obj.hold_interface_type = 'record';
1576         } else if (obj.pull) { /*************************************************** PULL ******************************/
1577             obj.hold_interface_type = 'pull';
1578         } else if (obj.shelf) { /*************************************************** HOLD SHELF ******************************/
1579             obj.hold_interface_type = 'shelf';
1580         } else { /*************************************************** PULL ******************************/
1581             obj.hold_interface_type = 'pull';
1582         }
1583     },
1584
1585     'clear_and_retrieve' : function() {
1586         try {
1587             this.list.clear();
1588             this.pull_from_shelf_interface.current.offset = this.pull_from_shelf_interface._default.offset;
1589             this.retrieve();
1590             if (window.xulG && typeof window.xulG.on_list_change == 'function') {
1591                 window.xulG.on_list_change(); 
1592             }
1593         } catch(E) {
1594             this.error.standard_unexpected_error_alert('holds.js, clear_and_retrieve(): ',E);
1595         }
1596     },
1597
1598     'retrieve' : function() {
1599         var obj = this; var holds = [];
1600         if (window.xulG && window.xulG.holds) {
1601             holds = window.xulG.holds;
1602         } else {
1603             var method; var params = [ ses() ];
1604             switch(obj.hold_interface_type) {
1605                 case 'patron' :
1606                     if (document.getElementById('show_cancelled_deck').selectedIndex == 0) {
1607                         method = 'FM_AHR_ID_LIST_RETRIEVE_VIA_AU.authoritative';
1608                     } else {
1609                         method = 'FM_AHR_CANCELLED_ID_LIST_RETRIEVE_VIA_AU.authoritative';
1610                     }
1611                     params.push( obj.patron_id );
1612                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','true');
1613                 break;
1614                 case 'record' :
1615                     method = 'FM_AHR_RETRIEVE_ALL_VIA_BRE';
1616                     params.push( obj.docid );
1617                     var x_lib_filter = document.getElementById('lib_filter_checkbox');
1618                     var x_lib_type_menu = document.getElementById('lib_type_menu');
1619                     if (x_lib_filter) {
1620                         if (x_lib_filter.checked) {
1621                             if (x_lib_type_menu && obj.controller.view.lib_menu) {
1622                                 var x = {};
1623                                 x[ x_lib_type_menu.value ] = obj.controller.view.lib_menu.value;
1624                                 params.push( x );
1625                             }
1626                         }
1627                     }
1628                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1629                 break;
1630                 case 'shelf' :
1631                     if (obj.expired) {
1632                         method = 'FM_AHR_ID_LIST_EXPIRED_ONSHELF_RETRIEVE';
1633                     } else {
1634                         method = 'FM_AHR_ID_LIST_ONSHELF_RETRIEVE';
1635                     }
1636                     params.push( obj.filter_lib || obj.data.list.au[0].ws_ou() );
1637                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1638                 break;
1639                 case 'pull' :
1640                 default:
1641                     method = 'FM_AHR_ID_LIST_PULL_LIST';
1642                     params.push( obj.pull_from_shelf_interface.current.limit ); params.push( obj.pull_from_shelf_interface.current.offset );
1643                     var x = document.getElementById('hold_count');
1644                     if (x) {
1645                         obj.network.simple_request('FM_AHR_PULL_LIST_COUNT',[ses()],function(req) {
1646                             var count = req.getResultObject();
1647                             if (typeof count.ilsevent == 'undefined' && count != null) {
1648                                 x.setAttribute('value', document.getElementById('patronStrings').getFormattedString(
1649                                     'staff.patron.holds.total_count',
1650                                     [ count ]
1651                                 ));
1652                                 x.hidden = false;
1653                             }
1654                         });
1655                     }
1656                 break;
1657             }
1658             var robj = obj.network.simple_request( method, params );
1659             if (robj != null && typeof robj.ilsevent != 'undefined') throw(robj);
1660             if (method == 'FM_AHR_RETRIEVE_ALL_VIA_BRE') {
1661                 holds = [];
1662                 if (robj != null) {
1663                     holds = holds.concat( robj.copy_holds );
1664                     holds = holds.concat( robj.recall_holds );
1665                     holds = holds.concat( robj.force_holds );
1666                     holds = holds.concat( robj.volume_holds );
1667                     holds = holds.concat( robj.title_holds );
1668                     holds = holds.concat( robj.part_holds );
1669                     holds = holds.concat( robj.issuance_holds );
1670                     holds = holds.concat( robj.metarecord_holds );
1671                     holds = holds.sort();
1672                 }
1673             } else {
1674                 if (robj == null ) {
1675                     holds = [];
1676                 } else {
1677                     if (typeof robj.length == 'undefined') {
1678                         holds = [ robj ];
1679                     } else {
1680                         holds = robj;
1681                     }
1682                 }
1683             }
1684             holds.reverse();
1685             //alert('method = ' + method + ' params = ' + js2JSON(params));
1686         }
1687
1688         var x_fetch_more = document.getElementById('fetch_more');
1689         if (holds.length == 0) {
1690             if (x_fetch_more) x_fetch_more.disabled = true;
1691         } else {
1692             if (x_fetch_more) x_fetch_more.disabled = false;
1693             obj.render(holds);
1694         }
1695
1696     },
1697
1698     'render' : function(holds) {
1699         try {
1700             var obj = this;
1701
1702             function list_append(hold_id) {
1703                 obj.list.append(
1704                     {
1705                         'row' : {
1706                             'my' : {
1707                                 'hold_id' : hold_id,
1708                                 'post_clear_shelf_action' : obj.post_clear_shelf_hold_action_map[ hold_id ]
1709                             }
1710                         },
1711                         'to_bottom' : true
1712                     }
1713                 );
1714             }
1715
1716             function gen_list_append(hold) {
1717                 return function() {
1718                     if (typeof obj.controller.view.lib_menu == 'undefined') {
1719                         list_append(typeof hold == 'object' ? hold.id() : hold);
1720                     } else {
1721                         list_append(typeof hold == 'object' ? hold.id() : hold);
1722                     }
1723                 };
1724             }
1725
1726             //obj.list.clear();
1727
1728             JSAN.use('util.exec'); var exec = new util.exec(2);
1729             var rows = [];
1730             for (var i in holds) {
1731                 rows.push( gen_list_append(holds[i]) );
1732             }
1733             exec.chain( rows );
1734
1735         } catch(E) {
1736             this.error.standard_unexpected_error_alert('holds.js, render():',E);
1737         }
1738     },
1739
1740     'render_lib_menus' : function(types) {
1741         try {
1742             var obj = this;
1743             JSAN.use('util.widgets'); JSAN.use('util.functional'); JSAN.use('util.fm_utils');
1744
1745             var x = document.getElementById('lib_type_menu');
1746             if (types) {
1747                 var nodes = x.firstChild.childNodes;
1748                 for (var i = 0; i < nodes.length; i++) nodes[i].hidden = true;
1749                 for (var i in types) document.getElementById(i).hidden = false;
1750             }
1751             x.setAttribute('oncommand','g.holds.clear_and_retrieve()');
1752
1753             x = document.getElementById('lib_menu_placeholder');
1754             util.widgets.remove_children( x );
1755
1756             JSAN.use('util.file');
1757             var file = new util.file('offline_ou_list');
1758             if (file._file.exists()) {
1759                 var list_data = file.get_object(); file.close();
1760                 var ml = util.widgets.make_menulist( list_data[0], obj.data.list.au[0].ws_ou() );
1761                 ml.setAttribute('id','lib_menu');
1762                 x.appendChild( ml );
1763                 ml.addEventListener(
1764                     'command',
1765                     function(ev) {
1766                         obj.filter_lib = ev.target.value;
1767                         obj.clear_and_retrieve();
1768                     },
1769                     false
1770                 );
1771                 obj.controller.view.lib_menu = ml;
1772             } else {
1773                 throw($("patronStrings").getString('staff.patron.holds.lib_menus.missing_library_list'));
1774             }
1775
1776         } catch(E) {
1777             this.error.standard_unexpected_error_alert('rendering lib menu',E);
1778         }
1779     },
1780
1781     'cmd_clear_expired_onshelf_holds' : function() {
1782         var obj = this;
1783         try {
1784             // Disable anything such as filters that can have us accidentally
1785             // lose these non-repeatable results.  Well, now that they're cached
1786             // it's less of an issue.
1787             if ($('lib_filter_checkbox')) {
1788                 $('lib_filter_checkbox').checked = false;
1789             }
1790             if ($('lib_type_menu')) {
1791                 $('lib_type_menu').disabled = true;
1792             }
1793             if ($('lib_menu_placeholder')) {
1794                 $('lib_menu_placeholder').firstChild.disabled = true;
1795             }
1796             obj.controller.view.cmd_view_expired_onshelf_holds.setAttribute(
1797                 'disabled', 'true');
1798             obj.controller.view.cmd_clear_expired_onshelf_holds.setAttribute(
1799                 'disabled', 'true');
1800
1801             // I could put this with the "retrieval" methods, but since it has
1802             // side effects, seems cleaner to invoke it here
1803             var robj = obj.network.simple_request(
1804                 'CLEAR_HOLD_SHELF',
1805                 [
1806                     ses(),
1807                     obj.filter_lib || obj.data.list.au[0].ws_ou()
1808                 ]
1809             );
1810             if (typeof robj.ilsevent != 'undefined') { throw(robj); }
1811             if (typeof robj.cache_key == 'undefined') { throw(robj); }
1812
1813             var cache_key = robj.cache_key;
1814
1815             // id's in xulG.holds will prevent the normal retrieval method from
1816             // firing.  Let's put our affected hold.id's in here:
1817             xulG.holds = [];
1818
1819             // Start the progress meter
1820             $('progress').value = 0;
1821             $('progress').hidden = false;
1822
1823             // Fetch the affected holds
1824             fieldmapper.standardRequest(
1825                 [ 'open-ils.circ', 'open-ils.circ.hold.clear_shelf.get_cache' ],
1826                 {
1827                     'async' : true,
1828                     'params' : [ ses(), cache_key ],
1829                     'onresponse' : function(r) {
1830                         dojo.forEach(
1831                             openils.Util.readResponse(r),
1832                             function(resp) {
1833                                 if (resp.maximum) {
1834                                     $('progress').value = Number(resp.progress)
1835                                         * 100/resp.maximum;
1836                                     return;
1837                                 }
1838                                 obj.post_clear_shelf_hold_action_map[
1839                                     resp.hold_details.id
1840                                 ] = resp.action;
1841                                 xulG.holds.push( resp.hold_details.id );
1842                             }
1843                         )
1844                     },
1845                     'oncomplete' : function() {
1846                         obj.clear_and_retrieve();
1847                         $('progress').hidden = true;
1848                     }
1849                 }
1850             );
1851
1852         } catch(E) {
1853             if (E.ilsevent == 5000 /* PERM_FAILURE */ ) {
1854                 return; /* handled by network.js */
1855             }
1856             obj.error.standard_unexpected_error_alert(
1857                 'Error in holds.js, cmd_clear_expired_onshelf_holds', E);
1858         }
1859     }
1860 }
1861
1862 dump('exiting patron.holds.js\n');