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