97cc07ccc101526c228d911dc44c5675c2d4c930
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / serial / manage_subs.js
1 dump('entering serial/manage_subs.js\n');
2 // vim:noet:sw=4:ts=4:
3
4 if (typeof serial == 'undefined') serial = {};
5 serial.manage_subs = function (params) {
6     try {
7         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
8         JSAN.use('util.error'); this.error = new util.error();
9     } catch(E) {
10         dump('serial/manage_subs: ' + E + '\n');
11     }
12 };
13
14 serial.manage_subs.prototype = {
15
16     'map_tree' : {},
17     'map_ssub' : {},
18     'map_sdist' : {},
19     'map_siss' : {},
20     'map_scap' : {},
21     'sel_list' : [],
22     'funcs' : [],
23     'editor_indexes' : { 'ssub' : 1, 'sdist' : 2, 'siss' : 3, 'scap' : 4 },
24
25     'ids_from_sel_list' : function(type) {
26         var obj = this;
27         JSAN.use('util.functional');
28
29         var list = util.functional.map_list(
30             util.functional.filter_list(
31                 obj.sel_list,
32                 function (o) {
33                     return o.split(/_/)[0] == type;
34                 }
35             ),
36             function (o) {
37                 return o.split(/_/)[1];
38             }
39         );
40
41         return list;
42     },
43
44     'editor_init' : function(type, mode, params) {
45         var obj = this;
46         try {
47             $('serial_manage_subs_editor_deck').selectedIndex = obj.editor_indexes[type];
48             var editor_type = type + '_editor';
49             if (typeof obj[editor_type] == 'undefined') {
50                 JSAN.use('serial.' + editor_type);
51                 obj[editor_type] = new serial[editor_type](); 
52             }
53
54             params.do_edit = true;
55             params.handle_update = true;
56             if (mode == 'add') {
57                 params.trigger_refresh = true;
58                 params.refresh_command = function () {obj.refresh_list();};
59             }
60             obj[editor_type].init(params);
61         } catch(E) {
62             obj.error.standard_unexpected_error_alert('editor_init() error',E);
63         }
64     },
65
66     'do_delete' : function(type, method, overridable_events) {
67         var obj = this;
68         try {
69             JSAN.use('util.functional');
70
71             var list = util.functional.filter_list(
72                 obj.sel_list,
73                 function (o) {
74                     return o.split(/_/)[0] == type;
75                 }
76             );
77
78             list = util.functional.map_list(
79                 list,
80                 function (o) {
81                     return JSON2js( js2JSON( obj['map_' + type][ type + '_' + o.split(/_/)[1] ] ) );
82                 }
83             );
84
85             //TODO: proper messages
86             var delete_msg;
87             if (list.length != 1) {
88                 delete_msg = document.getElementById('serialStrings').getFormattedString('staff.serial.manage_subs.delete_' + type + '.confirm.plural', [list.length]);
89             } else {
90                 delete_msg = document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete_' + type + '.confirm');
91             }
92             var r = obj.error.yns_alert(
93                     delete_msg,
94                     document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete_' + type + '.title'),
95                     document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.delete'),
96                     document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.cancel'),
97                     null,
98                     document.getElementById('commonStrings').getString('common.confirm')
99             );
100
101             if (r == 0) {
102                 for (var i = 0; i < list.length; i++) {
103                     list[i].isdeleted('1');
104                 }
105                 var robj = obj.network.request(
106                     'open-ils.serial', 
107                     method, 
108                     [ ses(), list, true ],
109                     null,
110                     {
111                         'title' : document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete_' + type + '.override'),
112                         'overridable_events' : overridable_events
113                     }
114                 );
115                 if (robj == null) throw(robj);
116                 if (typeof robj.ilsevent != 'undefined') {
117                     if (robj.ilsevent != 0) {
118                         var overridable = false;
119                         for (i = 0; i < overridable_events.length; i++) {
120                             if (overridable_events[i] == robj.ilsevent) {
121                                 overridable = true;
122                                 break;
123                             }
124                         }
125                         if (!overridable) throw(robj);
126                     }
127                 }
128                 obj.refresh_list();
129             }
130         } catch(E) {
131             obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete.error'),E);
132             obj.refresh_list();
133         }
134     },
135
136     'init' : function( params ) {
137
138         try {
139             netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
140             var obj = this;
141
142             obj.docid = params.docid;
143
144             JSAN.use('util.network'); obj.network = new util.network();
145             JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
146             JSAN.use('util.controller'); obj.controller = new util.controller();
147             obj.controller.init(
148                 {
149                     control_map : {
150                         'save_columns' : [ [ 'command' ], function() { obj.list.save_columns(); } ],
151                         'sel_clip' : [
152                             ['command'],
153                             function() { obj.list.clipboard(); }
154                         ],
155                         'cmd_broken' : [
156                             ['command'],
157                             function() { 
158                                 alert(document.getElementById('commonStrings').getString('common.unimplemented'));
159                             }
160                         ],
161                         'cmd_show_my_libs' : [
162                             ['command'],
163                             function() { 
164                                 obj.show_my_libs(); 
165                             }
166                         ],
167                         'cmd_show_all_libs' : [
168                             ['command'],
169                             function() {
170                                 obj.show_all_libs();
171                             }
172                         ],
173                         'cmd_show_libs_with_distributions' : [
174                             ['command'],
175                             function() {
176                                 obj.show_libs_with_distributions();
177                             }
178                         ],
179                         'cmd_clear' : [
180                             ['command'],
181                             function() {
182                                 obj.map_tree = {};
183                                 obj.list.clear();
184                             }
185                         ],
186                         'cmd_add_scap' : [
187                             ['command'],
188                             function() {
189                                 try {
190                                     var list = obj.ids_from_sel_list('ssub');
191                                     if (list.length == 0) list = obj.ids_from_sel_list('scap-group');
192                                     if (list.length == 0) return;
193
194                                     /*TODO: permission check?
195                                     //populate 'list' with owning_libs of subs, TODO
196                                     var edit = 0;
197                                     try {
198                                         edit = obj.network.request(
199                                             api.PERM_MULTI_ORG_CHECK.app,
200                                             api.PERM_MULTI_ORG_CHECK.method,
201                                             [ 
202                                                 ses(), 
203                                                 obj.data.list.au[0].id(), 
204                                                 list,
205                                                 [ 'CREATE_COPY' ]
206                                             ]
207                                         ).length == 0 ? 1 : 0;
208                                     } catch(E) {
209                                         obj.error.sdump('D_ERROR','batch permission check: ' + E);
210                                     }
211
212                                     if (edit==0) return; // no read-only view for this interface */
213                                     var new_scap = new scap();
214                                     new_scap.subscription(list[0]);//TODO: add multiple at once support?
215                                     new_scap.isnew(1);
216                                     var params = {};
217                                     params.scaps = [new_scap];
218                                     obj.editor_init('scap', 'add', params);
219                                 } catch(E) {
220                                     obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
221                                 }
222                             }
223                         ],
224                         'cmd_add_siss' : [
225                             ['command'],
226                             function() {
227                                 try {
228                                     var list = obj.ids_from_sel_list('ssub');
229                                     if (list.length == 0) list = obj.ids_from_sel_list('siss-group');
230                                     if (list.length == 0) return;
231
232                                     /*TODO: permission check?
233                                     //populate 'list' with owning_libs of subs, TODO
234                                     var edit = 0;
235                                     try {
236                                         edit = obj.network.request(
237                                             api.PERM_MULTI_ORG_CHECK.app,
238                                             api.PERM_MULTI_ORG_CHECK.method,
239                                             [ 
240                                                 ses(), 
241                                                 obj.data.list.au[0].id(), 
242                                                 list,
243                                                 [ 'CREATE_COPY' ]
244                                             ]
245                                         ).length == 0 ? 1 : 0;
246                                     } catch(E) {
247                                         obj.error.sdump('D_ERROR','batch permission check: ' + E);
248                                     }
249
250                                     if (edit==0) return; // no read-only view for this interface */
251                                     var new_siss = new siss();
252                                     new_siss.subscription(list[0]);//TODO: add multiple at once support?
253                                     new_siss.isnew(1);
254                                     var params = {};
255                                     params.sisses = [new_siss];
256                                     obj.editor_init('siss', 'add', params);
257                                 } catch(E) {
258                                     obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
259                                 }
260                             }
261                         ],
262                         'cmd_add_sdist' : [
263                             ['command'],
264                             function() {
265                                 try {
266                                     var list = obj.ids_from_sel_list('ssub');
267                                     if (list.length == 0) list = obj.ids_from_sel_list('sdist-group');
268                                     if (list.length == 0) return;
269
270                                     /*TODO: permission check?
271                                     //populate 'list' with owning_libs of subs, TODO
272                                     var edit = 0;
273                                     try {
274                                         edit = obj.network.request(
275                                             api.PERM_MULTI_ORG_CHECK.app,
276                                             api.PERM_MULTI_ORG_CHECK.method,
277                                             [ 
278                                                 ses(), 
279                                                 obj.data.list.au[0].id(), 
280                                                 list,
281                                                 [ 'CREATE_COPY' ]
282                                             ]
283                                         ).length == 0 ? 1 : 0;
284                                     } catch(E) {
285                                         obj.error.sdump('D_ERROR','batch permission check: ' + E);
286                                     }
287
288                                     if (edit==0) return; // no read-only view for this interface */
289                                     var new_sdist = new sdist();
290                                     new_sdist.subscription(list[0]);//TODO: add multiple at once support?
291                                     new_sdist.holding_lib(obj.map_ssub['ssub_' + list[0]].owning_lib());//default to sub owning lib
292                                     new_sdist.label('Default');
293                                     new_sdist.isnew(1);
294                                     var params = {};
295                                     params.sdists = [new_sdist];
296                                     obj.editor_init('sdist', 'add', params);
297                                 } catch(E) {
298                                     obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
299                                 }
300                             }
301                         ],
302                         'cmd_delete_scap' : [
303                             ['command'],
304                             function() {
305                                 var overridable_events = [
306                                     11001 // SERIAL_CAPTION_AND_PATTERN_HAS_ISSUANCES
307                                 ];
308                                 obj.do_delete('scap', 'open-ils.serial.caption_and_pattern.batch.update', overridable_events);
309                             }
310                         ],
311                         'cmd_delete_sdist' : [
312                             ['command'],
313                             function() {
314                                 var overridable_events = [ //TODO: proper overrides
315                                 ];
316                                 obj.do_delete('sdist', 'open-ils.serial.distribution.fleshed.batch.update', overridable_events);
317                             }
318                         ],
319                         'cmd_delete_siss' : [
320                             ['command'],
321                             function() {
322                                 var overridable_events = [ //TODO: proper overrides
323                                 ];
324                                 obj.do_delete('siss', 'open-ils.serial.issuance.fleshed.batch.update', overridable_events);
325                             }
326                         ],
327                         'cmd_delete_ssub' : [
328                             ['command'],
329                             function() {
330                                 var overridable_events = [
331                                     11000 // SERIAL_SUBSCRIPTION_NOT_EMPTY
332                                 ];
333                                 obj.do_delete('ssub', 'open-ils.serial.subscription.fleshed.batch.update', overridable_events);
334                             }
335                         ],
336                         /*dbw2 'cmd_delete_ssub' : [
337                             ['command'],
338                             function() {
339                                 try {
340                                     JSAN.use('util.functional');
341
342                                     var list = util.functional.filter_list(
343                                         obj.sel_list,
344                                         function (o) {
345                                             return o.split(/_/)[0] == 'ssub';
346                                         }
347                                     );
348
349                                     list = util.functional.map_list(
350                                         list,
351                                         function (o) {
352                                             return JSON2js( js2JSON( obj.map_ssub[ 'ssub_' + o.split(/_/)[1] ] ) );
353                                         }
354                                     );
355
356                                     var del_prompt;
357                                     if (list.length == 1) {
358                                         //TODO: correct prompts
359                                         del_prompt = document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.prompt');
360                                     } else {
361                                         del_prompt = document.getElementById('catStrings').getFormattedString('staff.cat.copy_browser.delete_volume.prompt.plural', [list.length]);
362                                     }
363
364                                     var r = obj.error.yns_alert(
365                                             del_prompt,
366                                             document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.title'),
367                                             document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.delete'),
368                                             document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.cancel'),
369                                             null,
370                                             document.getElementById('commonStrings').getString('common.confirm')
371                                     );
372
373                                     if (r == 0) {
374                                         for (var i = 0; i < list.length; i++) {
375                                             list[i].isdeleted('1');
376                                         }
377                                         var robj = obj.network.simple_request(
378                                             'FM_ACN_TREE_UPDATE', 
379                                             [ ses(), list, true ],
380                                             null,
381                                             {
382                                                 'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.override'),
383                                                 'overridable_events' : [
384                                                 ]
385                                             }
386                                         );
387                                         if (robj == null) throw(robj);
388                                         if (typeof robj.ilsevent != 'undefined') {
389                                             if (robj.ilsevent == 1206 ) { // VOLUME_NOT_EMPTY
390                                                 alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.copies_remain'));
391                                                 return;
392                                             }
393                                             if (robj.ilsevent != 0) throw(robj);
394                                         }
395                                         alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.success'));
396                                         obj.refresh_list();
397                                     }
398                                 } catch(E) {
399                                     obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.exception'),E);
400                                     obj.refresh_list();
401                                 }
402
403                             }
404                         ], dbw2*/
405                         'cmd_mark_library' : [
406                             ['command'],
407                             function() {
408                                 try {
409                                     var list = obj.ids_from_sel_list('aou');
410                                     if (list.length == 1) {
411                                         obj.data.marked_library = { 'lib' : list[0], 'docid' : obj.docid };
412                                         obj.data.stash('marked_library');
413                                         alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_library.alert'));
414                                     } else {
415                                         obj.error.yns_alert(
416                                                 document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_library.prompt'),
417                                                 document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_library.title'),
418                                                 document.getElementById('commonStrings').getString('common.ok'),
419                                                 null,
420                                                 null,
421                                                 document.getElementById('commonStrings').getString('common.confirm')
422                                                 );
423                                     }
424                                 } catch(E) {
425                                     obj.error.standard_unexpected_error_alert('manage_subs.js -> mark library',E);
426                                 }
427                             }
428                         ],
429
430                         'cmd_mark_subscription' : [
431                             ['command'],
432                             function() {
433                                 try {
434                                     var list = obj.ids_from_sel_list('ssub');
435                                     if (list.length == 1) {
436                                         obj.data.marked_subscription = list[0];
437                                         obj.data.stash('marked_subscription');
438                                         alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_volume.alert'));
439                                     } else {
440                                         obj.error.yns_alert(
441                                                 document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_volume.prompt'),
442                                                 document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_volume.title'),
443                                                 document.getElementById('commonStrings').getString('common.ok'),
444                                                 null,
445                                                 null,
446                                                 document.getElementById('commonStrings').getString('common.confirm')
447                                                 );
448                                     }
449                                 } catch(E) {
450                                     obj.error.standard_unexpected_error_alert('manage_subs.js -> mark subscription',E);
451                                 }
452                             }
453                         ],
454                         'cmd_add_subscriptions' : [
455                             ['command'],
456                             function() {
457                                 try {
458                                     var list = obj.ids_from_sel_list('aou');
459                                     if (list.length == 0) return;
460                                     //TODO: permission check?
461                                     /*var edit = 0;
462                                     try {
463                                         edit = obj.network.request(
464                                             api.PERM_MULTI_ORG_CHECK.app,
465                                             api.PERM_MULTI_ORG_CHECK.method,
466                                             [ 
467                                                 ses(), 
468                                                 obj.data.list.au[0].id(), 
469                                                 list,
470                                                 [ 'CREATE_VOLUME', 'CREATE_COPY' ]
471                                             ]
472                                         ).length == 0 ? 1 : 0;
473                                     } catch(E) {
474                                         obj.error.sdump('D_ERROR','batch permission check: ' + E);
475                                     }
476
477                                     if (edit==0) {
478                                         alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.add_volume.permission_error'));
479                                         return; // no read-only view for this interface
480                                     } */
481                                     var new_ssub = new ssub();
482                                     new_ssub.owning_lib(list[0]);//TODO: add multiple at once support?
483                                     new_ssub.isnew(1);
484                                     new_ssub.record_entry(obj.docid);
485                                     var params = {};
486                                     params.ssubs = [new_ssub];
487                                     obj.editor_init('ssub', 'add', params);
488                                 } catch(E) {
489                                     obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
490                                 }
491                             }
492                         ],
493                         'cmd_transfer_subscription' : [
494                             ['command'],
495                             function() {
496                                 try {
497                                     obj.data.stash_retrieve();
498                                     if (!obj.data.marked_library) {
499                                         alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer_volume.alert'));
500                                         return;
501                                     }
502                                     
503                                     var list = obj.ids_from_sel_list('ssub');
504
505                                     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
506
507                                     JSAN.use('util.functional');
508
509                                     var ssub_list = util.functional.map_list(
510                                         list,
511                                         function (o) {
512                                             return obj.map_ssub[ 'ssub_' + o ].start_date();
513                                         }
514                                     ).join(document.getElementById('commonStrings').getString('common.grouping_string'));
515
516                                     var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: auto">';
517                                     xml += '<description>';
518                                     xml += document.getElementById('catStrings').getFormattedString('staff.cat.copy_browser.transfer.prompt', [ssub_list, obj.data.hash.aou[ obj.data.marked_library.lib ].shortname()]);
519                                     xml += '</description>';
520                                     xml += '<hbox><button label="' + document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.submit.label') + '" name="fancy_submit"/>';
521                                     xml += '<button label="' 
522                                         + document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.cancel.label') 
523                                         + '" accesskey="' 
524                                         + document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.cancel.accesskey') 
525                                         + '" name="fancy_cancel"/></hbox>';
526                                     xml += '<iframe style="overflow: scroll" flex="1" src="' + urls.XUL_BIB_BRIEF + '?docid=' + obj.data.marked_library.docid + '"/>';
527                                     xml += '</vbox>';
528                                     JSAN.use('OpenILS.data');
529                                     var data = new OpenILS.data(); data.init({'via':'stash'});
530                                     //data.temp_transfer = xml; data.stash('temp_transfer');
531                                     JSAN.use('util.window'); var win = new util.window();
532                                     var fancy_prompt_data = win.open(
533                                         urls.XUL_FANCY_PROMPT,
534                                         //+ '?xml_in_stash=temp_transfer'
535                                         //+ '&title=' + window.escape('Volume Transfer'),
536                                         'fancy_prompt', 'chrome,resizable,modal,width=500,height=300',
537                                         {
538                                             'xml' : xml,
539                                             'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.title')
540                                         }
541                                     );
542
543                                     if (fancy_prompt_data.fancy_status == 'incomplete') {
544                                         alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.incomplete'));
545                                         return;
546                                     }
547
548                                     var robj = obj.network.simple_request(
549                                         'FM_ACN_TRANSFER', 
550                                         [ ses(), { 'docid' : obj.data.marked_library.docid, 'lib' : obj.data.marked_library.lib, 'subscriptions' : list } ],
551                                         null,
552                                         {
553                                             'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.override.failure'),
554                                             'overridable_events' : [
555                                                 1208, // TITLE_LAST_COPY
556                                                 1219, // COPY_REMOTE_CIRC_LIB
557                                             ],
558                                         }
559                                     );
560
561                                     if (typeof robj.ilsevent != 'undefined') {
562                                         if (robj.ilsevent == 1221) { // ORG_CANNOT_HAVE_VOLS
563                                             alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.ineligible_destination'));
564                                         } else {
565                                             throw(robj);
566                                         }
567                                     } else {
568                                         alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.success'));
569                                     }
570
571                                 } catch(E) {
572                                     obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.unexpected_error'),E);
573                                 }
574                                 obj.refresh_list();
575                             }
576                         ],
577
578                         'cmd_transfer_sdists' : [
579                             ['command'],
580                             function() {
581                                 try {
582                                     obj.data.stash_retrieve();
583                                     if (!obj.data.marked_subscription) {
584                                         alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer_items.missing_volume'));
585                                         return;
586                                     }
587                                     
588                                     JSAN.use('util.functional');
589
590                                     var list = obj.ids_from_sel_list('sdist');
591                                     var subscription = obj.network.simple_request('FM_ACN_RETRIEVE.authoritative',[ obj.data.marked_subscription ]);
592
593                                     JSAN.use('cat.util'); cat.util.transfer_copies( { 
594                                         'distribution_ids' : list, 
595                                         'docid' : subscription.record(),
596                                         'subscription_label' : subscription.start_date(),
597                                         'owning_lib' : subscription.owning_lib(),
598                                     } );
599
600                                 } catch(E) {
601                                     obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer_items.unexpected_error'),E);
602                                 }
603                                 obj.refresh_list();
604                             }
605                         ],
606                         'cmd_refresh_list' : [
607                             ['command'],
608                             function() {
609                                 obj.refresh_list();
610                             }
611                         ],
612                         'cmd_make_predictions' : [
613                             ['command'],
614                             function() {
615                                 try {
616                                     var list = obj.ids_from_sel_list('ssub');
617                                     if (list.length == 0) {
618                                         alert('You must select a subscription before predicting issuances.'); //TODO: better error
619                                         return;
620                                     }
621
622                                     var num_to_predict = prompt('How many items (per active pattern) would you like to predict?',
623                                             '12',
624                                             'Number of Predicted Items');
625                                     num_to_predict = String( num_to_predict ).replace(/\D/g,'');
626                                     if (num_to_predict == '') {
627                                         alert('Invalid number entered!'); //TODO: better error
628                                         return;
629                                     }
630
631                                     for (i = 0; i < list.length; i++) {
632                                         var robj = obj.network.request(
633                                                 'open-ils.serial',
634                                                 'open-ils.serial.make_predictions',
635                                                 [ ses(), {"ssub_id":list[i], "num_to_predict":num_to_predict}]
636                                         );
637                                         alert('Successfully predicted ' + robj.length + ' issuance(s) for subscription #' + list[i] + '.');
638                                     }
639
640                                     obj.refresh_list();
641
642                                 } catch(E) {
643                                     obj.error.standard_unexpected_error_alert('cmd_make_predictions failed!',E);
644                                 }
645                             }
646                         ],
647 /*dbw2                      'sel_distribution_details' : [
648                             ['command'],
649                             function() {
650                                 JSAN.use('util.functional');
651
652                                 var list = util.functional.filter_list(
653                                     obj.sel_list,
654                                     function (o) {
655                                         return o.split(/_/)[0] == 'sdist';
656                                     }
657                                 );
658
659                                 list = util.functional.map_list(
660                                     list,
661                                     function (o) {
662                                         return o.split(/_/)[1];
663                                     }
664                                 );
665     
666                                 JSAN.use('circ.util');
667                                 for (var i = 0; i < list.length; i++) {
668                                     circ.util.show_copy_details( list[i] );
669                                 }
670                             }
671                         ],
672                         'cmd_edit_sdists' : [
673                             ['command'],
674                             function() {
675                                 try {
676                                     JSAN.use('util.functional');
677
678                                     var list = util.functional.filter_list(
679                                         obj.sel_list,
680                                         function (o) {
681                                             return o.split(/_/)[0] == 'sdist';
682                                         }
683                                     );
684
685                                     list = util.functional.map_list(
686                                         list,
687                                         function (o) {
688                                             return o.split(/_/)[1];
689                                         }
690                                     );
691
692                                     JSAN.use('cat.util'); cat.util.spawn_copy_editor( { 'copy_ids' : list, 'edit' : 1 } );
693                                     obj.refresh_list();
694
695                                 } catch(E) {
696                                     obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_items.error'),E);
697                                 }
698                             }
699                         ], dbw2*/
700
701 /*dbw2                      'cmd_print_spine_labels' : [
702                             ['command'],
703                             function() {
704                                 try {
705                                     JSAN.use('util.functional');
706                                     
707                                     var list = util.functional.filter_list(
708                                         obj.sel_list,
709                                         function (o) {
710                                             return o.split(/_/)[0] == 'sdist';
711                                         }
712                                     );
713
714                                     list = util.functional.map_list(
715                                         list,
716                                         function (o) {
717                                             return obj.map_sdist[ o ];
718                                         }
719                                     );
720
721                                     obj.data.temp_barcodes_for_labels = util.functional.map_list( list, function(o){return o.barcode();}) ; 
722                                     obj.data.stash('temp_barcodes_for_labels');
723                                     xulG.new_tab(
724                                         xulG.url_prefix( urls.XUL_SPINE_LABEL ),
725                                         { 'tab_name' : document.getElementById('catStrings').getString('staff.cat.copy_browser.print_spine.tab') },
726                                         {}
727                                     );
728                                 } catch(E) {
729                                     obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.print_spine.error'),E);
730                                 }
731                             }
732                         ],
733                         'cmd_edit_subscriptions' : [
734                             ['command'],
735                             function() {
736                                 try {
737                                     JSAN.use('util.functional');
738                                     var list = util.functional.map_list(
739                                         util.functional.filter_list(
740                                             obj.sel_list,
741                                             function (o) {
742                                                 return o.split(/_/)[0] == 'ssub';
743                                             }
744                                         ),
745                                         function (o) {
746                                             return o.split(/_/)[1];
747                                         }
748                                     );
749                                     if (list.length == 0) return;
750
751                                     var edit = 0;
752                                     try {
753                                         edit = obj.network.request(
754                                             api.PERM_MULTI_ORG_CHECK.app,
755                                             api.PERM_MULTI_ORG_CHECK.method,
756                                             [ 
757                                                 ses(), 
758                                                 obj.data.list.au[0].id(), 
759                                                 util.functional.map_list(
760                                                     list,
761                                                     function (o) {
762                                                         return obj.map_ssub[ 'ssub_' + o ].owning_lib();
763                                                     }
764                                                 ),
765                                                 [ 'UPDATE_VOLUME' ]
766                                             ]
767                                         ).length == 0 ? 1 : 0;
768                                     } catch(E) {
769                                         obj.error.sdump('D_ERROR','batch permission check: ' + E);
770                                     }
771
772                                     if (edit==0) {
773                                         alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.permission_error'));
774                                         return; // no read-only view for this interface
775                                     }
776
777                                     list = util.functional.map_list(
778                                         list,
779                                         function (o) {
780                                             var my_ssub = obj.map_ssub['ssub_' + o];
781                                             return function(r){return r;}(my_ssub);
782                                         }
783                                     );
784
785                                     var title;
786                                     if (list.length == 1) {
787                                         title = document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.title');
788                                     } else {
789                                         title = document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.title.plural');
790                                     }
791
792                                     JSAN.use('util.window'); var win = new util.window();
793                                     //obj.data.volumes_temp = js2JSON( list );
794                                     //obj.data.stash('volumes_temp');
795                                     var my_xulG = win.open(
796                                         window.xulG.url_prefix(urls.XUL_VOLUME_EDITOR),
797                                         title,
798                                         'chrome,modal,resizable',
799                                         { 'subscriptions' : JSON2js(js2JSON(list)) }
800                                     );
801
802                                     // FIXME -- need to unique the temp space, and not rely on modalness of window
803                                     //obj.data.stash_retrieve();
804                                     if (typeof my_xulG.update_these_subscriptions == 'undefined') { return; }
805                                     var subscriptions = my_xulG.subscriptions;
806                                     if (!subscriptions) return;
807                                 
808                                     subscriptions = util.functional.filter_list(
809                                         subscriptions,
810                                         function (o) {
811                                             return o.ischanged() == '1';
812                                         }
813                                     );
814
815                                     subscriptions = util.functional.map_list(
816                                         subscriptions,
817                                         function (o) {
818                                             o.record( obj.docid ); // staff client 2 did not do this.  Does it matter?
819                                             return o;
820                                         }
821                                     );
822
823                                     if (subscriptions.length == 0) return;
824
825                                     try {
826                                         var r = obj.network.request(
827                                             api.FM_ACN_TREE_UPDATE.app,
828                                             api.FM_ACN_TREE_UPDATE.method,
829                                             [ ses(), subscriptions, true ]
830                                         );
831                                         if (typeof r.ilsevent != 'undefined') {
832                                             switch(Number(r.ilsevent)) {
833                                                 case 1705 : // VOLUME_LABEL_EXISTS
834                                                     alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.failed'));
835                                                     break;
836                                                 default: throw(r);
837                                             }
838                                         } else {
839                                             alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.success'));
840                                         }
841                                     } catch(E) {
842                                         obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.error'),E);
843                                     }
844                                     obj.refresh_list();
845
846                                 } catch(E) {
847                                     obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.exception'),E);
848                                 }
849                             }
850                         ], dbw2*/
851                     }
852                 }
853             );
854
855             obj.list_init(params);
856
857             obj.org_ids = obj.network.simple_request('FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
858             if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
859             JSAN.use('util.functional'); 
860             obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
861
862             var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
863             //obj.show_libs( org );
864
865             //obj.show_my_libs();
866
867             JSAN.use('util.file'); JSAN.use('util.widgets');
868
869             var file; var list_data; var ml; 
870
871             file = new util.file('offline_ou_list'); 
872             if (file._file.exists()) {
873                 list_data = file.get_object(); file.close();
874                 ml = util.widgets.make_menulist( list_data[0], list_data[1] );
875                 ml.setAttribute('id','lib_menu'); document.getElementById('serial_sub_lib_menu').appendChild(ml);
876                 //TODO: class this menu properly
877                 for (var i = 0; i < obj.org_ids.length; i++) {
878                     ml.getElementsByAttribute('value',obj.org_ids[i])[0].setAttribute('class','has_distributions');
879                 }
880                 ml.firstChild.addEventListener(
881                     'popupshown',
882                     function(ev) {
883                         document.getElementById('legend').setAttribute('hidden','false');
884                     },
885                     false
886                 );
887                 ml.firstChild.addEventListener(
888                     'popuphidden',
889                     function(ev) {
890                         document.getElementById('legend').setAttribute('hidden','true');
891                     },
892                     false
893                 );
894                 ml.addEventListener(
895                     'command',
896                     function(ev) {
897                         if (document.getElementById('refresh_button')) document.getElementById('refresh_button').focus(); 
898                         JSAN.use('util.file'); var file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
899                         util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_ssubs' : [ 'checked' ], 'show_groups' : [ 'checked' ] });
900                         obj.refresh_list();
901                     },
902                     false
903                 );
904             } else {
905                 throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n');
906             }
907
908             file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
909             util.widgets.load_attributes(file);
910             ml.value = ml.getAttribute('value');
911             if (! ml.value) {
912                 ml.value = org.id();
913                 ml.setAttribute('value',ml.value);
914             }
915
916             document.getElementById('show_ssubs').addEventListener(
917                 'command',
918                 function(ev) {
919                     JSAN.use('util.file'); var file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
920                     util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_ssubs' : [ 'checked' ], 'show_groups' : [ 'checked' ] });
921                 },
922                 false
923             );
924
925             document.getElementById('show_groups').addEventListener(
926                 'command',
927                 function(ev) {
928                     JSAN.use('util.file'); var file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
929                     util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_ssubs' : [ 'checked' ], 'show_groups' : [ 'checked' ] });
930                 },
931                 false
932             );
933
934             obj.show_my_libs( ml.value );
935
936             JSAN.use('util.exec'); var exec = new util.exec(20); exec.timer(obj.funcs,100);
937
938             obj.toggle_actions(); // disable menus initially
939
940         } catch(E) {
941             this.error.standard_unexpected_error_alert('serial/manage_subs.init: ',E);
942         }
943     },
944
945     'show_my_libs' : function(org) {
946         var obj = this;
947         try {
948             if (!org) {
949                 org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
950             } else {
951                 if (typeof org != 'object') org = obj.data.hash.aou[ org ];
952             }
953             obj.show_libs( org, false );
954         
955             var p_org = obj.data.hash.aou[ org.parent_ou() ];
956             if (p_org) {
957                 obj.funcs.push( function() { 
958                     document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
959                     document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
960                     document.getElementById('lib_menu').setAttribute('disabled','true'); 
961                 } );
962                 for (var i = 0; i < p_org.children().length; i++) {
963                     obj.funcs.push(
964                         function(o) {
965                             return function() {
966                                 obj.show_libs( o, false );
967                             }
968                         }( p_org.children()[i] )
969                     );
970                 }
971                 obj.funcs.push( function() { 
972                     document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
973                     document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
974                     document.getElementById('lib_menu').setAttribute('disabled','false'); 
975                 } );
976             }
977         } catch(E) {
978             alert(E);
979         }
980     },
981
982     'show_all_libs' : function() {
983         var obj = this;
984         try {
985             obj.show_my_libs();
986
987             obj.show_libs( obj.data.tree.aou );
988
989             obj.funcs.push( function() { 
990                 document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
991                 document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
992                 document.getElementById('lib_menu').setAttribute('disabled','true'); 
993             } );
994
995             for (var i = 0; i < obj.data.tree.aou.children().length; i++) {
996                 obj.funcs.push(
997                     function(o) {
998                         return function() {
999                             obj.show_libs( o );
1000                         }
1001                     }( obj.data.tree.aou.children()[i] )
1002                 );
1003             }
1004             obj.funcs.push( function() { 
1005                 document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
1006                 document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
1007                 document.getElementById('lib_menu').setAttribute('disabled','false'); 
1008             } );
1009
1010         } catch(E) {
1011             alert(E);
1012         }
1013     },
1014
1015     'show_libs_with_distributions' : function() {
1016         var obj = this;
1017         try {
1018             JSAN.use('util.functional');
1019
1020             var orgs = util.functional.map_list(
1021                 obj.org_ids,
1022                 function(id) { return obj.data.hash.aou[id]; }
1023             ).sort(
1024                 function( a, b ) {
1025                     if (a.shortname() < b.shortname()) return -1;
1026                     if (a.shortname() > b.shortname()) return 1;
1027                     return 0;
1028                 }
1029             );
1030             obj.funcs.push( function() { 
1031                 document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
1032                 document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
1033                 document.getElementById('lib_menu').setAttribute('disabled','true'); 
1034             } );
1035
1036             for (var i = 0; i < orgs.length; i++) {
1037                 obj.funcs.push(
1038                     function(o) {
1039                         return function() {
1040                             obj.show_libs(o,false);
1041                         }
1042                     }( orgs[i] )
1043                 );
1044             }
1045             obj.funcs.push( function() { 
1046                 document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
1047                 document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
1048                 document.getElementById('lib_menu').setAttribute('disabled','false'); 
1049             } );
1050
1051         } catch(E) {
1052             alert(E);
1053         }
1054     },
1055
1056     'show_libs' : function(start_aou,show_open) {
1057         var obj = this;
1058         try {
1059             if (!start_aou) throw('show_libs: Need a start_aou');
1060             JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
1061             JSAN.use('util.functional'); 
1062
1063             var parents = [];
1064             var temp_aou = start_aou;
1065             while ( temp_aou.parent_ou() ) {
1066                 temp_aou = obj.data.hash.aou[ temp_aou.parent_ou() ];
1067                 parents.push( temp_aou );
1068             }
1069             parents.reverse();
1070
1071             for (var i = 0; i < parents.length; i++) {
1072                 obj.funcs.push(
1073                     function(o,p) {
1074                         return function() { 
1075                             obj.append_org(o,p,{'container':'true','open':'true'}); 
1076                         };
1077                     }(parents[i], obj.data.hash.aou[ parents[i].parent_ou() ])
1078                 );
1079             }
1080
1081             obj.funcs.push(
1082                 function(o,p) {
1083                     return function() { obj.append_org(o,p); };
1084                 }(start_aou,obj.data.hash.aou[ start_aou.parent_ou() ])
1085             );
1086
1087             obj.funcs.push(
1088                 function() {
1089                     if (start_aou.children()) {
1090                         var x = obj.map_tree[ 'aou_' + start_aou.id() ];
1091                         x.setAttribute('container','true');
1092                         if (show_open) x.setAttribute('open','true');
1093                         for (var i = 0; i < start_aou.children().length; i++) {
1094                             obj.funcs.push(
1095                                 function(o,p) {
1096                                     return function() { obj.append_org(o,p); };
1097                                 }( start_aou.children()[i], start_aou )
1098                             );
1099                         }
1100                     }
1101                 }
1102             );
1103
1104         } catch(E) {
1105             alert(E);
1106         }
1107     },
1108
1109     'on_select' : function(list,twisty) {
1110         var obj = this;
1111         var sel_lists = {};
1112
1113         for (var i = 0; i < list.length; i++) {
1114             var row_type = list[i].split('_')[0];
1115             var id = list[i].split('_')[1];
1116
1117             if (!sel_lists[row_type]) sel_lists[row_type] = [];
1118             sel_lists[row_type].push(id);
1119
1120             if (twisty) {
1121                 switch(row_type) {
1122                     case 'aou' : obj.on_click_aou(id,twisty); break;
1123                     case 'ssub' : obj.on_select_ssub(id,twisty); break;
1124                     default: break;
1125                 }
1126             }
1127         }
1128
1129         if (!obj.focused_node_retrieve_id) return;
1130
1131         var row_type = obj.focused_node_retrieve_id.split('_')[0];
1132         var id = obj.focused_node_retrieve_id.split('_')[1];
1133
1134         if (sel_lists[row_type]) { // the type focused is in the selection (usually the case)
1135             switch(row_type) {
1136                 case 'aou' : obj.on_click_aou(id,twisty); break;
1137                 default: if (obj['on_click_' + row_type]) obj['on_click_' + row_type](sel_lists[row_type],twisty);
1138             }
1139         }
1140     },
1141
1142     'on_select_ssub' : function(ssub_id,twisty) {
1143         var obj = this;
1144         try {
1145             //typo? var ssub_tree = obj.map_sdist[ 'ssub_' + ssub_id ];
1146             var ssub_tree = obj.map_ssub[ 'ssub_' + ssub_id ];
1147             obj.funcs.push( function() { 
1148                 document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
1149                 document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
1150                 document.getElementById('lib_menu').setAttribute('disabled','true'); 
1151             } );
1152             if (ssub_tree.distributions()) {
1153                 for (var i = 0; i < ssub_tree.distributions().length; i++) {
1154                     obj.funcs.push(
1155                         function(c,a) {
1156                             return function() {
1157                                 obj.append_member(c,a,[],'sdist');
1158                             }
1159                         }( ssub_tree.distributions()[i], ssub_tree )
1160                     )
1161                 }
1162             }
1163             if (ssub_tree.issuances()) {
1164                 for (var i = 0; i < ssub_tree.issuances().length; i++) {
1165                     obj.funcs.push(
1166                         function(c,a) {
1167                             return function() {
1168                                 obj.append_member(c,a,[],'siss');
1169                             }
1170                         }( ssub_tree.issuances()[i], ssub_tree )
1171                     )
1172                 }
1173             }
1174             if (ssub_tree.scaps()) {
1175                 for (var i = 0; i < ssub_tree.scaps().length; i++) {
1176                     obj.funcs.push(
1177                         function(c,a) {
1178                             return function() {
1179                                 obj.append_member(c,a,[],'scap');
1180                             }
1181                         }( ssub_tree.scaps()[i], ssub_tree )
1182                     )
1183                 }
1184             }
1185             obj.funcs.push( function() { 
1186                 document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
1187                 document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
1188                 document.getElementById('lib_menu').setAttribute('disabled','false'); 
1189             } );
1190         } catch(E) {
1191             alert(E);
1192         }
1193     },
1194
1195     'on_click_ssub' : function(ssub_ids,twisty) {
1196         var obj = this;
1197         try {
1198             // draw sdist editor
1199             if (typeof twisty == 'undefined') {
1200                 var params = {};
1201                 params.ssub_ids = ssub_ids;
1202                 obj.editor_init('ssub', 'edit', params);
1203             }
1204         } catch(E) {
1205             alert(E);
1206         }
1207     },
1208
1209     'on_click_sdist' : function(sdist_ids,twisty) {
1210         var obj = this;
1211         try {
1212             // draw sdist editor
1213             if (typeof twisty == 'undefined') {
1214                 var params = {};
1215                 params.sdist_ids = sdist_ids;
1216                 obj.editor_init('sdist', 'edit', params);
1217             }
1218         } catch(E) {
1219             alert(E);
1220         }
1221     },
1222
1223     'on_click_siss' : function(siss_ids,twisty) {
1224         var obj = this;
1225         try {
1226             // draw siss editor
1227             if (typeof twisty == 'undefined') {
1228                 var params = {};
1229                 params.siss_ids = siss_ids;
1230                 obj.editor_init('siss', 'edit', params);
1231             }
1232         } catch(E) {
1233             alert(E);
1234         }
1235     },
1236
1237     'on_click_scap' : function(scap_ids,twisty) {
1238         var obj = this;
1239         try {
1240             // draw scap editor
1241             if (typeof twisty == 'undefined') {
1242                 var params = {};
1243                 params.scap_ids = scap_ids;
1244                 obj.editor_init('scap', 'edit', params);
1245             }
1246         } catch(E) {
1247             alert(E);
1248         }
1249     },
1250
1251     'on_click_aou' : function(org_id,twisty) {
1252         var obj = this;
1253         var org = obj.data.hash.aou[ org_id ];
1254         obj.funcs.push( function() { 
1255             document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
1256             document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
1257             document.getElementById('lib_menu').setAttribute('disabled','true'); 
1258         } );
1259         if (org.children()) {
1260             for (var i = 0; i < org.children().length; i++) {
1261                 obj.funcs.push(
1262                     function(o,p) {
1263                         return function() {
1264                             obj.append_org(o,p)
1265                         }
1266                     }(org.children()[i],org)
1267                 );
1268             }
1269         } 
1270         if (obj.map_ssub[ 'aou_' + org_id ]) {
1271             for (var i = 0; i < obj.map_ssub[ 'aou_' + org_id ].length; i++) {
1272                 obj.funcs.push(
1273                     function(o,a) {
1274                         return function() {
1275                             obj.append_ssub(o,a);
1276                         }
1277                     }( org, obj.map_ssub[ 'aou_' + org_id ][i] )
1278                 );
1279             }
1280         }
1281         obj.funcs.push( function() { 
1282             document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
1283             document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
1284             document.getElementById('lib_menu').setAttribute('disabled','false'); 
1285         } );
1286
1287         // remove current editor
1288         if (typeof twisty == 'undefined') {
1289             document.getElementById('serial_manage_subs_editor_deck').selectedIndex = 0;
1290         }
1291     },
1292
1293     'append_org' : function (org,parent_org,params) {
1294         var obj = this;
1295         try {
1296             if (obj.map_tree[ 'aou_' + org.id() ]) {
1297                 var x = obj.map_tree[ 'aou_' + org.id() ];
1298                 if (params) {
1299                     for (var i in params) {
1300                         x.setAttribute(i,params[i]);
1301                     }
1302                 }
1303                 return x;
1304             }
1305
1306             var data = {
1307                 'row' : {
1308                     'my' : {
1309                         'aou' : org,
1310                     }
1311                 },
1312                 'skip_all_columns_except' : [0,1,2],
1313                 'retrieve_id' : 'aou_' + org.id(),
1314                 'to_bottom' : true,
1315                 'no_auto_select' : true,
1316             };
1317         
1318             var ssub_tree_list;
1319             if ( obj.org_ids.indexOf( Number( org.id() ) ) == -1 ) {
1320                 if ( get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) {
1321                     data.row.my.subscription_count = '0';
1322                     //data.row.my.distribution_count = '<0>';
1323                 } else {
1324                     data.row.my.subscription_count = '';
1325                     //data.row.my.distribution_count = '';
1326                 }
1327             } else {
1328                 var v_count = 0; var d_count = 0;
1329                 ssub_tree_list = obj.network.simple_request(
1330                     'FM_SSUB_TREE_LIST_RETRIEVE_VIA_RECORD_ID_AND_ORG_IDS.authoritative',
1331                     [ ses(), obj.docid, [ org.id() ] ]
1332                 );
1333                 for (var i = 0; i < ssub_tree_list.length; i++) {
1334                     v_count++;
1335                     obj.map_ssub[ 'ssub_' + ssub_tree_list[i].id() ] = function(r){return r;}(ssub_tree_list[i]);
1336                     var distributions = ssub_tree_list[i].distributions();
1337                     //if (distributions) d_count += distributions.length;
1338                     for (var j = 0; j < distributions.length; j++) {
1339                         obj.map_sdist[ 'sdist_' + distributions[j].id() ] = function(r){return r;}(distributions[j]);
1340                     }
1341                     var issuances = ssub_tree_list[i].issuances();
1342                     for (var j = 0; j < issuances.length; j++) {
1343                         obj.map_siss[ 'siss_' + issuances[j].id() ] = function(r){return r;}(issuances[j]);
1344                     }
1345                     var scaps = ssub_tree_list[i].scaps();
1346                     for (var j = 0; j < scaps.length; j++) {
1347                         obj.map_scap[ 'scap_' + scaps[j].id() ] = function(r){return r;}(scaps[j]);
1348                     }
1349                 }
1350                 data.row.my.subscription_count = v_count;
1351                 //data.row.my.distribution_count = '<' + d_count + '>';
1352             }
1353             if (parent_org) {
1354                 data.node = obj.map_tree[ 'aou_' + parent_org.id() ];
1355             }
1356             var nparams = obj.list.append(data);
1357             var node = nparams.my_node;
1358             if (params) {
1359                 for (var i in params) {
1360                     node.setAttribute(i,params[i]);
1361                 }
1362             }
1363             obj.map_tree[ 'aou_' + org.id() ] = node;
1364
1365             if (org.children()) {
1366                 node.setAttribute('container','true');
1367             }
1368
1369             if (parent_org) {
1370                 if ( obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ].parent_ou() == parent_org.id() ) {
1371                     data.node.setAttribute('open','true');
1372                 }
1373             } else {
1374                 obj.map_tree[ 'aou_' + org.id() ].setAttribute('open','true');
1375             }
1376
1377             if (ssub_tree_list) {
1378                 obj.map_ssub[ 'aou_' + org.id() ] = ssub_tree_list;
1379                 node.setAttribute('container','true');
1380             }
1381
1382             if (document.getElementById('show_ssubs').checked) {
1383                 obj.funcs.push( function() { obj.on_click_aou( org.id() ); } );
1384                 node.setAttribute('open','true');
1385             }
1386
1387         } catch(E) {
1388             dump(E+'\n');
1389             alert(E);
1390         }
1391     },
1392
1393     'append_ssub' : function( org, ssub_tree, params ) {
1394         var obj = this;
1395         try {
1396             if (obj.map_tree[ 'ssub_' + ssub_tree.id() ]) {
1397                 var x = obj.map_tree[ 'ssub_' + ssub_tree.id() ];
1398                 if (params) {
1399                     for (var i in params) {
1400                         x.setAttribute(i,params[i]);
1401                     }
1402                 }
1403                 return x;
1404             }
1405
1406             var parent_node = obj.map_tree[ 'aou_' + org.id() ];
1407             var data = {
1408                 'row' : {
1409                     'my' : {
1410                         'aou' : org,
1411                         'ssub' : ssub_tree,
1412                         'subscription_count' : '',
1413                         //'distribution_count' : ssub_tree.distributions() ? ssub_tree.distributions().length : '0',
1414                     }
1415                 },
1416                 'skip_all_columns_except' : [0,1,2],
1417                 'retrieve_id' : 'ssub_' + ssub_tree.id(),
1418                 'node' : parent_node,
1419                 'to_bottom' : true,
1420                 'no_auto_select' : true,
1421             };
1422             var nparams = obj.list.append(data);
1423             var node = nparams.my_node;
1424             obj.map_tree[ 'ssub_' + ssub_tree.id() ] =  node;
1425             if (params) {
1426                 for (var i in params) {
1427                     node.setAttribute(i,params[i]);
1428                 }
1429             }
1430             if (ssub_tree.distributions() || ssub_tree.scaps() || ssub_tree.issuances()) {
1431                 //did this support a later typo? obj.map_sdist[ 'ssub_' + ssub_tree.id() ] = ssub_tree;
1432                 node.setAttribute('container','true');
1433             }
1434             if (document.getElementById('show_groups').checked) {
1435                 node.setAttribute('open','true');
1436                 obj.funcs.push( function() { obj.on_select_ssub( ssub_tree.id(), true ); } );
1437             }
1438             var sdist_group_node_data = {
1439                 'row' : {
1440                     'my' : {
1441                         'label' : 'Distributions',
1442                     }
1443                 },
1444                 'retrieve_id' : 'sdist-group_' + ssub_tree.id(),
1445                 'node' : node,
1446                 'to_bottom' : true,
1447                 'no_auto_select' : true,
1448             };
1449             nparams = obj.list.append(sdist_group_node_data);
1450             obj.map_tree[ 'ssub_sdist_group_' + ssub_tree.id() ] =  nparams.my_node;
1451
1452             var siss_group_node_data = {
1453                 'row' : {
1454                     'my' : {
1455                         'label' : 'Issuances',
1456                     }
1457                 },
1458                 'retrieve_id' : 'siss-group_' + ssub_tree.id(),
1459                 'node' : node,
1460                 'to_bottom' : true,
1461                 'no_auto_select' : true,
1462             };
1463             nparams = obj.list.append(siss_group_node_data);
1464             obj.map_tree[ 'ssub_siss_group_' + ssub_tree.id() ] =  nparams.my_node;
1465
1466             var scap_group_node_data = {
1467                 'row' : {
1468                     'my' : {
1469                         'label' : 'Captions/Patterns',
1470                     }
1471                 },
1472                 'retrieve_id' : 'scap-group_' + ssub_tree.id(),
1473                 'node' : node,
1474                 'to_bottom' : true,
1475                 'no_auto_select' : true,
1476             };
1477             nparams = obj.list.append(scap_group_node_data);
1478             obj.map_tree[ 'ssub_scap_group_' + ssub_tree.id() ] =  nparams.my_node;
1479         } catch(E) {
1480             dump(E+'\n');
1481             alert(E);
1482         }
1483     },
1484
1485     'append_member' : function( item, ssub_tree, attributes, type ) {
1486         var obj = this;
1487         try {
1488             if (obj.map_tree[ type + '_' + item.id() ]) {
1489                 var x = obj.map_tree[ type + '_' + item.id() ];
1490                 if (attributes) {
1491                     for (var i in attributes) {
1492                         x.setAttribute(i,attributes[i]);
1493                     }
1494                 }
1495                 return x;
1496             }
1497
1498             var parent_node = obj.map_tree[ 'ssub_' + type + '_group_' + ssub_tree.id() ];
1499             var data = {
1500                 'row' : {
1501                     'my' : {
1502                         'aou' : obj.data.hash.aou[ ssub_tree.owning_lib() ],
1503                         'ssub' : ssub_tree,
1504                         'subscription_count' : '',
1505                         //'distribution_count' : '',
1506                     }
1507                 },
1508                 'retrieve_id' : type + '_' + item.id(),
1509                 'node' : parent_node,
1510                 'to_bottom' : true,
1511                 'no_auto_select' : true,
1512             };
1513             data['row']['my'][type] = item; // TODO: future optimization: get only the IDs of these leaves, then fetch the full row in 'retrieve_row'
1514             var nparams = obj.list.append(data);
1515             var node = nparams.my_node;
1516             obj.map_tree[ type + '_' + item.id() ] =  node;
1517             if (attributes) {
1518                 for (var i in attributes) {
1519                     node.setAttribute(i,attributes[i]);
1520                 }
1521             }
1522
1523         } catch(E) {
1524             dump(E+'\n');
1525             alert(E);
1526         }
1527     },
1528
1529     'list_init' : function( params ) {
1530
1531         try {
1532             netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
1533             var obj = this;
1534             
1535             JSAN.use('circ.util');
1536             var columns = [
1537                 {
1538                     'id' : 'tree_location',
1539                     'label' : 'Location',
1540                     'flex' : 1, 'primary' : true, 'hidden' : false, 
1541                     'render' : function(my) { return my.sdist ? my.sdist.label() : my.siss ? my.siss.label() : my.scap ? 'C/P : #' + my.scap.id() : my.ssub ? 'Subscription : #' + my.ssub.id() : my.aou ? my.aou.shortname() + " : " + my.aou.name() : my.label ? my.label : "???"; },
1542                 },
1543                 {
1544                     'id' : 'subscription_count',
1545                     'label' : 'Subscriptions',
1546                     'flex' : 0, 'primary' : false, 'hidden' : false, 
1547                     'render' : function(my) { return my.subscription_count; },
1548                 },
1549                 /*{
1550                     'id' : 'distribution_count',
1551                     'label' : 'Members',
1552                     'flex' : 0,
1553                     'primary' : false, 'hidden' : false, 
1554                     'render' : function(my) { return my.distribution_count; },
1555                 },*/
1556             ];
1557             JSAN.use('util.list'); obj.list = new util.list('subs_tree');
1558             obj.list.init(
1559                 {
1560                     'no_auto_select' : true,
1561                     'columns' : columns,
1562                     'map_row_to_columns' : circ.util.std_map_row_to_columns(' '),
1563                     'retrieve_row' : function(params) {
1564
1565                         var row = params.row;
1566                         obj.funcs.push(
1567                             function() {
1568
1569                                 if (typeof params.on_retrieve == 'function') {
1570                                     params.on_retrieve(row);
1571                                 }
1572
1573                             }
1574                         );
1575
1576                         return row;
1577                     },
1578                     'on_click' : function(ev) {
1579                         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserRead');
1580                         var row = {}; var col = {}; var nobj = {};
1581                         obj.list.node.treeBoxObject.getCellAt(ev.clientX,ev.clientY,row,col,nobj); 
1582                         if ((row.value == -1)||(nobj.value != 'twisty')) { return; } // on_click runs for twistys only
1583
1584                         var node = obj.list.node.contentView.getItemAtIndex(row.value);
1585                         var list = [ node.getAttribute('retrieve_id') ];
1586                         if (typeof obj.on_select == 'function') {
1587                             obj.on_select(list,true);
1588                         }
1589                         if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
1590                             window.xulG.on_select(list);
1591                         }
1592                     },
1593                     'on_select' : function(ev) {
1594                         JSAN.use('util.functional');
1595                         
1596                         // get the actual node clicked to determine which editor to use
1597                         if (obj.list.node.view.selection.currentIndex > -1) {
1598                             var node = obj.list.node.contentView.getItemAtIndex(obj.list.node.view.selection.currentIndex);
1599                             obj.focused_node_retrieve_id = node.getAttribute('retrieve_id');
1600                         }
1601
1602                         var sel = obj.list.retrieve_selection();
1603                         obj.controller.view.sel_clip.disabled = sel.length < 1;
1604                         obj.sel_list = util.functional.map_list(
1605                             sel,
1606                             function(o) { return o.getAttribute('retrieve_id'); }
1607                         );
1608                         obj.toggle_actions();
1609                         if (typeof obj.on_select == 'function') {
1610                             obj.on_select(obj.sel_list);
1611                         }
1612                         if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
1613                             window.xulG.on_select(obj.sel_list);
1614                         }
1615                     },
1616                 }
1617             );
1618
1619             obj.controller.render();
1620
1621         } catch(E) {
1622             this.error.sdump('D_ERROR','serial/manage_subs.list_init: ' + E + '\n');
1623             alert(E);
1624         }
1625     },
1626
1627     'toggle_actions' : function() {
1628         var obj = this;
1629         try {
1630             var found_aou = false; var found_ssub = false; var found_sdist = false; var found_siss = false; var found_scap = false; var found_sdist_group = false; var found_siss_group = false; var found_scap_group = false;
1631             for (var i = 0; i < obj.sel_list.length; i++) {
1632                 var type = obj.sel_list[i].split(/_/)[0];
1633                 switch(type) {
1634                     case 'aou' : 
1635                         found_aou = true; 
1636                     break;
1637                     case 'ssub' : found_ssub = true; break;
1638                     case 'sdist' : found_sdist = true; break;
1639                     case 'siss' : found_siss = true; break;
1640                     case 'scap' : found_scap = true; break;
1641                     case 'sdist-group' : found_sdist_group = true; break;
1642                     case 'siss-group' : found_siss_group = true; break;
1643                     case 'scap-group' : found_scap_group = true; break;
1644                 }
1645             }
1646             obj.controller.view.cmd_add_sdist.setAttribute('disabled','true');
1647             obj.controller.view.cmd_add_siss.setAttribute('disabled','true');
1648             obj.controller.view.cmd_add_scap.setAttribute('disabled','true');
1649             obj.controller.view.cmd_make_predictions.setAttribute('disabled','true');
1650             obj.controller.view.cmd_delete_sdist.setAttribute('disabled','true');
1651             obj.controller.view.cmd_delete_siss.setAttribute('disabled','true');
1652             obj.controller.view.cmd_delete_scap.setAttribute('disabled','true');
1653             obj.controller.view.cmd_add_subscriptions.setAttribute('disabled','true');
1654             obj.controller.view.cmd_mark_library.setAttribute('disabled','true');
1655             obj.controller.view.cmd_delete_ssub.setAttribute('disabled','true');
1656             obj.controller.view.cmd_mark_subscription.setAttribute('disabled','true');
1657             obj.controller.view.cmd_transfer_subscription.setAttribute('disabled','true');
1658             obj.controller.view.cmd_transfer_sdists.setAttribute('disabled','true');
1659             if (found_aou) {
1660                 obj.controller.view.cmd_add_subscriptions.setAttribute('disabled','false');
1661                 obj.controller.view.cmd_mark_library.setAttribute('disabled','false');
1662             }
1663             if (found_ssub) {
1664                 obj.controller.view.cmd_delete_ssub.setAttribute('disabled','false');
1665                 obj.controller.view.cmd_mark_subscription.setAttribute('disabled','false');
1666                 obj.controller.view.cmd_add_sdist.setAttribute('disabled','false');
1667                 obj.controller.view.cmd_add_siss.setAttribute('disabled','false');
1668                 obj.controller.view.cmd_add_scap.setAttribute('disabled','false');
1669                 obj.controller.view.cmd_transfer_subscription.setAttribute('disabled','false');
1670                 obj.controller.view.cmd_make_predictions.setAttribute('disabled','false');
1671             }
1672             if (found_sdist_group) {
1673                 obj.controller.view.cmd_add_sdist.setAttribute('disabled','false');
1674             }
1675             if (found_siss_group) {
1676                 obj.controller.view.cmd_add_siss.setAttribute('disabled','false');
1677             }
1678             if (found_scap_group) {
1679                 obj.controller.view.cmd_add_scap.setAttribute('disabled','false');
1680             }
1681             if (found_sdist) {
1682                 obj.controller.view.cmd_delete_sdist.setAttribute('disabled','false');
1683                 obj.controller.view.cmd_transfer_sdists.setAttribute('disabled','false');
1684             }
1685             if (found_siss) {
1686                 obj.controller.view.cmd_delete_siss.setAttribute('disabled','false');
1687             }
1688             if (found_scap) {
1689                 obj.controller.view.cmd_delete_scap.setAttribute('disabled','false');
1690             }
1691         } catch(E) {
1692             obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.actions.error'),E);
1693         }
1694     },
1695
1696     'refresh_list' : function() { 
1697         try {
1698             var obj = this;
1699             obj.list.clear();
1700             obj.map_tree = {};
1701             obj.map_ssub = {};
1702             obj.map_sdist = {};
1703             obj.map_siss = {};
1704             obj.map_scap = {};
1705             obj.org_ids = obj.network.simple_request('FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
1706             if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
1707             JSAN.use('util.functional'); 
1708             obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
1709             /*
1710             var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
1711             obj.show_libs( org );
1712             */
1713             obj.show_my_libs( document.getElementById('lib_menu').value );
1714         } catch(E) {
1715             this.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.refresh_list.error'),E);
1716         }
1717     },
1718 };
1719
1720 dump('exiting serial/manage_subs.js\n');