]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/patron/holds.js
flatten current_copy on ahr before updating hold
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / patron / holds.js
1 dump('entering patron.holds.js\n');
2
3 if (typeof patron == 'undefined') patron = {};
4 patron.holds = function (params) {
5
6         JSAN.use('util.error'); this.error = new util.error();
7         JSAN.use('util.network'); this.network = new util.network();
8         JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
9 }
10
11 patron.holds.prototype = {
12
13     'hold_interface_type' : null,
14
15     'pull_from_shelf_interface' : {
16         'default' : { 'limit' : 50, 'offset' : 0 },
17         'current' : { 'limit' : 50, 'offset' : 0 }
18     },
19
20         'filter_lib' : null,
21
22         'retrieve_ids' : [],
23
24         'holds_map' : {},
25
26         'init' : function( params ) {
27
28                 var obj = this;
29
30                 obj.patron_id = params['patron_id'];
31                 obj.docid = params['docid'];
32                 obj.shelf = params['shelf'];
33                 obj.tree_id = params['tree_id'];
34
35                 JSAN.use('circ.util');
36                 var columns = circ.util.hold_columns( 
37                         { 
38                                 'title' : { 'hidden' : false, 'flex' : '3' },
39                                 'request_time' : { 'hidden' : false },
40                                 'pickup_lib_shortname' : { 'hidden' : false },
41                                 'hold_type' : { 'hidden' : false },
42                                 'current_copy' : { 'hidden' : false },
43                                 'capture_time' : { 'hidden' : false },
44                                 'notify_time' : { 'hidden' : false },
45                                 'notify_count' : { 'hidden' : false },
46                         } 
47                 );
48
49                 JSAN.use('util.list'); obj.list = new util.list( obj.tree_id || 'holds_list');
50                 obj.list.init(
51                         {
52                                 'columns' : columns,
53                                 'map_row_to_columns' : circ.util.std_map_row_to_columns(),
54                                 'retrieve_row' : function(params) {
55                                         var row = params.row;
56                                         try {
57                                                 obj.network.simple_request('FM_AHR_BLOB_RETRIEVE', [ ses(), row.my.hold_id ],
58                                                         function(blob_req) {
59                                                                 try {
60                                                                         var blob = blob_req.getResultObject();
61                                                                         if (typeof blob.ilsevent != 'undefined') throw(blob);
62                                                                         row.my.ahr = blob.hold;
63                                                                         row.my.status = blob.status;
64                                                                         row.my.acp = blob.copy;
65                                                                         row.my.acn = blob.volume;
66                                                                         row.my.mvr = blob.mvr;
67                                                                         row.my.patron_family_name = blob.patron_last;
68                                                                         row.my.patron_first_given_name = blob.patron_first;
69                                                                         row.my.patron_barcode = blob.patron_barcode;
70
71                                                                         var copy_id = row.my.ahr.current_copy();
72                                                                         if (typeof copy_id == 'object') {
73                                                                                 if (copy_id == null) {
74                                                                                         if (typeof row.my.acp == 'object' && row.my.acp != null) copy_id = row.my.acp.id();
75                                                                                 } else {
76                                                                                         copy_id = copy_id.id();
77                                                                                 }
78                                                                         } else {
79                                                                                 copy_id = row.my.acp.id();
80                                                                         }
81
82                                                                         obj.holds_map[ row.my.ahr.id() ] = row.my.ahr;
83                                                                         params.row_node.setAttribute('retrieve_id', 
84                                                                                 js2JSON({
85                                                                                         'copy_id':copy_id,
86                                             'barcode':row.my.acp ? row.my.acp.barcode() : null,
87                                                                                         'id':row.my.ahr.id(),
88                                                                                         'type':row.my.ahr.hold_type(),
89                                                                                         'target':row.my.ahr.target(),
90                                                                                         'usr':row.my.ahr.usr(),
91                                                                                 })
92                                                                         );
93                                                                         if (typeof params.on_retrieve == 'function') { params.on_retrieve(row); }
94
95                                                                 } catch(E) {
96                                                                         obj.error.standard_unexpected_error_alert('Error retrieving details for hold #' + row.my.hold_id, E);
97                                                                 }
98                                                         }
99                                                 );
100                                         } catch(E) {
101                                                 obj.error.sdump('D_ERROR','retrieve_row: ' + E );
102                                         }
103                                         return row;
104                                 },
105                                 'on_select' : function(ev) {
106                                         JSAN.use('util.functional');
107                                         var sel = obj.list.retrieve_selection();
108                                         obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
109                                         obj.retrieve_ids = util.functional.map_list(
110                                                 sel,
111                                                 function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
112                                         );
113                                         if (obj.retrieve_ids.length > 0) {
114                                                 obj.controller.view.sel_mark_items_damaged.setAttribute('disabled','false');
115                                                 obj.controller.view.sel_mark_items_missing.setAttribute('disabled','false');
116                                                 obj.controller.view.sel_copy_details.setAttribute('disabled','false');
117                                                 obj.controller.view.sel_patron.setAttribute('disabled','false');
118                                                 obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','false');
119                                                 obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','false');
120                                                 obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','false');
121                                                 obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','false');
122                                                 obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','false');
123                                                 obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','false');
124                                                 obj.controller.view.cmd_holds_edit_freeze.setAttribute('disabled','false');
125                                                 obj.controller.view.cmd_show_notifications.setAttribute('disabled','false');
126                                                 obj.controller.view.cmd_holds_retarget.setAttribute('disabled','false');
127                                                 obj.controller.view.cmd_holds_cancel.setAttribute('disabled','false');
128                                                 obj.controller.view.cmd_show_catalog.setAttribute('disabled','false');
129                                         } else {
130                                                 obj.controller.view.sel_mark_items_damaged.setAttribute('disabled','true');
131                                                 obj.controller.view.sel_mark_items_missing.setAttribute('disabled','true');
132                                                 obj.controller.view.sel_copy_details.setAttribute('disabled','true');
133                                                 obj.controller.view.sel_patron.setAttribute('disabled','true');
134                                                 obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
135                                                 obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
136                                                 obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
137                                                 obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
138                                                 obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
139                                                 obj.controller.view.cmd_holds_edit_thaw_date.setAttribute('disabled','true');
140                                                 obj.controller.view.cmd_holds_edit_freeze.setAttribute('disabled','true');
141                                                 obj.controller.view.cmd_show_notifications.setAttribute('disabled','true');
142                                                 obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
143                                                 obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
144                                                 obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
145                                         }
146                                 },
147
148                         }
149                 );
150                 
151                 JSAN.use('util.controller'); obj.controller = new util.controller();
152                 obj.controller.init(
153                         {
154                                 'control_map' : {
155                                         'save_columns' : [ [ 'command' ], function() { obj.list.save_columns(); } ],
156                                         'sel_clip' : [
157                                                 ['command'],
158                                                 function() { obj.list.clipboard(); }
159                                         ],
160                                         'cmd_broken' : [
161                                                 ['command'],
162                                                 function() { alert('Not Yet Implemented'); }
163                                         ],
164                                         'sel_patron' : [
165                                                 ['command'],
166                                                 function() {
167                                                         JSAN.use('circ.util');
168                                                         circ.util.show_last_few_circs(obj.retrieve_ids);
169                                                 }
170                                         ],
171                                         'sel_mark_items_damaged' : [
172                                                 ['command'],
173                                                 function() {
174                                                         JSAN.use('cat.util'); JSAN.use('util.functional');
175                                                         cat.util.mark_item_damaged( util.functional.map_list( obj.retrieve_ids, function(o) { return o.copy_id; } ) );
176                                                 }
177                                         ],
178                                         'sel_mark_items_missing' : [
179                                                 ['command'],
180                                                 function() {
181                                                         JSAN.use('cat.util'); JSAN.use('util.functional');
182                                                         cat.util.mark_item_missing( util.functional.map_list( obj.retrieve_ids, function(o) { return o.copy_id; } ) );
183                                                 }
184                                         ],
185                                         'sel_copy_details' : [
186                                                 ['command'],
187                                                 function() {
188                                                         JSAN.use('circ.util');
189                                                         for (var i = 0; i < obj.retrieve_ids.length; i++) {
190                                                                 if (obj.retrieve_ids[i].copy_id) circ.util.show_copy_details( obj.retrieve_ids[i].copy_id );
191                                                         }
192                                                 }
193                                         ],
194                                         'cmd_holds_print' : [
195                                                 ['command'],
196                                                 function() {
197                                                         try {
198                                                                 dump(js2JSON(obj.list.dump_with_keys()) + '\n');
199                                                                 function flesh_callback() {
200                                                                         try {
201                                                                                 JSAN.use('patron.util');
202                                                                                 var params = { 
203                                                                                         'patron' : patron.util.retrieve_au_via_id(ses(),obj.patron_id), 
204                                                                                         'lib' : obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ],
205                                                                                         'staff' : obj.data.list.au[0],
206                                                                                         'header' : obj.data.print_list_templates.holds.header,
207                                                                                         'line_item' : obj.data.print_list_templates.holds.line_item,
208                                                                                         'footer' : obj.data.print_list_templates.holds.footer,
209                                                                                         'type' : obj.data.print_list_templates.holds.type,
210                                                                                         'list' : obj.list.dump_with_keys(),
211                                                                                 };
212                                                                                 JSAN.use('util.print'); var print = new util.print();
213                                                                                 print.tree_list( params );
214                                                                                 setTimeout(function(){obj.list.on_all_fleshed = null;},0);
215                                                                         } catch(E) {
216                                                                                 obj.error.standard_unexpected_error_alert('print 2',E);
217                                                                         }
218                                                                 }
219                                                                 obj.list.on_all_fleshed = flesh_callback;
220                                                                 obj.list.full_retrieve();
221                                                         } catch(E) {
222                                                                 obj.error.standard_unexpected_error_alert('print 1',E);
223                                                         }
224                                                 }
225                                         ],
226                                         'cmd_holds_export' : [
227                                                 ['command'],
228                                                 function() {
229                                                         try {
230                                                                 function flesh_callback() {
231                                                                         try {
232                                                                                 dump(obj.list.dump_csv() + '\n');
233                                                                                 copy_to_clipboard(obj.list.dump_csv());
234                                                                                 setTimeout(function(){obj.list.on_all_fleshed = null;},0);
235                                                                         } catch(E) {
236                                                                                 obj.error.standard_unexpected_error_alert('export 2',E);
237                                                                         }
238                                                                 }
239                                                                 obj.list.on_all_fleshed = flesh_callback;
240                                                                 obj.list.full_retrieve();
241                                                         } catch(E) {
242                                                                 obj.error.standard_unexpected_error_alert('export 1',E);
243                                                         }
244                                                 }
245                                         ],
246
247                                         'cmd_show_notifications' : [
248                                                 ['command'],
249                                                 function() {
250                                                         try {
251                                                                 JSAN.use('util.window'); var win = new util.window();
252                                                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
253                                                                         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
254                                                                         win.open(
255                                                                                 xulG.url_prefix(urls.XUL_HOLD_NOTICES), // + '?ahr_id=' + obj.retrieve_ids[i].id,
256                                                                                 'hold_notices_' + obj.retrieve_ids[i].id,
257                                                                                 'chrome,resizable',
258                                                                                 { 'ahr_id' : obj.retrieve_ids[i].id }
259                                                                         );
260                                                                 }
261                                                         } catch(E) {
262                                                                 obj.error.standard_unexpected_error_alert('Error rendering/retrieving hold notifications.',E);
263                                                         }
264                                                 }
265                                         ],
266                                         'cmd_holds_edit_selection_depth' : [
267                                                 ['command'],
268                                                 function() {
269                                                         try {
270                                                                 JSAN.use('util.widgets'); JSAN.use('util.functional'); 
271                                                                 var ws_type = obj.data.hash.aout[ obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ].ou_type() ];
272                                                                 var list = util.functional.map_list(
273                                                                         util.functional.filter_list(    
274                                                                                 obj.data.list.aout,
275                                                                                 function(o) {
276                                                                                         if (o.depth() > ws_type.depth()) return false;
277                                                                                         if (o.depth() < ws_type.depth()) return true;
278                                                                                         return (o.id() == ws_type.id());
279                                                                                 }
280                                                                         ),
281                                                                         function(o) { 
282                                                                                 return [
283                                                                                         o.opac_label(),
284                                                                                         o.id(),
285                                                                                         false,
286                                                                                         ( o.depth() * 2),
287                                                                                 ]; 
288                                                                         }
289                                                                 );
290                                                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
291                                                                 ml.setAttribute('id','selection');
292                                                                 ml.setAttribute('name','fancy_data');
293                                                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
294                                                                 xml += '<description>Please choose a Hold Range:</description>';
295                                                                 xml += util.widgets.serialize_node(ml);
296                                                                 xml += '</vbox>';
297                                                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
298                                                                 bot_xml += '<spacer flex="1"/><button label="Done" accesskey="D" name="fancy_submit"/>';
299                                                                 bot_xml += '<button label="Cancel" accesskey="C" name="fancy_cancel"/></hbox>';
300                                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
301                                                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
302                                                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
303                                                                 JSAN.use('util.window'); var win = new util.window();
304                                                                 var fancy_prompt_data = win.open(
305                                                                         urls.XUL_FANCY_PROMPT,
306                                                                         //+ '?xml_in_stash=temp_mid'
307                                                                         //+ '&bottom_xml_in_stash=temp_bot'
308                                                                         //+ '&title=' + window.escape('Choose a Pick Up Library'),
309                                                                         'fancy_prompt', 'chrome,resizable,modal',
310                                                                         { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : 'Choose a Pick Up Library' }
311                                                                 );
312                                                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
313                                                                 var selection = fancy_prompt_data.selection;
314                                                                 var msg = 'Are you sure you would like to change the Hold Range for hold' + ( obj.retrieve_ids.length > 1 ? 's ' : ' ') + util.functional.map_list( obj.retrieve_ids, function(o){return o.id;}).join(', ') + ' to "' + obj.data.hash.aout[selection].opac_label() + '"?';
315                                                                 var r = obj.error.yns_alert(msg,'Modifying Holds','Yes','No',null,'Check here to confirm this message');
316                                                                 if (r == 0) {
317                                                                         for (var i = 0; i < obj.retrieve_ids.length; i++) {
318                                                                                 var hold = obj.holds_map[ obj.retrieve_ids[i].id ];
319                                                                                 hold.selection_depth( obj.data.hash.aout[selection].depth() ); hold.ischanged('1');
320                                         try { if ( typeof hold.current_copy() == 'object') hold.current_copy( hold.current_copy().id() ); } catch(E) { alert('IFXME: Error flattening hold before hold update: ' + E); }
321                                                                                 var robj = obj.network.simple_request('FM_AHR_UPDATE',[ ses(), hold ]);
322                                                                                 if (typeof robj.ilsevent != 'undefined') throw(robj);
323                                                                         }
324                                                                         obj.clear_and_retrieve(true);
325                                                                 }
326                                                         } catch(E) {
327                                                                 obj.error.standard_unexpected_error_alert('Holds not likely modified.',E);
328                                                         }
329                                                 }
330                                         ],
331
332                                         'cmd_holds_edit_pickup_lib' : [
333                                                 ['command'],
334                                                 function() {
335                                                         try {
336                                                                 JSAN.use('util.widgets'); JSAN.use('util.functional'); 
337                                                                 var list = util.functional.map_list(
338                                                                         obj.data.list.aou,
339                                                                         function(o) { 
340                                                                                 var sname = o.shortname(); for (i = sname.length; i < 20; i++) sname += ' ';
341                                                                                 return [
342                                                                                         o.name() ? sname + ' ' + o.name() : o.shortname(),
343                                                                                         o.id(),
344                                                                                         ( obj.data.hash.aout[ o.ou_type() ].can_have_users() == 0),
345                                                                                         ( obj.data.hash.aout[ o.ou_type() ].depth() * 2),
346                                                                                 ]; 
347                                                                         }
348                                                                 );
349                                                                 ml = util.widgets.make_menulist( list, obj.data.list.au[0].ws_ou() );
350                                                                 ml.setAttribute('id','lib');
351                                                                 ml.setAttribute('name','fancy_data');
352                                                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
353                                                                 xml += '<description>Please choose a new Pickup Library:</description>';
354                                                                 xml += util.widgets.serialize_node(ml);
355                                                                 xml += '</vbox>';
356                                                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
357                                                                 bot_xml += '<spacer flex="1"/><button label="Done" accesskey="D" name="fancy_submit"/>';
358                                                                 bot_xml += '<button label="Cancel" accesskey="C" name="fancy_cancel"/></hbox>';
359                                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
360                                                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
361                                                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
362                                                                 JSAN.use('util.window'); var win = new util.window();
363                                                                 var fancy_prompt_data = win.open(
364                                                                         urls.XUL_FANCY_PROMPT,
365                                                                         //+ '?xml_in_stash=temp_mid'
366                                                                         //+ '&bottom_xml_in_stash=temp_bot'
367                                                                         //+ '&title=' + window.escape('Choose a Pick Up Library'),
368                                                                         'fancy_prompt', 'chrome,resizable,modal',
369                                                                         { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : 'Choose a Pick Up Library' }
370                                                                 );
371                                                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
372                                                                 var pickup_lib = fancy_prompt_data.lib;
373                                                                 var msg = 'Are you sure you would like to change the Pick Up Lib for hold' + ( obj.retrieve_ids.length > 1 ? 's ' : ' ') + util.functional.map_list( obj.retrieve_ids, function(o){return o.id;}).join(', ') + ' to ' + obj.data.hash.aou[pickup_lib].shortname() + '?';
374                                                                 var r = obj.error.yns_alert(msg,'Modifying Holds','Yes','No',null,'Check here to confirm this message');
375                                                                 if (r == 0) {
376                                                                         for (var i = 0; i < obj.retrieve_ids.length; i++) {
377                                                                                 var hold = obj.holds_map[ obj.retrieve_ids[i].id ];
378                                                                                 hold.pickup_lib(  pickup_lib ); hold.ischanged('1');
379                                         try { if ( typeof hold.current_copy() == 'object') hold.current_copy( hold.current_copy().id() ); } catch(E) { alert('IFXME: Error flattening hold before hold update: ' + E); }
380                                                                                 var robj = obj.network.simple_request('FM_AHR_UPDATE',[ ses(), hold ]);
381                                                                                 if (typeof robj.ilsevent != 'undefined') throw(robj);
382                                                                         }
383                                                                         obj.clear_and_retrieve(true);
384                                                                 }
385                                                         } catch(E) {
386                                                                 obj.error.standard_unexpected_error_alert('Holds not likely modified.',E);
387                                                         }
388                                                 }
389                                         ],
390                                         'cmd_holds_edit_phone_notify' : [
391                                                 ['command'],
392                                                 function() {
393                                                         try {
394                                                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
395                                                                 xml += '<description>Please enter a new phone number for hold notification (leave the field empty to disable phone notification):</description>';
396                                                                 xml += '<textbox id="phone" name="fancy_data"/>';
397                                                                 xml += '</vbox>';
398                                                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
399                                                                 bot_xml += '<spacer flex="1"/><button label="Done" accesskey="D" name="fancy_submit"/>';
400                                                                 bot_xml += '<button label="Cancel" accesskey="C" name="fancy_cancel"/></hbox>';
401                                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
402                                                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
403                                                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
404                                                                 JSAN.use('util.window'); var win = new util.window();
405                                                                 var fancy_prompt_data = win.open(
406                                                                         urls.XUL_FANCY_PROMPT,
407                                                                         //+ '?xml_in_stash=temp_mid'
408                                                                         //+ '&bottom_xml_in_stash=temp_bot'
409                                                                         //+ '&title=' + window.escape('Choose a Hold Notification Phone Number')
410                                                                         //+ '&focus=phone',
411                                                                         'fancy_prompt', 'chrome,resizable,modal',
412                                                                         { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : 'Choose a Hold Notification Phone Number', 'focus' : 'phone' }
413                                                                 );
414                                                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
415                                                                 var phone = fancy_prompt_data.phone;
416                                                                 var msg = 'Are you sure you would like to change the Notification Phone Number for hold' + ( obj.retrieve_ids.length > 1 ? 's ' : ' ') + util.functional.map_list( obj.retrieve_ids, function(o){return o.id;}).join(', ') + ' to "' + phone + '"?';
417                                                                 var r = obj.error.yns_alert(msg,'Modifying Holds','Yes','No',null,'Check here to confirm this message');
418                                                                 if (r == 0) {
419                                                                         for (var i = 0; i < obj.retrieve_ids.length; i++) {
420                                                                                 var hold = obj.holds_map[ obj.retrieve_ids[i].id ];
421                                                                                 hold.phone_notify(  phone ); hold.ischanged('1');
422                                         try { if ( typeof hold.current_copy() == 'object') hold.current_copy( hold.current_copy().id() ); } catch(E) { alert('IFXME: Error flattening hold before hold update: ' + E); }
423                                                                                 var robj = obj.network.simple_request('FM_AHR_UPDATE',[ ses(), hold ]);
424                                                                                 if (typeof robj.ilsevent != 'undefined') throw(robj);
425                                                                         }
426                                                                         obj.clear_and_retrieve(true);
427                                                                 }
428                                                         } catch(E) {
429                                                                 obj.error.standard_unexpected_error_alert('Holds not likely modified.',E);
430                                                         }
431                                                 }
432                                         ],
433                                         'cmd_holds_edit_email_notify' : [
434                                                 ['command'],
435                                                 function() {
436                                                         try {
437                                                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
438                                                                 xml += '<description>Send email notifications (when appropriate)?  The email address used is found in the hold recipient account.</description>';
439                                                                 xml += '<hbox><button value="email" label="Email" accesskey="E" name="fancy_submit"/>';
440                                                                 xml += '<button value="noemail" label="No Email" accesskey="N" name="fancy_submit"/></hbox>';
441                                                                 xml += '</vbox>';
442                                                                 var bot_xml = '<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
443                                                                 bot_xml += '<spacer flex="1"/><button label="Cancel" accesskey="C" name="fancy_cancel"/></hbox>';
444                                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
445                                                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
446                                                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
447                                                                 JSAN.use('util.window'); var win = new util.window();
448                                                                 var fancy_prompt_data = win.open(
449                                                                         urls.XUL_FANCY_PROMPT,
450                                                                         //+ '?xml_in_stash=temp_mid'
451                                                                         //+ '&bottom_xml_in_stash=temp_bot'
452                                                                         //+ '&title=' + window.escape('Set Email Notification for Holds'),
453                                                                         'fancy_prompt', 'chrome,resizable,modal',
454                                                                         { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : 'Set Email Notification for Holds' }
455                                                                 );
456                                                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
457                                                                 var email = fancy_prompt_data.fancy_submit == 'email' ? get_db_true() : get_db_false();
458                                                                 var msg = 'Are you sure you would like ' + ( get_bool( email ) ? 'enable' : 'disable' ) + ' email notification for hold' + ( obj.retrieve_ids.length > 1 ? 's ' : ' ') + util.functional.map_list( obj.retrieve_ids, function(o){return o.id;}).join(', ') + '?';
459                                                                 var r = obj.error.yns_alert(msg,'Modifying Holds','Yes','No',null,'Check here to confirm this message');
460                                                                 if (r == 0) {
461                                                                         for (var i = 0; i < obj.retrieve_ids.length; i++) {
462                                                                                 var hold = obj.holds_map[ obj.retrieve_ids[i].id ];
463                                                                                 hold.email_notify(  email ); hold.ischanged('1');
464                                         try { if ( typeof hold.current_copy() == 'object') hold.current_copy( hold.current_copy().id() ); } catch(E) { alert('IFXME: Error flattening hold before hold update: ' + E); }
465                                                                                 var robj = obj.network.simple_request('FM_AHR_UPDATE',[ ses(), hold ]);
466                                                                                 if (typeof robj.ilsevent != 'undefined') throw(robj);
467                                                                         }
468                                                                         obj.clear_and_retrieve(true);
469                                                                 }
470                                                         } catch(E) {
471                                                                 obj.error.standard_unexpected_error_alert('Holds not likely modified.',E);
472                                                         }
473                                                 }
474                                         ],
475                     'cmd_holds_edit_freeze' : [
476                                                 ['command'],
477                                                 function() {
478                                                         try {
479                                                                 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: vertical">';
480                                                                 xml += '<description>Freeze or un-freeze these holds?</description>';
481                                                                 xml += '<hbox><button value="freeze" label="Freeze" accesskey="F" name="fancy_submit"/>';
482                                                                 xml += '<button value="unfreeze" label="Un-Freeze" accesskey="U" 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="Cancel" accesskey="C" name="fancy_cancel"/></hbox>';
486                                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
487                                                                 //obj.data.temp_mid = xml; obj.data.stash('temp_mid');
488                                                                 //obj.data.temp_bot = bot_xml; obj.data.stash('temp_bot');
489                                                                 JSAN.use('util.window'); var win = new util.window();
490                                                                 var fancy_prompt_data = win.open(
491                                                                         urls.XUL_FANCY_PROMPT,
492                                                                         //+ '?xml_in_stash=temp_mid'
493                                                                         //+ '&bottom_xml_in_stash=temp_bot'
494                                                                         //+ '&title=' + window.escape('Set Email Notification for Holds'),
495                                                                         'fancy_prompt', 'chrome,resizable,modal',
496                                                                         { 'xml' : xml, 'bottom_xml' : bot_xml, 'title' : 'Set Email Notification for Holds' }
497                                                                 );
498                                                                 if (fancy_prompt_data.fancy_status == 'incomplete') { return; }
499                                                                 var freeze = fancy_prompt_data.fancy_submit == 'freeze' ? get_db_true() : get_db_false();
500                                                                 var msg = 'Are you sure you would like to ' + ( get_bool( freeze ) ? 'freeze' : 'un-freeze' ) + ' hold' + ( obj.retrieve_ids.length > 1 ? 's ' : ' ') + util.functional.map_list( obj.retrieve_ids, function(o){return o.id;}).join(', ') + '?';
501                                                                 var r = obj.error.yns_alert(msg,'Modifying Holds','Yes','No',null,'Check here to confirm this message');
502                                                                 if (r == 0) {
503                                                                         for (var i = 0; i < obj.retrieve_ids.length; i++) {
504                                                                                 var hold = obj.holds_map[ obj.retrieve_ids[i].id ];
505                                                                                 hold.frozen(  freeze ); 
506                                                                                 if ( ! get_bool( freeze ) ) {
507                                                                                         hold.thaw_date( null );
508                                                                                 }
509                                                                                 hold.ischanged('1');
510                                         try { if ( typeof hold.current_copy() == 'object') hold.current_copy( hold.current_copy().id() ); } catch(E) { alert('IFXME: Error flattening hold before hold update: ' + E); }
511                                                                                 var robj = obj.network.simple_request('FM_AHR_UPDATE',[ ses(), hold ]);
512                                                                                 if (typeof robj.ilsevent != 'undefined') throw(robj);
513                                                                         }
514                                                                         obj.clear_and_retrieve(true);
515                                                                 }
516                                                         } catch(E) {
517                                                                 obj.error.standard_unexpected_error_alert('Holds not likely modified.',E);
518                                                         }
519                                                 }
520                                         ],
521
522                     'cmd_holds_edit_thaw_date' : [
523                                                 ['command'],
524                                                 function() {
525                                                         try {
526                                 JSAN.use('util.date');
527                                 function check_date(value) {
528                                     try {
529                                         if (! util.date.check('YYYY-MM-DD',value) ) { throw('Invalid Date'); }
530                                         if (util.date.check_past('YYYY-MM-DD',value) ) { 
531                                             throw('Thaw date for frozen holds needs to be after today.'); 
532                                         }
533                                         return true;
534                                     } catch(E) {
535                                         alert(E);
536                                         return false;
537                                     }
538                                 }
539
540                                                                 var msg = 'Please enter a thaw date for hold' + ( obj.retrieve_ids.length > 1 ? 's ' : ' ') + util.functional.map_list( obj.retrieve_ids, function(o){return o.id;}).join(', ') + '\nOr set to blank to unset the thaw date for these holds.  Frozen holds without a thaw date will remain frozen until manually unfrozen, otherwise they unfreeze on the thaw date.';
541                                 var value = 'YYYY-MM-DD';
542                                 var title = 'Modifying Holds';
543                                                                 var thaw_date; var invalid = true;
544                                 while(invalid) {
545                                     thaw_date = window.prompt(msg,value,title);
546                                     if (thaw_date) {
547                                         invalid = ! check_date(thaw_date);
548                                     } else { 
549                                         invalid = false;
550                                     }
551                                 }
552                                 if (thaw_date || thaw_date == '') {
553                                     for (var i = 0; i < obj.retrieve_ids.length; i++) {
554                                         var hold = obj.holds_map[ obj.retrieve_ids[i].id ];
555                                         hold.thaw_date(  thaw_date == '' ? null : util.date.formatted_date(thaw_date + ' 00:00:00','%{iso8601}') ); hold.ischanged('1');
556                                         try { if ( typeof hold.current_copy() == 'object') hold.current_copy( hold.current_copy().id() ); } catch(E) { alert('IFXME: Error flattening hold before hold update: ' + E); }
557                                         var robj = obj.network.simple_request('FM_AHR_UPDATE',[ ses(), hold ]);
558                                         if (typeof robj.ilsevent != 'undefined') throw(robj);
559                                     }
560                                                                         obj.clear_and_retrieve(true);
561                                 }
562                                                         } catch(E) {
563                                                                 obj.error.standard_unexpected_error_alert('Holds not likely modified.',E);
564                                                         }
565                                                 }
566                                         ],
567
568                                         'cmd_holds_retarget' : [
569                                                 ['command'],
570                                                 function() {
571                                                         try {
572                                                                 JSAN.use('util.functional');
573                                                                 var msg = 'Are you sure you would like to reset hold' + ( obj.retrieve_ids.length > 1 ? 's ' : ' ') + util.functional.map_list( obj.retrieve_ids, function(o){return o.id;}).join(', ') + '?';
574                                                                 var r = obj.error.yns_alert(msg,'Resetting Holds','Yes','No',null,'Check here to confirm this message');
575                                                                 if (r == 0) {
576                                                                         for (var i = 0; i < obj.retrieve_ids.length; i++) {
577                                                                                 var robj = obj.network.simple_request('FM_AHR_RESET',[ ses(), obj.retrieve_ids[i].id]);
578                                                                                 if (typeof robj.ilsevent != 'undefined') throw(robj);
579                                                                         }
580                                                                         obj.clear_and_retrieve();
581                                                                 }
582                                                         } catch(E) {
583                                                                 obj.error.standard_unexpected_error_alert('Holds not likely reset.',E);
584                                                         }
585
586                                                 }
587                                         ],
588
589                                         'cmd_holds_cancel' : [
590                                                 ['command'],
591                                                 function() {
592                                                         try {
593                                                                 JSAN.use('util.functional');
594                                                                 var msg = 'Are you sure you would like to cancel hold' + ( obj.retrieve_ids.length > 1 ? 's ' : ' ') + util.functional.map_list( obj.retrieve_ids, function(o){return o.id;}).join(', ') + '?';
595                                                                 var r = obj.error.yns_alert(msg,'Cancelling Holds','Yes','No',null,'Check here to confirm this message');
596                                                                 if (r == 0) {
597                                     var transits = [];
598                                                                         for (var i = 0; i < obj.retrieve_ids.length; i++) {
599                                         if (obj.holds_map[ obj.retrieve_ids[i].id ].transit()) {
600                                             transits.push( obj.retrieve_ids[i].barcode );
601                                         }
602                                                                                 var robj = obj.network.simple_request('FM_AHR_CANCEL',[ ses(), obj.retrieve_ids[i].id]);
603                                                                                 if (typeof robj.ilsevent != 'undefined') throw(robj);
604                                                                         }
605                                     if (transits.length > 0) {
606                                         var msg2 = 'For barcodes ' + transits.join(', ') + ' cancel the transits as well?';
607                                         var r2 = obj.error.yns_alert(msg2,'Cancelling Transits','Yes','No',null,'Check here to confirm this message');
608                                         if (r2 == 0) {
609                                             try {
610                                                 for (var i = 0; i < transits.length; i++) {
611                                                     var robj = obj.network.simple_request('FM_ATC_VOID',[ ses(), { 'barcode' : transits[i] } ]);
612                                                     if (typeof robj.ilsevent != 'undefined') {
613                                                         switch(robj.ilsevent) {
614                                                             case 1225 /* TRANSIT_ABORT_NOT_ALLOWED */ :
615                                                                 alert(robj.desc);
616                                                             break;
617                                                             case 5000 /* PERM_FAILURE */ :
618                                                             break;
619                                                             default:
620                                                                 throw(robj);
621                                                             break;
622                                                         }
623                                                                                             }
624                                                 }
625                                             } catch(E) {
626                                                                             obj.error.standard_unexpected_error_alert('Hold-transits not likely cancelled.',E);
627                                             }
628                                         }
629                                     }
630                                                                         obj.clear_and_retrieve();
631                                                                 }
632                                                         } catch(E) {
633                                                                 obj.error.standard_unexpected_error_alert('Holds not likely cancelled.',E);
634                                                         }
635                                                 }
636                                         ],
637                                         'cmd_retrieve_patron' : [
638                                                 ['command'],
639                                                 function() {
640                                                         try {
641                                                                 var seen = {};
642                                                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
643                                                                         var patron_id = obj.retrieve_ids[i].usr;
644                                                                         if (seen[patron_id]) continue; seen[patron_id] = true;
645                                                                         xulG.new_tab(
646                                                                                 xulG.url_prefix(urls.XUL_PATRON_DISPLAY), // + '?id=' + patron_id, 
647                                                                                 {}, 
648                                                                                 { 'id' : patron_id }
649                                                                         );
650                                                                 }
651                                                         } catch(E) {
652                                                                 obj.error.standard_unexpected_error_alert('',E);
653                                                         }
654                                                 }
655                                         ],
656                                         'cmd_show_catalog' : [
657                                                 ['command'],
658                                                 function() {
659                                                         try {
660                                                                 for (var i = 0; i < obj.retrieve_ids.length; i++) {
661                                                                         var htarget = obj.retrieve_ids[i].target;
662                                                                         var htype = obj.retrieve_ids[i].type;
663                                                                         var opac_url;
664                                                                         switch(htype) {
665                                                                                 case 'M' :
666                                                                                         opac_url = xulG.url_prefix( urls.opac_rresult ) + '?m=' + htarget;
667                                                                                 break;
668                                                                                 case 'T' : 
669                                                                                         opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + htarget;
670                                                                                 break;
671                                                                                 case 'V' :
672                                                                                         var my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE', [ htarget ]);
673                                                                                         opac_url = xulG.url_prefix( urls.opac_rdetail) + '?r=' + my_acn.record();
674                                                                                 break;
675                                                                                 case 'C' :
676                                                                                         var my_acp = obj.network.simple_request( 'FM_ACP_RETRIEVE', [ htarget ]);
677                                                                                         var my_acn;
678                                                                                         if (typeof my_acp.call_number() == 'object') {
679                                                                                                 my_acn = my.acp.call_number();
680                                                                                         } else {
681                                                                                                 my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE', 
682                                                                                                         [ my_acp.call_number() ]);
683                                                                                         }
684                                                                                         opac_url = xulG.url_prefix( urls.opac_rdetail) + '?r=' + my_acn.record();
685                                                                                 break;
686                                                                                 default:
687                                                                                         obj.error.standard_unexpected_error_alert("I don't understand the hold type of " + htype + ", so I can't jump to the appropriate record in the catalog.", obj.retrieve_ids[i]);
688                                                                                         continue;
689                                                                                 break;
690                                                                         }
691                                                                         var content_params = { 
692                                                                                 'session' : ses(),
693                                                                                 'authtime' : ses('authtime'),
694                                                                                 'opac_url' : opac_url,
695                                                                         };
696                                                                         xulG.new_tab(
697                                                                                 xulG.url_prefix(urls.XUL_OPAC_WRAPPER), 
698                                                                                 {'tab_name': htype == 'M' ? 'Catalog' : 'Retrieving title...'}, 
699                                                                                 content_params
700                                                                         );
701                                                                 }
702                                                         } catch(E) {
703                                                                 obj.error.standard_unexpected_error_alert('',E);
704                                                         }
705                                                 }
706                                         ],
707                     'fetch_more' : [
708                         ['command'],
709                         function() {
710                             obj.pull_from_shelf_interface.current.offset += obj.pull_from_shelf_interface.current.limit;
711                             obj.retrieve();
712                         }
713                     ],
714                     'lib_filter_checkbox' : [
715                         ['command'],
716                         function(ev) {
717                             var x_lib_type_menu = document.getElementById('lib_type_menu');
718                             if (x_lib_type_menu) x_lib_type_menu.disabled = ! ev.target.checked;
719                             if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = ! ev.target.checked;
720                             obj.clear_and_retrieve();
721                             ev.target.setAttribute('checked',ev.target.checked);
722                         }
723                     ]
724                                 }
725                         }
726                 );
727         
728         obj.determine_hold_interface_type();
729         var x_fetch_more = document.getElementById('fetch_more');
730         var x_lib_type_menu = document.getElementById('lib_type_menu');
731         var x_lib_menu_placeholder = document.getElementById('lib_menu_placeholder');
732         var x_lib_filter_checkbox = document.getElementById('lib_filter_checkbox');
733         switch(obj.hold_interface_type) {
734             case 'shelf':
735                 obj.render_lib_menus({'pickup_lib':true});
736                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
737                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
738             break;
739             case 'pull' :
740                 if (x_fetch_more) x_fetch_more.hidden = false;
741                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
742                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
743             break;
744             case 'record' :
745                 obj.render_lib_menus({'pickup_lib':true,'request_lib':true});
746                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.hidden = false;
747                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
748                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
749             break;
750             default:
751                 if (x_fetch_more) x_fetch_more.hidden = true;
752                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
753                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
754             break;
755         }
756         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
757             function() {
758                 if (x_lib_filter_checkbox) if (!x_lib_filter_checkbox.checked) {
759                     if (x_lib_type_menu) x_lib_type_menu.disabled = true;
760                     if (obj.controller.view.lib_menu) obj.controller.view.lib_menu.disabled = true;
761                 }
762                 obj.controller.render();
763                 obj.retrieve();
764
765                 obj.controller.view.cmd_retrieve_patron.setAttribute('disabled','true');
766                 obj.controller.view.cmd_holds_edit_pickup_lib.setAttribute('disabled','true');
767                 obj.controller.view.cmd_holds_edit_phone_notify.setAttribute('disabled','true');
768                 obj.controller.view.cmd_holds_edit_email_notify.setAttribute('disabled','true');
769                 obj.controller.view.cmd_holds_edit_selection_depth.setAttribute('disabled','true');
770                 obj.controller.view.cmd_show_notifications.setAttribute('disabled','true');
771                 obj.controller.view.cmd_holds_retarget.setAttribute('disabled','true');
772                 obj.controller.view.cmd_holds_cancel.setAttribute('disabled','true');
773                 obj.controller.view.cmd_show_catalog.setAttribute('disabled','true');
774             }, 0
775         );
776         },
777
778     'determine_hold_interface_type' : function() {
779                 var obj = this;
780         if (obj.patron_id) { /*************************************************** PATRON ******************************/
781             obj.hold_interface_type = 'patron';
782                 } else if (obj.docid) { /*************************************************** RECORD ******************************/
783             obj.hold_interface_type = 'record';
784                 } else if (obj.pull) { /*************************************************** PULL ******************************/
785             obj.hold_interface_type = 'pull';
786                 } else if (obj.shelf) { /*************************************************** HOLD SHELF ******************************/
787             obj.hold_interface_type = 'shelf';
788                 } else { /*************************************************** PULL ******************************/
789             obj.hold_interface_type = 'pull';
790                 }
791     },
792
793     'clear_and_retrieve' : function(dont_show_me_the_list_change) {
794         this.list.clear();
795         this.pull_from_shelf_interface.current.offset = this.pull_from_shelf_interface.default.offset;
796         this.retrieve(dont_show_me_the_list_change);
797     },
798
799         'retrieve' : function(dont_show_me_the_list_change) {
800                 var obj = this; var holds = [];
801                 if (window.xulG && window.xulG.holds) {
802                         holds = window.xulG.holds;
803                 } else {
804                         var method; var params = [ ses() ];
805             switch(obj.hold_interface_type) {
806                 case 'patron' :
807                                     method = 'FM_AHR_ID_LIST_RETRIEVE_VIA_AU'; 
808                                 params.push( obj.patron_id ); 
809                                 obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','true');
810                 break;
811                 case 'record' :
812                                     method = 'FM_AHR_RETRIEVE_ALL_VIA_BRE'; 
813                                 params.push( obj.docid ); 
814                     var x_lib_filter = document.getElementById('lib_filter_checkbox');
815                     var x_lib_type_menu = document.getElementById('lib_type_menu');
816                     if (x_lib_filter) {
817                         if (x_lib_filter.checked) {
818                             if (x_lib_type_menu && obj.controller.view.lib_menu) {
819                                 var x = {};
820                                 x[ x_lib_type_menu.value ] = obj.controller.view.lib_menu.value;
821                                 params.push( x );
822                             } else { alert('3'); }
823                         } else { alert('2'); }
824                     } else { alert('1'); }
825                                 obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
826                 break;
827                 case 'shelf' : 
828                                     method = 'FM_AHR_ID_LIST_ONSHELF_RETRIEVE';
829                     params.push( obj.filter_lib || obj.data.list.au[0].ws_ou() ); 
830                                 obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
831                 break;
832                 case 'pull' : 
833                 default:
834                                     method = 'FM_AHR_ID_LIST_PULL_LIST'; 
835                                 params.push( obj.pull_from_shelf_interface.current.limit ); params.push( obj.pull_from_shelf_interface.current.offset );
836                                     //obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
837                 break;
838                         }
839                         var robj = obj.network.simple_request( method, params );
840                         if (typeof robj.ilsevent != 'undefined') throw(robj);
841                         if (method == 'FM_AHR_RETRIEVE_ALL_VIA_BRE') {
842                                 holds = [];
843                                 holds = holds.concat( robj.copy_holds );
844                                 holds = holds.concat( robj.volume_holds );
845                                 holds = holds.concat( robj.title_holds );
846                                 holds = holds.sort();
847                         } else {
848                                 holds = robj;
849                         }
850                         //alert('method = ' + method + ' params = ' + js2JSON(params));
851                 }
852
853         var x_fetch_more = document.getElementById('fetch_more');
854         if (holds.length == 0) {
855             if (x_fetch_more) x_fetch_more.disabled = true;
856         } else {
857             if (x_fetch_more) x_fetch_more.disabled = false;
858             obj.render(holds,dont_show_me_the_list_change);
859         }
860
861     },
862
863     'render' : function(holds,dont_show_me_the_list_change) {
864         var obj = this;
865
866                 function list_append(hold_id) {
867                         obj.list.append(
868                                 {
869                                         'row' : {
870                                                 'my' : {
871                                                         'hold_id' : hold_id,
872                                                 }
873                                         }
874                                 }
875                         );
876                 }
877
878                 function gen_list_append(hold) {
879                         return function() {
880                                 if (typeof obj.controller.view.lib_menu == 'undefined') {
881                                         list_append(typeof hold == 'object' ? hold.id() : hold);
882                                 } else {
883                                         list_append(typeof hold == 'object' ? hold.id() : hold);
884                                 }
885                         };
886                 }
887
888                 //obj.list.clear();
889
890                 JSAN.use('util.exec'); var exec = new util.exec(2);
891                 var rows = [];
892                 for (var i in holds) {
893                         rows.push( gen_list_append(holds[i]) );
894                 }
895                 exec.chain( rows );
896         
897                 if (!dont_show_me_the_list_change) {
898                         if (window.xulG && typeof window.xulG.on_list_change == 'function') {
899                                 try { window.xulG.on_list_change(holds); } catch(E) { this.error.sdump('D_ERROR',E); }
900                         }
901                 }
902         },
903
904         'render_lib_menus' : function(types) {
905                 try {
906                         var obj = this;
907                         JSAN.use('util.widgets'); JSAN.use('util.functional'); JSAN.use('util.fm_utils');
908
909             var x = document.getElementById('lib_type_menu');
910             if (types) {
911                 var nodes = x.firstChild.childNodes;
912                 for (var i = 0; i < nodes.length; i++) nodes[i].hidden = true;
913                 for (var i in types) document.getElementById(i).hidden = false;
914             }
915             x.setAttribute('oncommand','g.holds.clear_and_retrieve()');
916
917                         x = document.getElementById('lib_menu_placeholder');
918                         util.widgets.remove_children( x );
919
920             JSAN.use('util.file');
921                         var file = new util.file('offline_ou_list'); 
922                         if (file._file.exists()) {
923                                 var list_data = file.get_object(); file.close();
924                                 var ml = util.widgets.make_menulist( list_data[0], obj.data.list.au[0].ws_ou() );
925                 ml.setAttribute('id','lib_menu');
926                 x.appendChild( ml );
927                         ml.addEventListener(
928                                 'command',
929                                 function(ev) {
930                                         obj.filter_lib = ev.target.value;
931                                         obj.clear_and_retrieve();
932                                 },
933                                 false
934                         );
935                         obj.controller.view.lib_menu = ml;
936                         } else {
937                                 throw('Missing library list.\n');
938                         }
939
940                 } catch(E) {
941                         this.error.standard_unexpected_error_alert('rendering lib menu',E);
942                 }
943         },
944 }
945
946 dump('exiting patron.holds.js\n');