]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/patron/holds.js
Make use of streaming batch hold update method in staff client and tie it to a progre...
[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' : 50, 'offset' : 0 },
19         'current' : { 'limit' : 50, 'offset' : 0 }
20     },
21
22     'filter_lib' : null,
23
24     'retrieve_ids' : [],
25
26     'holds_map' : {},
27
28     'flatten_copy' : function(hold) {
29         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); }
30         return hold;
31     },
32
33     'init' : function( params ) {
34
35         var obj = this;
36
37         obj.patron_id = params['patron_id'];
38         obj.patron_barcode = params['patron_barcode'];
39         obj.docid = params['docid'];
40         obj.shelf = params['shelf'];
41         obj.tree_id = params['tree_id'];
42
43         var progressmeter = document.getElementById('progress');
44
45         JSAN.use('circ.util');
46         var columns = circ.util.hold_columns(
47             {
48                 'title' : { 'hidden' : false, 'flex' : '3' },
49                 'request_time' : { 'hidden' : false },
50                 'pickup_lib_shortname' : { 'hidden' : false },
51                 'hold_type' : { 'hidden' : false },
52                 'current_copy' : { 'hidden' : false },
53                 'capture_time' : { 'hidden' : false },
54                 'notify_time' : { 'hidden' : false },
55                 'notify_count' : { 'hidden' : false }
56             }
57         );
58
59         JSAN.use('util.list'); obj.list = new util.list( obj.tree_id || 'holds_list');
60         obj.list.init(
61             {
62                 'columns' : columns,
63                 'map_row_to_columns' : circ.util.std_map_row_to_columns(),
64                 'retrieve_row' : function(params) {
65                     var row = params.row;
66                     try {
67                         obj.network.simple_request('FM_AHR_BLOB_RETRIEVE.authoritative', [ ses(), row.my.hold_id ],
68                             function(blob_req) {
69                                 try {
70                                     var blob = blob_req.getResultObject();
71                                     if (typeof blob.ilsevent != 'undefined') throw(blob);
72                                     row.my.ahr = blob.hold;
73                                     row.my.status = blob.status;
74                                                                         row.my.ahr.status( blob.status );
75                                     row.my.acp = blob.copy;
76                                     row.my.acn = blob.volume;
77                                     row.my.mvr = blob.mvr;
78                                     row.my.patron_family_name = blob.patron_last;
79                                     row.my.patron_first_given_name = blob.patron_first;
80                                     row.my.patron_barcode = blob.patron_barcode;
81                                                                         row.my.total_holds = blob.total_holds;
82                                                                         row.my.queue_position = blob.queue_position;
83                                                                         row.my.potential_copies = blob.potential_copies;
84                                                                         row.my.estimated_wait = blob.estimated_wait;
85                                                                         row.my.ahrn_count = blob.hold.notes().length;
86
87                                     var copy_id = row.my.ahr.current_copy();
88                                     if (typeof copy_id == 'object') {
89                                         if (copy_id == null) {
90                                             if (typeof row.my.acp == 'object' && row.my.acp != null) copy_id = row.my.acp.id();
91                                         } else {
92                                             copy_id = copy_id.id();
93                                         }
94                                     } else {
95                                         copy_id = row.my.acp.id();
96                                     }
97
98                                     obj.holds_map[ row.my.ahr.id() ] = blob;
99                                     params.row_node.setAttribute('retrieve_id',
100                                         js2JSON({
101                                             'copy_id':copy_id,
102                                                                                         'barcode':row.my.acp ? row.my.acp.barcode() : null,
103                                             'id':row.my.ahr.id(),
104                                             'type':row.my.ahr.hold_type(),
105                                             'target':row.my.ahr.target(),
106                                             'usr':row.my.ahr.usr()
107                                         })
108                                     );
109                                     if (typeof params.on_retrieve == 'function') { params.on_retrieve(row); }
110
111                                 } catch(E) {
112                                     obj.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.holds.init.hold_num_error', [row.my.hold_id]), E);
113                                 }
114                             }
115                         );
116                     } catch(E) {
117                         obj.error.sdump('D_ERROR','retrieve_row: ' + E );
118                     }
119                     return row;
120                 },
121                 'on_select' : function(ev) {
122                     JSAN.use('util.functional');
123                     var sel = obj.list.retrieve_selection();
124                     obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
125                     obj.retrieve_ids = util.functional.map_list(
126                         sel,
127                         function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
128                     );
129                     if (obj.retrieve_ids.length > 0) {
130                         obj.controller.view.sel_mark_items_damaged.setAttribute('disabled','false');
131                         obj.controller.view.sel_mark_items_missing.setAttribute('disabled','false');
132                         obj.controller.view.sel_copy_details.setAttribute('disabled','false');
133                         obj.controller.view.sel_patron.setAttribute('disabled','false');
134                         obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','false');
135                         obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','false');
136                         obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','false');
137                         obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','false');
138                         obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','false');
139                         obj.controller.view.cmd_holds_edit_expire_time.setAttribute('disabled','false');
140                         obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','false');
141                         obj.controller.view.cmd_holds_activate.setAttribute('disabled','false');
142                         obj.controller.view.cmd_holds_suspend.setAttribute('disabled','false');
143                         obj.controller.view.cmd_alt_view.setAttribute('disabled','false');
144                         obj.controller.view.cmd_holds_retarget.setAttribute('disabled','false');
145                         obj.controller.view.cmd_holds_cancel.setAttribute('disabled','false');
146                         obj.controller.view.cmd_show_catalog.setAttribute('disabled','false');
147                     } else {
148                         obj.controller.view.sel_mark_items_damaged.setAttribute('disabled','true');
149                         obj.controller.view.sel_mark_items_missing.setAttribute('disabled','true');
150                         obj.controller.view.sel_copy_details.setAttribute('disabled','true');
151                         obj.controller.view.sel_patron.setAttribute('disabled','true');
152                         obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
153                         obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
154                         obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
155                         obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
156                         obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
157                         obj.controller.view.cmd_holds_edit_expire_time.setAttribute('disabled','true');
158                         obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','true');
159                         obj.controller.view.cmd_holds_activate.setAttribute('disabled','true');
160                         obj.controller.view.cmd_holds_suspend.setAttribute('disabled','true');
161                         obj.controller.view.cmd_alt_view.setAttribute('disabled','true');
162                         obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
163                         obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
164                         obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
165                     }
166                 }
167             }
168         );
169
170         JSAN.use('util.controller'); obj.controller = new util.controller();
171         obj.controller.init(
172             {
173                 'control_map' : {
174                     'save_columns' : [ [ 'command' ], function() { obj.list.save_columns(); } ],
175                     'sel_clip' : [
176                         ['command'],
177                         function() { obj.list.clipboard(); }
178                     ],
179                     'cmd_broken' : [
180                         ['command'],
181                         function() { alert($("commonStrings").getString('common.unimplemented')); }
182                     ],
183                     'sel_patron' : [
184                         ['command'],
185                         function() {
186                             JSAN.use('circ.util');
187                             circ.util.show_last_few_circs(obj.retrieve_ids);
188                         }
189                     ],
190                     'alt_view_btn' : [
191                         ['render'],
192                         function(e) {
193                             e.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.label'));
194                             e.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.accesskey'));
195                         }
196                     ],
197                     'cmd_alt_view' : [
198                         ['command'],
199                         function(ev) {
200                             try {
201                                 var n = obj.controller.view.alt_view_btn;
202                                 if (n.getAttribute('toggle') == '1') {
203                                     document.getElementById('deck').selectedIndex = 0;
204                                     n.setAttribute('toggle','0');
205                                     n.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.label'));
206                                     n.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.accesskey'));
207                                 } else {
208                                     document.getElementById('deck').selectedIndex = 1;
209                                     n.setAttribute('toggle','1');
210                                     n.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.list_view.label'));
211                                     n.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.list_view.accesskey'));
212                                     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
213                                     if (obj.retrieve_ids.length == 0) return;
214                                     var f = obj.browser.get_content();
215                                     xulG.ahr_id = obj.retrieve_ids[0].id;
216                                     xulG.blob = obj.holds_map[ xulG.ahr_id ];
217                                     xulG.patron_rendered_elsewhere = (obj.hold_interface_type == 'patron');
218                                     xulG.bib_rendered_elsewhere = (obj.hold_interface_type == 'record');
219                                     f.xulG = xulG;
220                                     f.fetch_and_render_all();
221                                 }
222                             } catch(E) {
223                                 alert('Error in holds.js, cmd_alt_view handler: ' + E);
224                             }
225                         },
226                     ],
227                     'sel_mark_items_damaged' : [
228                         ['command'],
229                         function() {
230                             JSAN.use('cat.util'); JSAN.use('util.functional');
231                             cat.util.mark_item_damaged( util.functional.map_list( obj.retrieve_ids, function(o) { return o.copy_id; } ) );
232                         }
233                     ],
234                     'sel_mark_items_missing' : [
235                         ['command'],
236                         function() {
237                             JSAN.use('cat.util'); JSAN.use('util.functional');
238                             cat.util.mark_item_missing( util.functional.map_list( obj.retrieve_ids, function(o) { return o.copy_id; } ) );
239                         }
240                     ],
241                     'sel_copy_details' : [
242                         ['command'],
243                         function() {
244                             JSAN.use('circ.util');
245                             for (var i = 0; i < obj.retrieve_ids.length; i++) {
246                                 if (obj.retrieve_ids[i].copy_id) circ.util.show_copy_details( obj.retrieve_ids[i].copy_id );
247                             }
248                         }
249                     ],
250
251                     'cmd_holds_print' : [
252                         ['command'],
253                         function() {
254                             try {
255                                 JSAN.use('patron.util');
256                                 var params = {
257                                     'patron' : patron.util.retrieve_au_via_id(ses(),obj.patron_id),
258                                     'template' : 'holds'
259                                 };
260                                 obj.list.print(params);
261                             } catch(E) {
262                                 obj.error.standard_unexpected_error_alert('print 1',E);
263                             }
264                         }
265                     ],
266                     'cmd_csv_to_clipboard' : [ ['command'], function() { obj.list.dump_csv_to_clipboard(); } ],
267                     'cmd_csv_to_printer' : [ ['command'], function() { obj.list.dump_csv_to_printer(); } ],
268                     'cmd_csv_to_file' : [ ['command'], function() { obj.list.dump_csv_to_file( { 'defaultFileName' : 'holds.txt' } ); } ],
269
270                     'cmd_holds_edit_selection_depth' : [
271                         ['command'],
272                         function() {
273                             try {
274                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
275                                 var ws_type = obj.data.hash.aout[ obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ].ou_type() ];
276                                 var list = util.functional.map_list(
277                                     util.functional.filter_list(
278                                         obj.data.list.aout,
279                                         function(o) {
280                                             if (o.depth() > ws_type.depth()) return false;
281                                             if (o.depth() < ws_type.depth()) return true;
282                                             return (o.id() == ws_type.id());
283                                         }
284                                     ),
285                                     function(o) {
286                                         return [
287                                             o.opac_label(),
288                                             o.id(),
289                                             false,
290                                             ( o.depth() * 2),
291                                         ];
292                                     }
293                                 );
294                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
295                                 ml.setAttribute('id','selection');
296                                 ml.setAttribute('name','fancy_data');
297                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
298                                 xml += '<description>' + $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.choose_hold_range') + '</description>';
299                                 xml += util.widgets.serialize_node(ml);
300                                 xml += '</vbox>';
301                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
302                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.done.label') +'"';
303                                 bot_xml += 'accesskey="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.done.accesskey') +'" name="fancy_submit"/>';
304                                 bot_xml += '<button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.cancel.label') +'"';
305                                 bot_xml += 'accesskey="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.cancel.accesskey') +'" name="fancy_cancel"/></hbox>';
306                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
307                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
308                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
309                                 JSAN.use('util.window'); var win = new util.window();
310                                 var fancy_prompt_data = win.open(
311                                     urls.XUL_FANCY_PROMPT,
312                                     //+ '?xml_in_stash=temp_mid'
313                                     //+ '&bottom_xml_in_stash=temp_bot'
314                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
315                                     'fancy_prompt', 'chrome,resizable,modal',
316                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.choose_library') }
317                                 );
318                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
319                                 var selection = fancy_prompt_data.selection;
320
321                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
322                                 var msg = '';
323                                 if(obj.retrieve_ids.length > 1) {
324                                     msg = $("patronStrings").getformattedString('staff.patron.holds.holds_edit_selection_depth.modify_holds_message.plural', [hold_list.join(', '), obj.data.hash.aout[selection].opac_label()])
325                                 } else {
326                                     msg = $("patronStrings").getformattedString('staff.patron.holds.holds_edit_selection_depth.modify_holds_message.singular', [hold_list.join(', '), obj.data.hash.aout[selection].opac_label()])
327                                 }
328
329                                 var r = obj.error.yns_alert(msg,
330                                         $("patronStrings").getString('staff.patron.holds.holds_edit_selection_depth.modify_holds_title'),
331                                         $("commonStrings").getString('common.yes'),
332                                         $("commonStrings").getString('common.no'),
333                                         null,
334                                         $("commonStrings").getString('common.check_to_confirm')
335                                 );
336                                 if (r == 0) {
337                                     circ.util.batch_hold_update(hold_list, { 'selection_depth' : obj.data.hash.aout[selection].depth() }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
338                                 }
339                             } catch(E) {
340                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
341                             }
342                         }
343                     ],
344
345                     'cmd_holds_edit_pickup_lib' : [
346                         ['command'],
347                         function() {
348                             try {
349                                 JSAN.use('util.widgets'); JSAN.use('util.functional');
350
351                                 var deny_edit_because_of_transit = false;
352                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
353                                     var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
354                                     if (hold.status() == 3 /* In-Transit */) deny_edit_because_of_transit = true;
355                                 }
356                                 if (deny_edit_because_of_transit) {
357                                     alert(document.getElementById('circStrings').getString('staff.circ.holds.error.may_not_edit_pickup_lib_for_hold_intransit'));
358                                     return;
359                                 }
360
361                                 var list = util.functional.map_list(
362                                     obj.data.list.aou,
363                                     function(o) {
364                                         var sname = o.shortname(); for (i = sname.length; i < 20; i++) sname += ' ';
365                                         return [
366                                             o.name() ? sname + ' ' + o.name() : o.shortname(),
367                                             o.id(),
368                                             ( obj.data.hash.aout[ o.ou_type() ].can_have_users() == 0),
369                                             ( obj.data.hash.aout[ o.ou_type() ].depth() * 2),
370                                         ];
371                                     }
372                                 );
373                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
374                                 ml.setAttribute('id','lib');
375                                 ml.setAttribute('name','fancy_data');
376                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
377                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.new_pickup_lib.description')+'</description>';
378                                 xml += util.widgets.serialize_node(ml);
379                                 xml += '</vbox>';
380                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
381                                 bot_xml += '<spacer flex="1"/><button label="'+ $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.done.label') +'"';
382                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.done.accesskey')+'" name="fancy_submit"/>';
383                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.cancel.label')+'"';
384                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
385                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
386                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
387                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
388                                 JSAN.use('util.window'); var win = new util.window();
389                                 var fancy_prompt_data = win.open(
390                                     urls.XUL_FANCY_PROMPT,
391                                     //+ '?xml_in_stash=temp_mid'
392                                     //+ '&bottom_xml_in_stash=temp_bot'
393                                     //+ '&title=' + window.escape('Choose a Pick Up Library'),
394                                     'fancy_prompt', 'chrome,resizable,modal',
395                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.choose_lib') }
396                                 );
397                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
398                                 var pickup_lib = fancy_prompt_data.lib;
399
400                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
401                                 var msg = '';
402                                 if(obj.retrieve_ids.length > 1) {
403                                     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()]);
404                                 } else {
405                                     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()]);
406                                 }
407                                 var r = obj.error.yns_alert(msg,
408                                         $("patronStrings").getString('staff.patron.holds.holds_edit_pickup_lib.change_pickup_lib_title'),
409                                         $("commonStrings").getString('common.yes'),
410                                         $("commonStrings").getString('common.no'),
411                                         null,
412                                         $("commonStrings").getString('common.check_to_confirm')
413                                 );
414                                 if (r == 0) {
415                                     circ.util.batch_hold_update(hold_list, { 'pickup_lib' : pickup_lib }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
416                                 }
417                             } catch(E) {
418                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
419                             }
420                         }
421                     ],
422                     'cmd_holds_edit_phone_notify' : [
423                         ['command'],
424                         function() {
425                             try {
426                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
427                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.new_phone_number')+'</description>';
428                                 xml += '<textbox id="phone" name="fancy_data" context="clipboard"/>';
429                                 xml += '</vbox>';
430                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
431                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_done.label')+'"';
432                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_done.accesskey')+'" name="fancy_submit"/>';
433                                 bot_xml += '<button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_cancel.label')+'"';
434                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
435                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
436                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
437                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
438                                 JSAN.use('util.window'); var win = new util.window();
439                                 var fancy_prompt_data = win.open(
440                                     urls.XUL_FANCY_PROMPT,
441                                     //+ '?xml_in_stash=temp_mid'
442                                     //+ '&bottom_xml_in_stash=temp_bot'
443                                     //+ '&title=' + window.escape('Choose a Hold Notification Phone Number')
444                                     //+ '&focus=phone',
445                                     'fancy_prompt', 'chrome,resizable,modal',
446                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.choose_phone_number'), 'focus' : 'phone' }
447                                 );
448                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
449                                 var phone = fancy_prompt_data.phone;
450
451                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
452                                 var msg = '';
453                                 if(obj.retrieve_ids.length > 1) {
454                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_phone_notify.confirm_phone_number_change.plural',[hold_list.join(', '), phone]);
455                                 } else {
456                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_phone_notify.confirm_phone_number_change.singular',[hold_list.join(', '), phone]);
457                                 }
458                                 var r = obj.error.yns_alert(msg,
459                                         $("patronStrings").getString('staff.patron.holds.holds_edit_phone_notify.modifying_holds_title'),
460                                         $("commonStrings").getString('common.yes'),
461                                         $("commonStrings").getString('common.no'),
462                                         null,
463                                         $("commonStrings").getString('common.check_to_confirm')
464                                 );
465                                 if (r == 0) {
466                                     circ.util.batch_hold_update(hold_list, { 'phone_notify' : phone }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
467                                 }
468                             } catch(E) {
469                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
470                             }
471                         }
472                     ],
473                     'cmd_holds_edit_email_notify' : [
474                         ['command'],
475                         function() {
476                             try {
477                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
478                                 xml += '<description>'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.description')+'</description>';
479                                 xml += '<hbox><button value="email" label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_email.label')+'"';
480                                 xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_email.accesskey')+'" name="fancy_submit"/>';
481                                 xml += '<button value="noemail" label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_no_email.label')+'"';
482                                 xml += '  accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_no_email.accesskey')+'" name="fancy_submit"/></hbox>';
483                                 xml += '</vbox>';
484                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
485                                 bot_xml += '<spacer flex="1"/><button label="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_cancel.label')+'"';
486                                 bot_xml += ' accesskey="'+$("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.btn_cancel.accesskey')+'" name="fancy_cancel"/></hbox>';
487                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
488                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
489                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
490                                 JSAN.use('util.window'); var win = new util.window();
491                                 var fancy_prompt_data = win.open(
492                                     urls.XUL_FANCY_PROMPT,
493                                     //+ '?xml_in_stash=temp_mid'
494                                     //+ '&bottom_xml_in_stash=temp_bot'
495                                     //+ '&title=' + window.escape('Set Email Notification for Holds'),
496                                     'fancy_prompt', 'chrome,resizable,modal',
497                                     { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : $("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.set_notifs') }
498                                 );
499                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
500                                 var email = fancy_prompt_data.fancy_submit == 'email' ? get_db_true() : get_db_false();
501
502                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
503                                 var msg = '';
504                                 if(get_bool(email)) {
505                                     if(obj.retrieve_ids.length > 1) {
506                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.enable_email.plural', [hold_list.join(', ')]);
507                                     } else {
508                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.enable_email.singular', [hold_list.join(', ')]);
509                                     }
510                                 } else {
511                                     if(obj.retrieve_ids.length > 1) {
512                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.disable_email.plural', [hold_list.join(', ')]);
513                                     } else {
514                                         msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_edit_email_notify.disable_email.singular', [hold_list.join(', ')]);
515                                     }
516                                 }
517
518                                 var r = obj.error.yns_alert(msg,
519                                         $("patronStrings").getString('staff.patron.holds.holds_edit_email_notify.mod_holds_title'),
520                                         $("commonStrings").getString('common.yes'),
521                                         $("commonStrings").getString('common.no'),
522                                         null,
523                                         $("commonStrings").getString('common.check_to_confirm')
524                                 );
525                                 if (r == 0) {
526                                     circ.util.batch_hold_update(hold_list, { 'email_notify' : email }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } });
527                                 }
528                             } catch(E) {
529                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_not_modified'),E);
530                             }
531                         }
532                     ],
533                     'cmd_holds_suspend' : [
534                         ['command'],
535                         function() {
536                             try {
537                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
538                                 var r = obj.error.yns_alert(
539                                     obj.retrieve_ids.length > 1 ?
540                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.suspend.prompt.plural',[hold_list.join(', ')]) :
541                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.suspend.prompt',[hold_list.join(', ')]),
542                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds'),
543                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.yes'),
544                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.no'),
545                                     null,
546                                     document.getElementById('commonStrings').getString('common.confirm')
547                                 );
548                                 if (r == 0) {
549                                     var already_suspended = []; var filtered_hold_list = [];
550                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
551                                         var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
552                                         if ( get_bool( hold.frozen() ) ) {
553                                             already_suspended.push( hold.id() );
554                                             continue;
555                                         }
556                                         filtered_hold_list.push( hold.id() );
557                                     }
558                                     circ.util.batch_hold_update(filtered_hold_list, { 'frozen' : 't', 'thaw_date' : null }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { 
559                                         if (already_suspended.length == 1) {
560                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_suspended',[already_suspended[0]]) );
561                                         } else if (already_suspended.length > 1) {
562                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_suspended.plural',[already_suspended.join(', ')]) );
563                                         }
564                                         obj.clear_and_retrieve(true); 
565                                     } });
566                                 }
567                             } catch(E) {
568                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_suspended'),E);
569                             }
570                         }
571                     ],
572                     'cmd_holds_activate' : [
573                         ['command'],
574                         function() {
575                             try {
576                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
577                                 var r = obj.error.yns_alert(
578                                     obj.retrieve_ids.length > 1 ?
579                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.activate.prompt.plural',[hold_list.join(', ')]) :
580                                     document.getElementById('circStrings').getFormattedString('staff.circ.holds.activate.prompt',[hold_list.join(', ')]),
581                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds'),
582                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.yes'),
583                                     document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds.no'),
584                                     null,
585                                     document.getElementById('commonStrings').getString('common.confirm')
586                                 );
587                                 if (r == 0) {
588                                     var already_activated = []; var filtered_hold_list = [];
589                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
590                                         var hold = obj.holds_map[ obj.retrieve_ids[i].id ].hold;
591                                         if ( ! get_bool( hold.frozen() ) ) {
592                                             already_activated.push( hold.id() );
593                                             continue;
594                                         }
595                                         filtered_hold_list.push( hold.id() );
596                                     }
597                                     circ.util.batch_hold_update(filtered_hold_list, { 'frozen' : 'f', 'thaw_date' : null }, { 'progressmeter' : progressmeter, 'oncomplete' :  function() { 
598                                         if (already_activated.length == 1) {
599                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_activated',[already_activated[0]]) );
600                                         } else if (already_activated.length > 1) {
601                                             alert( document.getElementById('circStrings').getFormattedString('staff.circ.holds.already_activated.plural',[already_activated.join(', ')]) );
602                                         }
603                                         obj.clear_and_retrieve(true); 
604                                     } });
605                                 }
606                             } catch(E) {
607                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_activated'),E);
608                             }
609                         }
610                     ],
611                     'cmd_holds_edit_thaw_date' : [
612                         ['command'],
613                         function() {
614                             try {
615                                 JSAN.use('util.date');
616                                 function check_date(value) {
617                                     try {
618                                         if (! util.date.check('YYYY-MM-DD',value) ) { throw(document.getElementById('circStrings').getString('staff.circ.holds.activation_date.invalid_date')); }
619                                         if (util.date.check_past('YYYY-MM-DD',value) || util.date.formatted_date(new Date(),'%F') == value ) {
620                                             throw(document.getElementById('circStrings').getString('staff.circ.holds.activation_date.too_early.error'));
621                                         }
622                                         return true;
623                                     } catch(E) {
624                                         alert(E);
625                                         return false;
626                                     }
627                                 }
628
629                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
630                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.activation_date.prompt',[hold_list.join(', ')]);
631                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.activation_date.prompt',[hold_list.join(', ')]);
632                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
633                                 var value = 'YYYY-MM-DD';
634                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
635                                 var thaw_date; var invalid = true;
636                                 while(invalid) {
637                                     thaw_date = window.prompt(msg,value,title);
638                                     if (thaw_date) {
639                                         invalid = ! check_date(thaw_date);
640                                     } else {
641                                         invalid = false;
642                                     }
643                                 }
644                                 if (thaw_date || thaw_date == '') {
645                                     circ.util.batch_hold_update(
646                                         hold_list, 
647                                         { 'frozen' : 't', 'thaw_date' : thaw_date == '' ? null : util.date.formatted_date(thaw_date + ' 00:00:00','%{iso8601}') }, 
648                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
649                                     );
650                                 }
651                             } catch(E) {
652                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
653                             }
654                         }
655                     ],
656                     'cmd_holds_edit_expire_time' : [
657                         ['command'],
658                         function() {
659                             try {
660                                 JSAN.use('util.date');
661                                 function check_date(value) {
662                                     try {
663                                         if (! util.date.check('YYYY-MM-DD',value) ) { throw(document.getElementById('circStrings').getString('staff.circ.holds.expire_time.invalid_date')); }
664                                         if (util.date.check_past('YYYY-MM-DD',value) || util.date.formatted_date(new Date(),'%F') == value ) {
665                                             throw(document.getElementById('circStrings').getString('staff.circ.holds.expire_time.too_early.error'));
666                                         }
667                                         return true;
668                                     } catch(E) {
669                                         alert(E);
670                                         return false;
671                                     }
672                                 }
673
674                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
675                                 var msg_singular = document.getElementById('circStrings').getFormattedString('staff.circ.holds.expire_time.prompt',[hold_list.join(', ')]);
676                                 var msg_plural = document.getElementById('circStrings').getFormattedString('staff.circ.holds.expire_time.prompt',[hold_list.join(', ')]);
677                                 var msg = obj.retrieve_ids.length > 1 ? msg_plural : msg_singular;
678                                 var value = 'YYYY-MM-DD';
679                                 var title = document.getElementById('circStrings').getString('staff.circ.holds.modifying_holds');
680                                 var expire_time; var invalid = true;
681                                 while(invalid) {
682                                     expire_time = window.prompt(msg,value,title);
683                                     if (expire_time) {
684                                         invalid = ! check_date(expire_time);
685                                     } else {
686                                         invalid = false;
687                                     }
688                                 }
689                                 if (expire_time || expire_time == '') {
690                                     circ.util.batch_hold_update(
691                                         hold_list, 
692                                         { 'expire_time' : expire_time == '' ? null : util.date.formatted_date(expire_time + ' 00:00:00','%{iso8601}') }, 
693                                         { 'progressmeter' : progressmeter, 'oncomplete' :  function() { obj.clear_and_retrieve(true); } }
694                                     );
695                                 }
696                             } catch(E) {
697                                 obj.error.standard_unexpected_error_alert(document.getElementById('circStrings').getString('staff.circ.holds.unexpected_error.not_likely_modified'),E);
698                             }
699                         }
700                     ],
701
702
703
704                     'cmd_holds_retarget' : [
705                         ['command'],
706                         function() {
707                             try {
708                                 JSAN.use('util.functional');
709
710                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
711                                 var msg = '';
712                                 if(obj.retrieve_ids.length > 1) {
713                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_retarget.reset_hold_message.plural',[hold_list.join(', ')]);
714                                 } else {
715                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_retarget.reset_hold_message.singular',[hold_list.join(', ')]);
716                                 }
717                                 var r = obj.error.yns_alert(msg,
718                                         $("patronStrings").getString('staff.patron.holds.holds_retarget.reset_hold_title'),
719                                         $("commonStrings").getString('common.yes'),
720                                         $("commonStrings").getString('common.no'),
721                                         null,
722                                         $("commonStrings").getString('common.check_to_confirm')
723                                 );
724                                 if (r == 0) {
725                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
726                                         var robj = obj.network.simple_request('FM_AHR_RESET',[ ses(), obj.retrieve_ids[i].id]);
727                                         if (typeof robj.ilsevent != 'undefined') throw(robj);
728                                     }
729                                     obj.clear_and_retrieve();
730                                 }
731                             } catch(E) {
732                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_retarget.holds_not_reset'),E);
733                             }
734
735                         }
736                     ],
737
738                     'cmd_holds_cancel' : [
739                         ['command'],
740                         function() {
741                             try {
742                                 JSAN.use('util.functional');
743
744                                 var hold_list = util.functional.map_list(obj.retrieve_ids, function(o){return o.id;});
745                                 var msg = '';
746                                 if(obj.retrieve_ids.length > 1 ) {
747                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_hold_message.plural', [hold_list.join(', ')]);
748                                 } else {
749                                     msg = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_hold_message.singular', [hold_list.join(', ')]);
750                                 }
751
752                                 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
753                                 JSAN.use('util.window');
754                                 var win = new util.window();
755                                 var my_xulG = win.open(
756                                     urls.XUL_HOLD_CANCEL,
757                                     'hold_cancel',
758                                     'chrome,resizable,modal',
759                                     {}
760                                 );
761                                 /*var r = obj.error.yns_alert(msg,
762                                         $("patronStrings").getString('staff.patron.holds.holds_cancel.cancel_hold_title'),
763                                         $("commonStrings").getString('common.yes'),
764                                         $("commonStrings").getString('common.no'),
765                                         null,
766                                         $("commonStrings").getString('common.check_to_confirm')
767                                 );*/
768
769                                 if (my_xulG.proceed) { 
770                                     var transits = [];
771                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
772                                         if (obj.holds_map[ obj.retrieve_ids[i].id ].hold.transit()) {
773                                             transits.push( obj.retrieve_ids[i].barcode );
774                                         }
775                                         var robj = obj.network.simple_request('FM_AHR_CANCEL',[ ses(), obj.retrieve_ids[i].id, my_xulG.cancel_reason, my_xulG.note]);
776                                         if (typeof robj.ilsevent != 'undefined') throw(robj);
777                                     }
778                                     if (transits.length > 0) {
779                                         var msg2 = $("patronStrings").getFormattedString('staff.patron.holds.holds_cancel.cancel_for_barcodes', [transits.join(', ')]);
780                                         var r2 = obj.error.yns_alert(msg2,
781                                             $("patronStrings").getString('staff.patron.holds.holds_cancel.cancel_for_barcodes.title'),
782                                             $("commonStrings").getString('common.yes'),
783                                             $("commonStrings").getString('common.no'),
784                                             null,
785                                             $("commonStrings").getString('common.check_to_confirm'));
786                                         if (r2 == 0) {
787                                             try {
788                                                 for (var i = 0; i < transits.length; i++) {
789                                                     var robj = obj.network.simple_request('FM_ATC_VOID',[ ses(), { 'barcode' : transits[i] } ]);
790                                                     if (typeof robj.ilsevent != 'undefined') {
791                                                         switch(Number(robj.ilsevent)) {
792                                                             case 1225 /* TRANSIT_ABORT_NOT_ALLOWED */ :
793                                                                 alert(robj.desc);
794                                                             break;
795                                                             case 5000 /* PERM_FAILURE */ :
796                                                             break;
797                                                             default:
798                                                                 throw(robj);
799                                                             break;
800                                                         }
801                                                     }
802                                                 }
803                                             } catch(E) {
804                                                obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_cancel.hold_transits_not_cancelled'),E);
805                                             }
806                                         }
807                                     }
808                                     obj.clear_and_retrieve();
809                                 }
810                             } catch(E) {
811                                 obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.holds.holds_cancel.hold_not_cancelled'),E);
812                             }
813                         }
814                     ],
815                     'cmd_retrieve_patron' : [
816                         ['command'],
817                         function() {
818                             try {
819                                 var seen = {};
820                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
821                                     var patron_id = obj.retrieve_ids[i].usr;
822                                     if (seen[patron_id]) continue; seen[patron_id] = true;
823                                     xulG.new_patron_tab(
824                                         {},
825                                         { 'id' : patron_id }
826                                     );
827                                 }
828                             } catch(E) {
829                                 obj.error.standard_unexpected_error_alert('',E);
830                             }
831                         }
832                     ],
833                     'cmd_show_catalog' : [
834                         ['command'],
835                         function() {
836                             try {
837                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
838                                     var htarget = obj.retrieve_ids[i].target;
839                                     var htype = obj.retrieve_ids[i].type;
840                                     var opac_url;
841                                     switch(htype) {
842                                         case 'M' :
843                                             opac_url = xulG.url_prefix( urls.opac_rresult ) + '?m=' + htarget;
844                                         break;
845                                         case 'T' :
846                                             opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + htarget;
847                                         break;
848                                         case 'V' :
849                                             var my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative', [ htarget ]);
850                                             opac_url = xulG.url_prefix( urls.opac_rdetail) + '?r=' + my_acn.record();
851                                         break;
852                                         case 'C' :
853                                             var my_acp = obj.network.simple_request( 'FM_ACP_RETRIEVE', [ htarget ]);
854                                             var my_acn;
855                                             if (typeof my_acp.call_number() == 'object') {
856                                                 my_acn = my.acp.call_number();
857                                             } else {
858                                                 my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative',
859                                                     [ my_acp.call_number() ]);
860                                             }
861                                             opac_url = xulG.url_prefix( urls.opac_rdetail) + '?r=' + my_acn.record();
862                                         break;
863                                         default:
864                                             obj.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.holds.show_catalog.unknown_htype', [htype]), obj.retrieve_ids[i]);
865                                             continue;
866                                         break;
867                                     }
868                                     var content_params = {
869                                         'session' : ses(),
870                                         'authtime' : ses('authtime'),
871                                         'opac_url' : opac_url
872                                     };
873                                     xulG.new_tab(
874                                         xulG.url_prefix(urls.XUL_OPAC_WRAPPER),
875                                         {'tab_name': htype == 'M' ? 'Catalog' : $("patronStrings").getString('staff.patron.holds.show_catalog.retrieving_title') },
876                                         content_params
877                                     );
878                                 }
879                             } catch(E) {
880                                 obj.error.standard_unexpected_error_alert('',E);
881                             }
882                         }
883                     ],
884                     'fetch_more' : [
885                         ['command'],
886                         function() {
887                             obj.pull_from_shelf_interface.current.offset += obj.pull_from_shelf_interface.current.limit;
888                             obj.retrieve(true);
889                         }
890                     ],
891                     'lib_filter_checkbox' : [
892                         ['command'],
893                         function(ev) {
894                             var x_lib_type_menu = document.getElementById('lib_type_menu');
895                             if (x_lib_type_menu) x_lib_type_menu.disabled = ! ev.target.checked;
896                             if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = ! ev.target.checked;
897                             obj.clear_and_retrieve();
898                             ev.target.setAttribute('checked',ev.target.checked);
899                         }
900                     ],
901                     'cmd_search_opac' : [
902                         ['command'],
903                         function(ev) {
904                             try {
905                                 var content_params = {
906                                     'show_nav_buttons' : false,
907                                     'show_print_button' : true,
908                                     'passthru_content_params' : {
909                                         'authtoken' : ses(),
910                                         'authtime' : ses('authtime'),
911                                         'window_open' : function(a,b,c) {
912                                             try {
913                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
914                                                 return window.open(a,b,c);
915                                             } catch(E) {
916                                                 obj.error.standard_unexpected_error_alert('window_open',E);
917                                             }
918                                         },
919                                         'opac_hold_placed' : function(hold) {
920                                             try {
921                                                 obj.list.append(
922                                                     {
923                                                         'row' : {
924                                                             'my' : {
925                                                                 'hold_id' : typeof hold == 'object' ? hold.id() : hold
926                                                             }
927                                                         }
928                                                     }
929                                                 );
930                                                 if (window.xulG && typeof window.xulG.on_list_change == 'function') {
931                                                     window.xulG.on_list_change(); 
932                                                 }
933                                             } catch(E) {
934                                                 obj.error.standard_unexpected_error_alert('holds.js, opac_hold_placed(): ',E);
935                                             }
936                                         },
937                                         'patron_barcode' : obj.patron_barcode
938                                     },
939                                     'url_prefix' : xulG.url_prefix,
940                                     'url' : xulG.url_prefix( urls.browser )
941                                 };
942                                 xulG.display_window.g.patron.right_deck.set_iframe( urls.XUL_REMOTE_BROWSER + '?patron_hold=1', {}, content_params);
943                             } catch(E) {
944                                 obj.error.sdump('D_ERROR','cmd_search_opac: ' + E);
945                             }
946
947                         }
948                     ]
949                 }
950             }
951         );
952
953         obj.determine_hold_interface_type();
954         var x_fetch_more = document.getElementById('fetch_more');
955         var x_lib_type_menu = document.getElementById('lib_type_menu');
956         var x_lib_menu_placeholder = document.getElementById('lib_menu_placeholder');
957         var x_lib_filter_checkbox = document.getElementById('lib_filter_checkbox');
958         switch(obj.hold_interface_type) {
959             case 'shelf':
960                 obj.render_lib_menus({'pickup_lib':true});
961                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
962                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
963             break;
964             case 'pull' :
965                 if (x_fetch_more) x_fetch_more.hidden = false;
966                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
967                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
968             break;
969             case 'record' :
970                 obj.render_lib_menus({'pickup_lib':true,'request_lib':true});
971                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.hidden = false;
972                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
973                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
974             break;
975             default:
976                 if (obj.controller.view.cmd_search_opac) obj.controller.view.cmd_search_opac.setAttribute('hidden', false);
977                 if (x_fetch_more) x_fetch_more.hidden = true;
978                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
979                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
980             break;
981         }
982         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
983             function() {
984                 if (x_lib_filter_checkbox) if (!x_lib_filter_checkbox.checked) {
985                     if (x_lib_type_menu) x_lib_type_menu.disabled = true;
986                     if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = true;
987                 }
988                 obj.controller.render();
989                 obj.retrieve(true);
990
991                 obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
992                 obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
993                 obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
994                 obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
995                 obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','true');
996                 obj.controller.view.cmd_holds_activate.setAttribute('disabled','true');
997                 obj.controller.view.cmd_holds_suspend.setAttribute('disabled','true');
998                 obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
999                 obj.controller.view.cmd_alt_view.setAttribute('disabled','true');
1000                 obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
1001                 obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
1002                 obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
1003             }, 0
1004         );
1005
1006         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
1007         JSAN.use('util.browser');
1008         obj.browser = new util.browser();
1009         obj.browser.init(
1010             {
1011                 'url' : urls.XUL_HOLD_DETAILS,
1012                 'push_xulG' : true,
1013                 'alt_print' : false,
1014                 'browser_id' : 'hold_detail_frame',
1015                 'passthru_content_params' : xulG,
1016             }
1017         );
1018
1019     },
1020
1021     'determine_hold_interface_type' : function() {
1022         var obj = this;
1023         if (obj.patron_id) { /*************************************************** PATRON ******************************/
1024             obj.hold_interface_type = 'patron';
1025         } else if (obj.docid) { /*************************************************** RECORD ******************************/
1026             obj.hold_interface_type = 'record';
1027         } else if (obj.pull) { /*************************************************** PULL ******************************/
1028             obj.hold_interface_type = 'pull';
1029         } else if (obj.shelf) { /*************************************************** HOLD SHELF ******************************/
1030             obj.hold_interface_type = 'shelf';
1031         } else { /*************************************************** PULL ******************************/
1032             obj.hold_interface_type = 'pull';
1033         }
1034     },
1035
1036     'clear_and_retrieve' : function() {
1037         try {
1038             this.list.clear();
1039             this.pull_from_shelf_interface.current.offset = this.pull_from_shelf_interface._default.offset;
1040             this.retrieve();
1041             if (window.xulG && typeof window.xulG.on_list_change == 'function') {
1042                 window.xulG.on_list_change(); 
1043             }
1044         } catch(E) {
1045             this.error.standard_unexpected_error_alert('holds.js, clear_and_retrieve(): ',E);
1046         }
1047     },
1048
1049     'retrieve' : function() {
1050         var obj = this; var holds = [];
1051         if (window.xulG && window.xulG.holds) {
1052             holds = window.xulG.holds;
1053         } else {
1054             var method; var params = [ ses() ];
1055             switch(obj.hold_interface_type) {
1056                 case 'patron' :
1057                     method = 'FM_AHR_ID_LIST_RETRIEVE_VIA_AU.authoritative';
1058                     params.push( obj.patron_id );
1059                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','true');
1060                 break;
1061                 case 'record' :
1062                     method = 'FM_AHR_RETRIEVE_ALL_VIA_BRE';
1063                     params.push( obj.docid );
1064                     var x_lib_filter = document.getElementById('lib_filter_checkbox');
1065                     var x_lib_type_menu = document.getElementById('lib_type_menu');
1066                     if (x_lib_filter) {
1067                         if (x_lib_filter.checked) {
1068                             if (x_lib_type_menu && obj.controller.view.lib_menu) {
1069                                 var x = {};
1070                                 x[ x_lib_type_menu.value ] = obj.controller.view.lib_menu.value;
1071                                 params.push( x );
1072                             }
1073                         }
1074                     }
1075                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1076                 break;
1077                 case 'shelf' :
1078                     method = 'FM_AHR_ID_LIST_ONSHELF_RETRIEVE';
1079                     params.push( obj.filter_lib || obj.data.list.au[0].ws_ou() );
1080                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1081                 break;
1082                 case 'pull' :
1083                 default:
1084                     method = 'FM_AHR_ID_LIST_PULL_LIST';
1085                     params.push( obj.pull_from_shelf_interface.current.limit ); params.push( obj.pull_from_shelf_interface.current.offset );
1086                     //obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
1087                 break;
1088             }
1089             var robj = obj.network.simple_request( method, params );
1090             if (robj != null && typeof robj.ilsevent != 'undefined') throw(robj);
1091             if (method == 'FM_AHR_RETRIEVE_ALL_VIA_BRE') {
1092                 holds = [];
1093                 if (robj != null) {
1094                     holds = holds.concat( robj.copy_holds );
1095                     holds = holds.concat( robj.volume_holds );
1096                     holds = holds.concat( robj.title_holds );
1097                     holds = holds.concat( robj.metarecord_holds );
1098                     holds = holds.sort();
1099                 }
1100             } else {
1101                 if (robj == null ) {
1102                     holds = [];
1103                 } else {
1104                     if (typeof robj.length == 'undefined') {
1105                         holds = [ robj ];
1106                     } else {
1107                         holds = robj;
1108                     }
1109                 }
1110             }
1111             //alert('method = ' + method + ' params = ' + js2JSON(params));
1112         }
1113
1114         var x_fetch_more = document.getElementById('fetch_more');
1115         if (holds.length == 0) {
1116             if (x_fetch_more) x_fetch_more.disabled = true;
1117         } else {
1118             if (x_fetch_more) x_fetch_more.disabled = false;
1119             obj.render(holds);
1120         }
1121
1122     },
1123
1124     'render' : function(holds) {
1125         try {
1126             var obj = this;
1127
1128             function list_append(hold_id) {
1129                 obj.list.append(
1130                     {
1131                         'row' : {
1132                             'my' : {
1133                                 'hold_id' : hold_id
1134                             }
1135                         }
1136                     }
1137                 );
1138             }
1139
1140             function gen_list_append(hold) {
1141                 return function() {
1142                     if (typeof obj.controller.view.lib_menu == 'undefined') {
1143                         list_append(typeof hold == 'object' ? hold.id() : hold);
1144                     } else {
1145                         list_append(typeof hold == 'object' ? hold.id() : hold);
1146                     }
1147                 };
1148             }
1149
1150             //obj.list.clear();
1151
1152             JSAN.use('util.exec'); var exec = new util.exec(2);
1153             var rows = [];
1154             for (var i in holds) {
1155                 rows.push( gen_list_append(holds[i]) );
1156             }
1157             exec.chain( rows );
1158
1159         } catch(E) {
1160             this.error.standard_unexpected_error_alert('holds.js, render():',E);
1161         }
1162     },
1163
1164     'render_lib_menus' : function(types) {
1165         try {
1166             var obj = this;
1167             JSAN.use('util.widgets'); JSAN.use('util.functional'); JSAN.use('util.fm_utils');
1168
1169             var x = document.getElementById('lib_type_menu');
1170             if (types) {
1171                 var nodes = x.firstChild.childNodes;
1172                 for (var i = 0; i < nodes.length; i++) nodes[i].hidden = true;
1173                 for (var i in types) document.getElementById(i).hidden = false;
1174             }
1175             x.setAttribute('oncommand','g.holds.clear_and_retrieve()');
1176
1177             x = document.getElementById('lib_menu_placeholder');
1178             util.widgets.remove_children( x );
1179
1180             JSAN.use('util.file');
1181             var file = new util.file('offline_ou_list');
1182             if (file._file.exists()) {
1183                 var list_data = file.get_object(); file.close();
1184                 var ml = util.widgets.make_menulist( list_data[0], obj.data.list.au[0].ws_ou() );
1185                 ml.setAttribute('id','lib_menu');
1186                 x.appendChild( ml );
1187                 ml.addEventListener(
1188                     'command',
1189                     function(ev) {
1190                         obj.filter_lib = ev.target.value;
1191                         obj.clear_and_retrieve();
1192                     },
1193                     false
1194                 );
1195                 obj.controller.view.lib_menu = ml;
1196             } else {
1197                 throw($("patronStrings").getString('staff.patron.holds.lib_menus.missing_library_list'));
1198             }
1199
1200         } catch(E) {
1201             this.error.standard_unexpected_error_alert('rendering lib menu',E);
1202         }
1203     }
1204 }
1205
1206 dump('exiting patron.holds.js\n');