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