]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/serial/manage_items.js
Merge remote branch 'working/user/dbwells/serial_items_and_note_fixes'
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / serial / manage_items.js
1 dump('entering manage_items.js\n');
2
3 function $(id) { return document.getElementById(id); }
4
5 if (typeof serial == 'undefined') serial = {};
6 serial.manage_items = function (params) {
7
8         JSAN.use('util.error'); this.error = new util.error();
9         JSAN.use('util.network'); this.network = new util.network();
10         JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
11
12     this.current_sunit_id = -1; //default to **AUTO**
13     this.mode = 'receive';
14
15 }
16
17 serial.manage_items.prototype = {
18
19         'list_sitem_map' : {},
20     'sdist_map' : {},
21     'ssub_map' : {},
22     'row_map' : {},
23
24     'retrieve_ssubs_and_sdists' : function () {
25                 var obj = this;
26
27         try {
28             obj.lib = $('serial_item_lib_menu').value;
29             var sdist_retrieve_params = {"+ssub":{"record_entry" : obj.docid}};
30             if (obj.mode == 'receive') {
31                 sdist_retrieve_params["+ssub"].owning_lib = obj.lib;
32             } else {
33                 sdist_retrieve_params.holding_lib = obj.lib;
34             }
35             var robj = obj.network.request(
36                 'open-ils.pcrud',
37                 'open-ils.pcrud.id_list.sdist',
38                 [ ses(), sdist_retrieve_params, {"join":"ssub"} ]
39             );
40             if (robj != null) {
41                 if (typeof robj.ilsevent != 'undefined') throw(robj);
42                 obj.sdist_ids = robj.length ? robj : [robj];
43                 // now get actual sdist and ssub objects
44                 robj = obj.network.simple_request(
45                     'FM_SDIST_FLESHED_BATCH_RETRIEVE.authoritative',
46                     [ obj.sdist_ids ]
47                 );
48                 if (robj != null) {
49                     if (typeof robj.ilsevent != 'undefined') throw(robj);
50                     robj = robj.length ? robj : [robj];
51                     for (var i = 0; i < robj.length; i++) {
52                         obj.sdist_map[robj[i].id()] = robj[i];
53                     }
54                 }
55                 robj = obj.network.request(
56                     'open-ils.pcrud',
57                     'open-ils.pcrud.id_list.ssub',
58                     [ ses(), {"+sdist" : {"id" : obj.sdist_ids}}, {"join":"sdist"} ]
59                 );
60                 var ssub_ids = robj.length ? robj : [robj];
61                 robj = obj.network.simple_request(
62                     'FM_SSUB_FLESHED_BATCH_RETRIEVE.authoritative',
63                     [ ssub_ids ]
64                 );
65                 if (robj != null) {
66                     if (typeof robj.ilsevent != 'undefined') throw(robj);
67                     robj = robj.length ? robj : [robj];
68                     for (var i = 0; i < robj.length; i++) {
69                         obj.ssub_map[robj[i].id()] = robj[i];
70                     }
71                 }
72             } else {
73                 obj.sdist_ids = [];
74             }
75
76         } catch(E) {
77             obj.error.standard_unexpected_error_alert('retrieve_ssubs_and_sdists failed!',E);
78         }
79     },
80
81     'build_menus' : function () {
82                 var obj = this;
83
84         // draw library drop-down
85         obj.org_ids = obj.network.simple_request('FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
86         if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
87         JSAN.use('util.functional');
88         obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
89
90         var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
91
92         JSAN.use('util.file'); JSAN.use('util.widgets');
93
94         var file; var list_data; var ml;
95
96         file = new util.file('offline_ou_list');
97         if (file._file.exists()) {
98             list_data = file.get_object(); file.close();
99             ml = util.widgets.make_menulist( list_data[0], list_data[1] );
100             ml.setAttribute('id','serial_item_lib_menu'); document.getElementById('serial_item_lib_menu_box').appendChild(ml);
101             //TODO: class this menu properly
102             for (var i = 0; i < obj.org_ids.length; i++) {
103                 ml.getElementsByAttribute('value',obj.org_ids[i])[0].setAttribute('class','has_distributions');
104             }
105             /*TODO: add/enable this legend?
106             ml.firstChild.addEventListener(
107                 'popupshown',
108                 function(ev) {
109                     document.getElementById('legend').setAttribute('hidden','false');
110                 },
111                 false
112             );
113             ml.firstChild.addEventListener(
114                 'popuphidden',
115                 function(ev) {
116                     document.getElementById('legend').setAttribute('hidden','true');
117                 },
118                 false
119             );*/
120             ml.addEventListener(
121                 'command',
122                 function(ev) {
123                     //if (document.getElementById('serial_item_refresh_button')) document.getElementById('serial_item_refresh_button').focus();
124                     obj.save_settings();
125                     // get latest sdist id list based on library drowdown
126                     obj.retrieve_ssubs_and_sdists();
127                     obj.refresh_list('main');
128                     obj.refresh_list('workarea');
129                 },
130                 false
131             );
132
133         } else {
134             throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n');
135         }
136         file = new util.file('serial_items_prefs.'+obj.data.server_unadorned);
137         util.widgets.load_attributes(file);
138         ml.value = ml.getAttribute('value');
139         if (! ml.value) {
140             ml.value = org.id();
141             ml.setAttribute('value',ml.value);
142         }
143         
144         // deal with mode radio selectedIndex, as load_attributes is setting a "read-only" value
145         if ($('mode_receive').getAttribute('selected')) {
146             $('serial_manage_items_mode').selectedIndex = 0;
147         } else if ($('mode_advanced_receive').getAttribute('selected')) {
148             $('serial_manage_items_mode').selectedIndex = 1;
149         } else {
150             $('serial_manage_items_mode').selectedIndex = 2;
151         }
152
153         // setup recent sunits list
154         var recent_sunits_file = new util.file('serial_items_recent_sunits_'+obj.docid+'.'+obj.data.server_unadorned);
155         util.widgets.load_attributes(recent_sunits_file);
156         var recent_sunits_popup = $('serial_items_recent_sunits');
157         obj.sunit_entries = JSON2js(recent_sunits_popup.getAttribute('sunit_json'));
158         for (i = 0; i < obj.sunit_entries.length; i++) {
159             var sunit_info = obj.sunit_entries[i];
160             var new_menu_item = recent_sunits_popup.appendItem(sunit_info.label);
161             new_menu_item.setAttribute('id', 'serial_items_recent_sunits_entry_'+sunit_info.id);
162             new_menu_item.setAttribute('sunit_id', sunit_info.id);
163             new_menu_item.setAttribute('command', 'cmd_set_sunit');
164         }
165     },
166
167         'init' : function( params ) {
168                 var obj = this;
169
170                 obj.docid = params['docid'];
171
172         obj.build_menus();
173         obj.set_sunit($('serial_items_current_sunit').getAttribute('sunit_id'), $('serial_items_current_sunit').getAttribute('sunit_label'), $('serial_items_current_sunit').getAttribute('sdist_id'), $('serial_items_current_sunit').getAttribute('sstr_id'));
174         //obj.retrieve_ssubs_and_sdists();
175                 obj.init_lists();
176
177         var mode_radio_group = $('serial_manage_items_mode');
178         obj.set_mode(mode_radio_group.selectedItem.id.substr(5));
179         mode_radio_group.addEventListener(
180             'command',
181             function(ev) {
182                 obj.save_settings();
183                 var mode = ev.target.id.substr(5); //strip out 'mode_'
184                 obj.set_mode(mode);
185                 obj.refresh_list('main');
186                 obj.refresh_list('workarea');
187             },
188             false
189         );
190         $('serial_manage_items_show_all').addEventListener(
191             'command',
192             function(ev) {
193                 obj.save_settings();
194                 obj.set_mode();
195                 obj.refresh_list('main');
196                 obj.refresh_list('workarea');
197             },
198             false
199         );
200
201                 JSAN.use('util.controller'); obj.controller = new util.controller();
202                 obj.controller.init(
203                         {
204                                 'control_map' : {
205                                         'save_columns' : [ [ 'command' ], function() { obj.lists.main.save_columns(); } ],
206                                         'cmd_broken' : [ ['command'], function() { alert('Not Yet Implemented'); } ],
207                                         'sel_clip' : [ ['command'], function() { obj.lists.main.clipboard(); } ],
208                     'cmd_add_item' : [
209                         ['command'],
210                         function() {
211                             try {
212                                 var new_item = new sitem();
213                                 new_item.issuance(new siss());
214                                 new_item.stream(1); //FIXME: hard-coded stream
215                                 new_item.issuance().subscription(1); //FIXME: hard-coded subscription
216                                 new_item.isnew(1);
217                                 new_item.issuance().isnew(1);
218                                 spawn_sitem_editor( {'sitems' : [new_item], 'do_edit' : 1 } );
219
220                                 obj.refresh_list('main');
221
222                             } catch(E) {
223                                 obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_items.error'),E);
224                             }
225                         }
226                     ],
227                     'cmd_edit_items' : [
228                         ['command'],
229                         function() {
230                             try {
231                                 if (!obj.retrieve_ids || obj.retrieve_ids.length == 0) return;
232
233                                 JSAN.use('util.functional');
234                                 var list = util.functional.map_list(
235                                         obj.retrieve_ids,
236                                         function (o) {
237                                             return o.sitem_id;
238                                         }
239                                     );
240
241                                 spawn_sitem_editor( { 'sitem_ids' : list, 'do_edit' : 1 } );
242
243                                 obj.refresh_rows(list);
244
245                             } catch(E) {
246                                 obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_items.error'),E);
247                             }
248                         }
249                     ],
250                     'cmd_reset_items' : [
251                         ['command'],
252                         function() {
253                             try {
254                                 if (!obj.retrieve_ids || obj.retrieve_ids.length == 0) return;
255
256                                 JSAN.use('util.functional');
257                                 var list = util.functional.map_list(
258                                         obj.retrieve_ids,
259                                         function (o) {
260                                             return o.sitem_id;
261                                         }
262                                     );
263
264                                 var robj = obj.network.request(
265                                             'open-ils.serial',
266                                             'open-ils.serial.reset_items',
267                                             [ ses(), list ]
268                                         );
269                                 if (typeof robj.ilsevent != 'undefined') throw(robj);
270
271                                 alert('Successfully reset '+robj.num_items+' item(s)');
272
273                                 obj.refresh_list('main');
274                                 obj.refresh_list('workarea');
275                             } catch(E) {
276                                 obj.error.standard_unexpected_error_alert('staff.serial.manage_items.reset_items.error',E);
277                             }
278                         }
279                     ],
280                     'cmd_delete_items' : [
281                         ['command'],
282                         function() {
283                             try {
284                                 JSAN.use('util.functional');
285                                 var list = util.functional.map_list(
286                                         obj.retrieve_ids,
287                                         function (o) {
288                                             return obj.list_sitem_map[o.sitem_id];
289                                         }
290                                     );
291                                 var delete_msg;
292                                 if (list.length != 1) {
293                                     delete_msg = document.getElementById('catStrings').getFormattedString('staff.cat.copy_browser.delete_items.confirm.plural', [list.length]);
294                                 } else {
295                                     delete_msg = document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.confirm');
296                                 }
297                                 var r = obj.error.yns_alert(
298                                         delete_msg,
299                                         document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.title'),
300                                         document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.delete'),
301                                         document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.cancel'),
302                                         null,
303                                         document.getElementById('commonStrings').getString('common.confirm')
304                                 );
305
306                                 if (r == 0) {
307                                     for (var i = 0; i < list.length; i++) {
308                                         list[i].isdeleted('1');
309                                     }
310                                     var robj = obj.network.request(
311                                             'open-ils.serial',
312                                             'open-ils.serial.item.fleshed.batch.update',
313                                         [ ses(), list ],
314                                         null,
315                                         {
316                                             'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.override'),
317                                             'overridable_events' : [ // FIXME: replace or delete these events
318                                                 1208 /* TITLE_LAST_COPY */,
319                                                 1227 /* COPY_DELETE_WARNING */,
320                                             ]
321                                         }
322                                     );
323                                     if (robj == null) throw(robj);
324                                     if (typeof robj.ilsevent != 'undefined') {
325                                         if ( (robj.ilsevent != 0) && (robj.ilsevent != 1227 /* COPY_DELETE_WARNING */) && (robj.ilsevent != 1208 /* TITLE_LAST_COPY */) ) throw(robj);
326                                     }
327                                     obj.refresh_list(obj.selected_list);
328                                 }
329
330
331                             } catch(E) {
332                                 obj.error.standard_unexpected_error_alert('staff.serial.manage_items.delete_items.error',E);
333                                 obj.refresh_list();
334                             }
335                         }
336                     ],
337                     'cmd_set_sunit' : [
338                         ['command'],
339                         function(evt) {
340                             try {
341                                 var target = evt.explicitOriginalTarget;
342                                 obj.process_unit_selection(target);
343                             } catch(E) {
344                                 obj.error.standard_unexpected_error_alert('cmd_set_sunit failed!',E);
345                             }
346                         }
347                     ],
348                     'cmd_set_other_sunit' : [
349                         ['command'],
350                         function() {
351                             obj.set_other_sunit();
352                             if (obj.mode == 'bind') {
353                                 obj.refresh_list('main');
354                                 obj.refresh_list('workarea');
355                             }
356                         }
357                     ],
358                     'cmd_predict_items' : [
359                         ['command'],
360                         function() {
361                             alert('Subscription selection needed here'); //FIXME: make this prompt, or discard this feature
362                         }
363                     ],
364                     'cmd_receive_items' : [
365                         ['command'],
366                         function() {
367                             try {
368                                 JSAN.use('util.functional');
369                                 var donor_unit_ids = {};
370                                 var list = util.functional.map_list(
371                                         obj.retrieve_ids,
372                                         function (o) {
373                                             var item = obj.list_sitem_map[o.sitem_id];
374                                             if (item.unit()) {
375                                                 donor_unit_ids[item.unit().id()] = 1;
376                                             }
377                                             item.unit(obj.current_sunit_id);
378                                             return item;
379                                         }
380                                     );
381
382                                 var mode = obj.mode;
383                                 if (mode == 'advanced_receive') mode = 'receive';
384
385                                 var method; var success_label;
386                                 if (mode == 'receive') {
387                                     method = 'open-ils.serial.receive_items';
388                                     success_label = 'received';
389                                 } else { // bind mode
390                                     method = 'open-ils.serial.bind_items';
391                                     success_label = 'bound';
392                                 } 
393
394                                 // deal with barcodes and call numbers for *NEW* units
395                                 var barcodes = {};
396                                 var call_numbers = {};
397                                 var call_numbers_by_siss_and_sdist = {};
398
399                                 if (obj.current_sunit_id < 0) { // **AUTO** or **NEW** units
400                                     var new_unit_barcode = '';
401                                     var new_unit_call_number = '';
402                                     for (var i = 0; i < list.length; i++) {
403                                         var item = list[i];
404                                         if (new_unit_barcode) {
405                                             barcodes[item.id()] = new_unit_barcode;
406                                             call_numbers[item.id()] = new_unit_call_number;
407                                             continue;
408                                         }
409                                         var prompt_text;
410                                         if (obj.current_sunit_id == -1) {
411                                             prompt_text = 'for '+item.issuance().label()+ ' from Distribution: '+obj.sdist_map[item.stream().distribution()].label()+'/'+item.stream().id()+':';
412                                         } else { // must be -2
413                                             prompt_text = 'for the new unit:';
414                                         }
415
416                                         // first barcodes
417                                         var barcode = window.prompt('Please enter a barcode ' + prompt_text,
418                                             '@@AUTO',
419                                             'Unit Barcode Prompt');
420                                         barcode = String( barcode ).replace(/\s/g,'');
421                                         /* Casting a possibly null input value to a String turns it into "null" */
422                                         if (!barcode || barcode == 'null') {
423                                             alert('Invalid barcode entered, defaulting to system-generated.');
424                                             barcode = '@@AUTO';
425                                         } else {
426                                             // disable alarm sound temporarily
427                                             var sound_setting = obj.data.no_sound;
428                                             if (!sound_setting) { // undefined or false
429                                                 obj.data.no_sound = true; obj.data.stash('no_sound');
430                                             }
431                                             var test = obj.network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ barcode ]);
432                                             if (typeof test.ilsevent == 'undefined') {
433                                                 alert('Another copy has barcode "' + barcode + '", defaulting to system-generated.');
434                                                 barcode = '@@AUTO';
435                                             }
436                                             if (!sound_setting) {
437                                                 obj.data.no_sound = sound_setting; obj.data.stash('no_sound');
438                                             }
439                                         }
440                                         barcodes[item.id()] = barcode;
441
442                                         // now call numbers
443                                         if (typeof call_numbers_by_siss_and_sdist[item.issuance().id() + '@' + item.stream().distribution()] == 'undefined') {
444                                             var default_cn = 'DEFAULT';
445                                             // if they defined a *_call_number, honor it as the default
446                                             var preset_cn = obj.sdist_map[item.stream().distribution()][mode + '_call_number']();
447                                             if (preset_cn) {
448                                                 default_cn = preset_cn.label();
449                                             } else {
450                                                 // for now, let's default to the last created call number if there is one
451                                                 var acn_list = obj.network.request(
452                                                         'open-ils.pcrud',
453                                                         'open-ils.pcrud.search.acn',
454                                                         [ ses(), {"record" : obj.docid, "owning_lib" : obj.sdist_map[item.stream().distribution()].holding_lib().id(), "deleted" : 'f' }, {"order_by" : {"acn" : "create_date DESC"}, "limit" : "1" } ]
455                                                 );
456
457                                                 if (acn_list) {
458                                                     default_cn = acn_list.label();
459                                                 }
460                                             }
461                                             var call_number = window.prompt('Please enter/adjust a call number ' + prompt_text,
462                                                 default_cn, //TODO: real default by setting
463                                                 'Unit Call Number Prompt');
464                                             call_number = String( call_number ).replace(/^\s+/,'').replace(/\s$/,'');
465                                             /* Casting a possibly null input value to a String turns it into "null" */
466                                             if (!call_number || call_number == 'null') {
467                                                 alert('Invalid call number entered, setting to "DEFAULT".');
468                                                 call_number = 'DEFAULT'; //TODO: real default by setting
469                                             }
470                                             call_numbers[item.id()] = call_number;
471                                             call_numbers_by_siss_and_sdist[item.issuance().id() + '@' + item.stream().distribution()] = call_number;
472                                         } else {
473                                             // we have already seen this same issuance and distribution combo, so use the same call number
474                                             call_numbers[item.id()] = call_numbers_by_siss_and_sdist[item.issuance().id() + '@' + item.stream().distribution()];
475                                         }
476
477                                         if (obj.current_sunit_id == -2) {
478                                             new_unit_barcode = barcode;
479                                             new_unit_call_number = call_number;
480                                         }
481                                     }
482                                 }
483
484                                 var robj = obj.network.request(
485                                             'open-ils.serial',
486                                             method,
487                                             [ ses(), list, barcodes, call_numbers, donor_unit_ids ]
488                                         );
489                                 if (typeof robj.ilsevent != 'undefined') throw(robj); //TODO: catch for override
490
491                                 alert('Successfully '+success_label+' '+robj.num_items+' item(s)');
492
493                                 if (obj.current_sunit_id == -2) {
494                                     obj.current_sunit_id = robj.new_unit_id;
495                                 }
496
497                                 obj.rebuild_current_sunit(obj.sdist_map[list[0].stream().distribution()].label(), list[0].stream().distribution(), list[0].stream().id());
498                                 obj.refresh_list('main');
499                                 obj.refresh_list('workarea');
500                                 
501                             } catch(E) {
502                                 obj.error.standard_unexpected_error_alert('cmd_receive_items failed!',E);
503                             }
504                         }
505                     ],
506                     'cmd_edit_sunit' : [
507                         ['command'],
508                         function() {
509                             try {
510                                 /*if (!obj.retrieve_ids || obj.retrieve_ids.length == 0) return;
511
512                                 JSAN.use('util.functional');
513                                 var list = util.functional.map_list(
514                                         obj.retrieve_ids,
515                                         function (o) {
516                                             return o.sitem_id;
517                                         }
518                                     );
519 */
520                                 spawn_sunit_editor( { 'sunit_ids' : [1], 'edit' : 1 } ); //FIXME: hard-coded sunit
521
522                             } catch(E) {
523                                 obj.error.standard_unexpected_error_alert('cmd_edit_sunit failed!',E);
524                             }
525                         }
526                     ],
527                     'cmd_view_sitem_notes' : [
528                         ['command'],
529                         function() {
530                             try {
531                                 obj.view_notes('sitem');
532                             } catch(E) {
533                                 obj.error.standard_unexpected_error_alert('cmd_view_sitem_notes failed!',E);
534                             }
535                         }
536                     ],
537                     'cmd_view_sdist_notes' : [
538                         ['command'],
539                         function() {
540                             try {
541                                 obj.view_notes('sdist');
542                             } catch(E) {
543                                 obj.error.standard_unexpected_error_alert('cmd_view_sdist_notes failed!',E);
544                             }
545                         }
546                     ],
547                     'cmd_view_ssub_notes' : [
548                         ['command'],
549                         function() {
550                             try {
551                                 obj.view_notes('ssub');
552                             } catch(E) {
553                                 obj.error.standard_unexpected_error_alert('cmd_view_ssub_notes failed!',E);
554                             }
555                         }
556                     ],
557                     'cmd_items_print' : [ ['command'], function() { obj.items_print(obj.selected_list); } ],
558                                         'cmd_items_export' : [ ['command'], function() { obj.items_export(obj.selected_list); } ],
559                                         'cmd_refresh_list' : [ ['command'], function() { obj.retrieve_ssubs_and_sdists(); obj.refresh_list('main'); obj.refresh_list('workarea'); } ]
560                                 }
561                         }
562                 );
563         
564                 obj.retrieve('main'); // retrieve main list
565         obj.retrieve('workarea'); // retrieve shelving unit list
566
567                 obj.controller.view.sel_clip.setAttribute('disabled','true');
568
569         },
570
571         'items_print' : function(which) {
572                 var obj = this;
573                 try {
574                         var list = obj.lists[which];
575 /* FIXME: serial items print template?                  JSAN.use('patron.util');
576                         var params = { 
577                                 'patron' : patron.util.retrieve_fleshed_au_via_id(ses(),obj.patron_id), 
578                                 'template' : 'items_out'
579                         }; */
580                         list.print( params );
581                 } catch(E) {
582                         obj.error.standard_unexpected_error_alert('manage_items printing',E);
583                 }
584         },
585
586         'items_export' : function(which) {
587                 var obj = this;
588                 try {
589                         var list = obj.lists[which];
590                         list.dump_csv_to_clipboard();
591                 } catch(E) {
592                         obj.error.standard_unexpected_error_alert('manage_items export',E);
593                 }
594         },
595
596         'rebuild_current_sunit' : function(sdist_label, sdist_id, sstr_id) {
597                 var obj = this;
598         if (!obj.current_sunit_id) return; // current sunit is NONE
599                 try {
600             var robj = obj.network.request(
601                 'open-ils.pcrud',
602                 'open-ils.pcrud.retrieve.sunit',
603                 [ ses(),  obj.current_sunit_id]
604             );
605             if (!robj) return; // current sunit is NEW or AUTO
606
607             var label = '[' + sdist_label + '/' + sstr_id + ' #' + obj.current_sunit_id + '] ' + robj.summary_contents();
608             obj.set_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
609             obj.save_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
610                 } catch(E) {
611                         obj.error.standard_unexpected_error_alert('serial items set_sunit',E);
612                 }
613         },
614
615         'set_sunit' : function(sunit_id, label, sdist_id, sstr_id) {
616                 var obj = this;
617                 try {
618             obj.current_sunit_id = sunit_id;
619             obj.current_sunit_sdist_id = sdist_id;
620             obj.current_sunit_sstr_id = sstr_id;
621             if (sunit_id < 0  || sunit_id === '') {
622                 $('serial_workarea_sunit_desc').firstChild.nodeValue = '**' + label + '**';
623             } else {
624                 $('serial_workarea_sunit_desc').firstChild.nodeValue = label;
625                 obj.add_sunit_to_menu(sunit_id, label, sdist_id, sstr_id);
626             }
627                 } catch(E) {
628                         obj.error.standard_unexpected_error_alert('serial items set_sunit',E);
629                 }
630         },
631
632         'save_sunit' : function(sunit_id, label, sdist_id, sstr_id) {
633                 var obj = this;
634                 try {
635             $('serial_items_current_sunit').setAttribute('sunit_id', sunit_id);
636             $('serial_items_current_sunit').setAttribute('sunit_label', label);
637             if (sunit_id > 0) {
638                 $('serial_items_current_sunit').setAttribute('sdist_id', sdist_id);
639                 $('serial_items_current_sunit').setAttribute('sstr_id', sstr_id);
640             }
641             var recent_sunits_file = new util.file('serial_items_recent_sunits_'+obj.docid+'.'+obj.data.server_unadorned);
642             util.widgets.save_attributes(recent_sunits_file, { 'serial_items_recent_sunits' : [ 'sunit_json' ], 'serial_items_current_sunit' : [ 'sunit_id', 'sunit_label', 'sdist_id', 'sstr_id' ] });
643                 } catch(E) {
644                         obj.error.standard_unexpected_error_alert('serial items save_sunit',E);
645                 }
646         },
647
648         'set_other_sunit' : function() {
649                 var obj = this;
650                 try {
651             JSAN.use('util.window'); var win = new util.window();
652             var select_unit_window = win.open(
653                 xulG.url_prefix(urls.XUL_SERIAL_SELECT_UNIT),
654                 '_blank',
655                 'chrome,resizable,modal,centerscreen',
656                 {'sdist_ids' : obj.sdist_ids}
657             );
658             if (!select_unit_window.sunit_selection) {
659                 return;
660             }
661
662             var selection = select_unit_window.sunit_selection;
663             var sunit_id = selection.sunit;
664             var sdist_id = selection.sdist;
665             var sstr_id = selection.sstr;
666             var label = selection.label;
667
668             obj.set_sunit(sunit_id, label, sdist_id, sstr_id);
669             obj.save_sunit(sunit_id, label, sdist_id, sstr_id);
670                 } catch(E) {
671                         obj.error.standard_unexpected_error_alert('serial items set_other_sunit',E);
672                 }
673         },
674
675         'add_sunit_to_menu' : function(sunit_id, label, sdist_id, sstr_id) {
676                 var obj = this;
677                 try {
678             if (sunit_id > 0) {
679                 // check if it is already in sunit_entries, remove it
680                 for (i = 0; i < obj.sunit_entries.length; i++) {
681                     if (obj.sunit_entries[i].id == sunit_id) {
682                         obj.sunit_entries.splice(i,1);
683                         var menu_item = $('serial_items_recent_sunits_entry_'+sunit_id);
684                         menu_item.parentNode.removeChild(menu_item);
685                         i--;
686                     }
687                 }
688                 // add to front of array
689                 obj.sunit_entries.unshift({"id" : sunit_id, "label" : label, "sdist_id" : sdist_id, "sstr_id" : sstr_id});
690                 var recent_sunits_popup = $('serial_items_recent_sunits');
691                 var new_menu_item = recent_sunits_popup.insertItemAt(0,label);
692                 new_menu_item.setAttribute('id', 'serial_items_recent_sunits_entry_'+sunit_id);
693                 new_menu_item.setAttribute('sunit_id', sunit_id);
694                 new_menu_item.setAttribute('sdist_id', sdist_id);
695                 new_menu_item.setAttribute('sstr_id', sstr_id);
696                 new_menu_item.setAttribute('command', 'cmd_set_sunit');
697
698                 // pop off from sunit_entries if it already has 10 sunits
699                 if (obj.sunit_entries.length > 10) {
700                     var sunit_info = obj.sunit_entries.pop();
701                     var menu_item = $('serial_items_recent_sunits_entry_'+sunit_info.id);
702                     menu_item.parentNode.removeChild(menu_item);
703                 }
704
705                 recent_sunits_popup.setAttribute('sunit_json', js2JSON(obj.sunit_entries));
706             }
707                 } catch(E) {
708                         obj.error.standard_unexpected_error_alert('serial items add_sunit_to_menu',E);
709                 }
710         },
711
712         'set_mode' : function(mode) {
713                 var obj = this;
714
715         if (!mode) {
716             mode = obj.mode;
717         } else {
718             obj.mode = mode;
719         }
720
721         obj.retrieve_ssubs_and_sdists();
722
723         if (mode == 'receive' || mode == 'advanced_receive') {
724             $('serial_workarea_mode_label').value = 'Recently Received';
725             if ($('serial_manage_items_show_all').checked) {
726                 obj.lists.main.sitem_retrieve_params = {};
727             } else {
728                 obj.lists.main.sitem_retrieve_params = {'date_received' : null };
729             }
730             obj.lists.main.sitem_extra_params ={'order_by' : {'sitem' : 'date_expected ASC, stream ASC'}};
731
732             obj.lists.workarea.sitem_retrieve_params = {'date_received' : {"!=" : null}};
733             obj.lists.workarea.sitem_extra_params ={'order_by' : {'sitem' : 'date_received DESC'}, 'limit' : 30};
734             if (mode == 'receive') {
735                 $('serial_manage_items_context').value = $('serialStrings').getString('staff.serial.manage_items.subscriber.label') + ':';
736                 $('cmd_set_other_sunit').setAttribute('disabled','true');
737                 $('serial_items_recent_sunits').disabled = true;
738                 obj.process_unit_selection($('serial_items_auto_per_item_menuitem'));
739                 //obj.set_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
740             } else {
741                 $('serial_manage_items_context').value = $('serialStrings').getString('staff.serial.manage_items.holder.label') + ':';
742                 $('cmd_set_other_sunit').setAttribute('disabled','false');
743                 $('serial_items_recent_sunits').disabled = false;
744             }    
745         } else { // bind mode
746             $('serial_workarea_mode_label').value = 'Bound Items in Current Working Unit';
747             $('serial_manage_items_context').value = $('serialStrings').getString('staff.serial.manage_items.holder.label') + ':';
748             if ($('serial_manage_items_show_all').checked) {
749                 obj.lists.main.sitem_retrieve_params = {};
750             } else {
751                 obj.lists.main.sitem_retrieve_params = {'date_received' : {'!=' : null}}; // unit set dynamically in 'retrieve'
752             }
753             obj.lists.main.sitem_extra_params ={'order_by' : {'sitem' : 'date_expected ASC, stream ASC'}};
754
755             obj.lists.workarea.sitem_retrieve_params = {}; // unit set dynamically in 'retrieve'
756             obj.lists.workarea.sitem_extra_params ={'order_by' : {'sitem' : 'date_received DESC'}};
757
758             $('cmd_set_other_sunit').setAttribute('disabled','false');
759             $('serial_items_recent_sunits').disabled = false;
760             // default to **NEW UNIT**
761             // For now, keep the unit static.  TODO: Eventually, keep track of and store the last used unit value for both receive and bind separately
762             // obj.set_sunit(-2, 'New Unit', '', '');
763         }
764     },
765
766         'save_settings' : function() {
767                 var obj = this;
768
769         JSAN.use('util.file'); var file = new util.file('serial_items_prefs.'+obj.data.server_unadorned);
770         util.widgets.save_attributes(file, { 'serial_item_lib_menu' : [ 'value' ], 'mode_receive' : [ 'selected' ], 'mode_advanced_receive' : [ 'selected' ], 'mode_bind' : [ 'selected' ], 'serial_manage_items_show_all' : [ 'checked' ] });
771     },
772
773         'init_lists' : function() {
774                 var obj = this;
775
776                 JSAN.use('circ.util');
777         var columns = item_columns({});
778
779         function retrieve_row(params) {
780                         try { 
781                                 var row = params.row;
782                 obj.network.simple_request(
783                     'FM_SITEM_FLESHED_BATCH_RETRIEVE.authoritative',
784                     [[row.my.sitem_id]],
785                     //[ ses(), row.my.sitem_id, {"flesh":2,"flesh_fields":{"sitem":["creator","editor","issuance","stream","unit","notes"], "sunit":["call_number"], "sstr":["distribution"]}}],
786                     function(req) {
787                         try {
788                             var robj = req.getResultObject();
789                             if (typeof robj.ilsevent != 'undefined') throw(robj);
790                             if (typeof robj.ilsevent == 'null') throw('null result');
791                             var sitem = robj[0];
792                             obj.list_sitem_map[sitem.id()] = sitem;
793                             row.my.sitem = sitem;
794                             row.my.parent_obj = obj;
795                             //params.treeitem_node.setAttribute( 'retrieve_id', js2JSON({'copy_id':copy_id,'circ_id':row.my.circ.id(),'barcode':row.my.acp.barcode(),'doc_id': ( row.my.record ? row.my.record.id() : null ) }) );
796                             params.treeitem_node.setAttribute( 'retrieve_id', js2JSON({'sitem_id':sitem.id()}) );
797                             dump('dumping... ' + js2JSON(obj.list_sitem_map[sitem.id()]));
798                             if (typeof params.on_retrieve == 'function') {
799                                 params.on_retrieve(row);
800                             }
801
802                         } catch(E) {
803                             obj.error.standard_unexpected_error_alert('staff.serial.manage_items.retrieve_row.callback_error', E);
804                         }
805                     }
806                 );
807                                 return row;
808                         } catch(E) {
809                                 obj.error.standard_unexpected_error_alert('staff.serial.manage_items.retrieve_row.error_in_retrieve_row',E);
810                                 return params.row;
811                         }
812                 }
813
814                 JSAN.use('util.list');
815
816         obj.lists = {};
817         obj.lists.main = new util.list('item_tree');
818                 obj.lists.main.init(
819                         {
820                                 'columns' : columns,
821                                 'retrieve_row' : retrieve_row,
822                                 'on_select' : function(ev) {
823                     obj.selected_list = 'main';
824                                         JSAN.use('util.functional');
825                                         var sel = obj.lists.main.retrieve_selection();
826                                         obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
827                                         var list = util.functional.map_list(
828                                                 sel,
829                                                 function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
830                                         );
831                                         if (typeof obj.on_select == 'function') {
832                                                 obj.on_select(list);
833                                         }
834                                         if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
835                                                 obj.error.sdump('D_CAT','manage_items: Calling external .on_select()\n');
836                                                 window.xulG.on_select(list);
837                                         }
838                                 }
839                         }
840                 );
841
842         obj.lists.workarea = new util.list('workarea_tree');
843                 obj.lists.workarea.init(
844                         {
845                                 'columns' : columns,
846                                 'retrieve_row' : retrieve_row,
847                                 'on_select' : function(ev) {
848                     obj.selected_list = 'workarea';
849                                         JSAN.use('util.functional');
850                                         var sel = obj.lists.workarea.retrieve_selection();
851                                         obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
852                                         var list = util.functional.map_list(
853                                                 sel,
854                                                 function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
855                                         );
856                                         if (typeof obj.on_select == 'function') {
857                                                 obj.on_select(list);
858                                         }
859                                         if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
860                                                 obj.error.sdump('D_CAT','serctrl: Calling external .on_select()\n');
861                                                 window.xulG.on_select(list);
862                                         } else {
863                                                 obj.error.sdump('D_CAT','serctrl: No external .on_select()\n');
864                                         }
865                                 }
866                         }
867                 );
868     },
869
870         'refresh_list' : function(list_name) {
871         var obj = this;
872
873         //TODO Optimize this?
874         obj.retrieve(list_name);
875     },
876
877     // accepts a list of ids or a list of objects
878     'refresh_rows' : function(list) {
879         var obj = this;
880
881         var id_list;
882
883         if (typeof list[0] == 'object') {
884             id_list = util.functional.map_list(
885                 list,
886                 function(o) {
887                     return o.id()
888                 }
889             );
890         } else {
891             id_list = list;
892         }
893
894         for (var i = 0; i < id_list.length; i++) {
895             obj.lists[obj.selected_list].refresh_row(obj.row_map[id_list[i]]);
896         }
897     },
898
899         'retrieve' : function(list_name) {
900                 var obj = this;
901         var list = obj.lists[list_name];
902         
903                 list.clear();
904
905         if (!obj.sdist_ids.length) { // no sdists to retrieve items for
906             return;
907         }
908
909         var rparams = list.sitem_retrieve_params;
910         var robj;
911         rparams['+sstr'] = { "distribution" : obj.sdist_ids };
912
913         if (obj.mode == 'bind') {
914             if (list_name == 'workarea') {
915                 rparams['unit'] = obj.current_sunit_id;
916             } else if (!$('serial_manage_items_show_all').checked){
917                 rparams['unit'] = {"<>" : obj.current_sunit_id};
918             }
919         }
920
921         var other_params = list.sitem_extra_params;
922         other_params.join = 'sstr';
923
924         robj = obj.network.simple_request(
925             'FM_SITEM_ID_LIST',
926             [ ses(), rparams, other_params ]
927         );
928         if (!robj) {
929             robj = [];
930         } else if (typeof robj.ilsevent!='undefined') {
931             obj.error.standard_unexpected_error_alert('Failed to retrieve serial item ID list',E);
932         } else if (!robj.length) {
933             robj = [robj];
934         }
935
936         for (i = 0; i < robj.length; i++) {
937             var nparams = list.append( { 'row' : { 'my' : { 'sitem_id' : robj[i] } }, 'to_bottom' : true, 'no_auto_select' : true } );
938             obj.row_map[robj[i]] = nparams;
939         }
940         },
941
942         'on_select' : function(list) {
943
944                 dump('manage_items.on_select list = ' + js2JSON(list) + '\n');
945
946                 var obj = this;
947
948                 /*obj.controller.view.cmd_items_claimed_returned.setAttribute('disabled','false');
949                 obj.controller.view.sel_mark_items_missing.setAttribute('disabled','false');*/
950
951                 obj.retrieve_ids = list;
952         },
953
954     'process_unit_selection' : function(menuitem) {
955         var obj = this;
956
957         var label = menuitem.label;
958         var sunit_id = menuitem.getAttribute('sunit_id');
959         var sdist_id = menuitem.getAttribute('sdist_id');
960         var sstr_id = menuitem.getAttribute('sstr_id');
961         obj.set_sunit(sunit_id, label, sdist_id, sstr_id);
962         obj.save_sunit(sunit_id, label, sdist_id, sstr_id);
963         if (obj.mode == 'bind') {
964             obj.refresh_list('main');
965             obj.refresh_list('workarea');
966         }
967     },
968
969     'view_notes' : function(type) {
970         var obj = this;
971
972         if (!obj.retrieve_ids || obj.retrieve_ids.length == 0) return;
973
974         var object_id_fn;
975         var function_type;
976         var object_type;
977         var constructor;
978
979         switch(type) {
980             case 'sitem':
981                 object_id_fn = function(item) { return item.id() };
982                 title_fn = function(item) { return fieldmapper.IDL.fmclasses.sitem.field_map.id.label + ' ' + item.id() };
983                 function_type = 'SIN';
984                 object_type = 'item';
985                 constructor = sin;
986                 break;
987             case 'sdist':
988                 object_id_fn = function(item) { return item.stream().distribution() };
989                 title_fn = function(item) {
990                     var sdist_id = object_id_fn(item);
991                     return obj.sdist_map[sdist_id].label()
992                         + ' -- ' + obj.sdist_map[sdist_id].holding_lib().shortname()
993                         + ' (' + fieldmapper.IDL.fmclasses.sdist.field_map.id.label + ' ' + sdist_id + ')'
994                 };
995                 function_type = 'SDISTN';
996                 object_type = 'distribution';
997                 constructor = sdistn;
998                 break;
999             case 'ssub':
1000                 object_id_fn = function(item) { return item.issuance().subscription().id() };
1001                 title_fn = function(item) {
1002                     var ssub_id = object_id_fn(item);
1003                     return obj.ssub_map[ssub_id].owning_lib().shortname()
1004                         + ' (' + fieldmapper.IDL.fmclasses.ssub.field_map.id.label + ' ' + ssub_id + ')'
1005                 };
1006                 function_type = 'SSUBN';
1007                 object_type = 'subscription';
1008                 constructor = ssubn;
1009                 break;
1010             default:
1011                 return;
1012         }
1013
1014         var seen_ids = {};
1015         for (var i = 0; i < obj.retrieve_ids.length; i++) {
1016             var item = obj.list_sitem_map[obj.retrieve_ids[i].sitem_id];
1017             var obj_id = object_id_fn(item);
1018             if (seen_ids[obj_id]) continue;
1019             JSAN.use('util.window'); var win = new util.window();
1020             win.open(
1021                 urls.XUL_SERIAL_NOTES,
1022                 '','chrome,resizable,modal',
1023                 { 'object_id' : obj_id, 'function_type' : function_type, 'object_type' : object_type, 'constructor' : constructor, 'title' : $('serialStrings').getString('staff.serial.'+type+'_editor.notes') + ' -- ' + title_fn(item) }
1024             );
1025             seen_ids[obj_id] = 1;
1026         }
1027     }
1028 }
1029
1030 function item_columns(modify,params) {
1031
1032     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
1033     //JSAN.use('util.network'); var network = new util.network();
1034
1035     var c = [
1036         {
1037             'id' : 'sitem_id',
1038             'label' : 'Item ID',
1039             'flex' : 1,
1040             'primary' : false,
1041             'hidden' : false,
1042             'render' : function(my) { return my.sitem.id(); },
1043             'persist' : 'hidden width ordinal'
1044         },
1045         {
1046             'id' : 'label',
1047             'label' : 'Issuance Label',
1048             'flex' : 1,
1049             'primary' : false,
1050             'hidden' : false,
1051             'render' : function(my) { return my.sitem.issuance().label(); },
1052             'persist' : 'hidden width ordinal'
1053         },
1054         {
1055             'id' : 'distribution',
1056             'label' : 'Distribution',
1057             'flex' : 1,
1058             'primary' : false,
1059             'hidden' : false,
1060             'persist' : 'hidden width ordinal',
1061             'render' : function(my) { return my.parent_obj.sdist_map[my.sitem.stream().distribution()].label(); }
1062         },
1063         {
1064             'id' : 'distribution_ou',
1065             'label' : $('serialStrings').getString('staff.serial.manage_items.holder.label'),
1066             'flex' : 1,
1067             'primary' : false,
1068             'hidden' : false,
1069             'persist' : 'hidden width ordinal',
1070             'render' : function(my) { return my.parent_obj.sdist_map[my.sitem.stream().distribution()].holding_lib().shortname(); }
1071         },
1072         {
1073             'id' : 'stream_id',
1074             'label' : 'Stream ID',
1075             'flex' : 1,
1076             'primary' : false,
1077             'hidden' : false,
1078             'persist' : 'hidden width ordinal',
1079             'render' : function(my) { return my.sitem.stream().id(); }
1080         },
1081         {
1082             'id' : 'date_published',
1083             'label' : 'Date Published',
1084             'flex' : 1,
1085             'primary' : false,
1086             'hidden' : false,
1087             'render' : function(my) { return my.sitem.issuance().date_published().substr(0,10); },
1088             'persist' : 'hidden width ordinal'
1089         },
1090         {
1091             'id' : 'date_expected',
1092             'label' : 'Date Expected',
1093             'flex' : 1,
1094             'primary' : false,
1095             'hidden' : false,
1096             'render' : function(my) { return my.sitem.date_expected().substr(0,10); },
1097             'persist' : 'hidden width ordinal'
1098         },
1099         {
1100             'id' : 'date_received',
1101             'label' : 'Date Received',
1102             'flex' : 1,
1103             'primary' : false,
1104             'hidden' : false,
1105             'render' : function(my) { return my.sitem.date_received().substr(0,10); },
1106             'persist' : 'hidden width ordinal'
1107         },
1108         {
1109             'id' : 'notes',
1110             'label' : $('serialStrings').getString('staff.serial.manage_items.notes_column.label'),
1111             'flex' : 1,
1112             'primary' : false,
1113             'hidden' : false,
1114             'render' : function(my) { return my.sitem.notes().length + ' / ' + my.parent_obj.sdist_map[my.sitem.stream().distribution()].notes().length + ' / ' + my.parent_obj.ssub_map[my.sitem.issuance().subscription().id()].notes().length; },
1115             'persist' : 'hidden width ordinal'
1116         },
1117         {
1118             'id' : 'call_number',
1119             'label' : 'Call Number',
1120             'flex' : 1,
1121             'primary' : false,
1122             'hidden' : false,
1123             'persist' : 'hidden width ordinal',
1124             'render' : function(my) { return my.sitem.unit().call_number().label(); }
1125         },
1126         {
1127             'id' : 'unit_id_contents',
1128             'label' : 'Unit ID / Contents',
1129             'flex' : 1,
1130             'primary' : false,
1131             'hidden' : false,
1132             'render' : function(my) { return '[' + my.sitem.unit().id() + '] ' + my.sitem.unit().summary_contents() ; },
1133             'persist' : 'hidden width ordinal'
1134         },
1135         {
1136             'id' : 'creator',
1137             'label' : 'Creator',
1138             'flex' : 1,
1139             'primary' : false,
1140             'hidden' : true,
1141             'persist' : 'hidden width ordinal',
1142             'render' : function(my) { return my.sitem.creator().usrname(); }
1143         },
1144         {
1145             'id' : 'create_date',
1146             'label' : document.getElementById('circStrings').getString('staff.circ.utils.create_date'),
1147             'flex' : 1,
1148             'primary' : false,
1149             'hidden' : true,
1150             'persist' : 'hidden width ordinal',
1151             'render' : function(my) { return my.sitem.create_date().substr(0,10); }
1152         },
1153         {
1154             'id' : 'editor',
1155             'label' : 'Editor',
1156             'flex' : 1,
1157             'primary' : false,
1158             'hidden' : true,
1159             'persist' : 'hidden width ordinal',
1160             'render' : function(my) { return my.sitem.editor().usrname(); }
1161         },
1162         {
1163             'id' : 'edit_date',
1164             'label' : document.getElementById('circStrings').getString('staff.circ.utils.edit_date'),
1165             'flex' : 1,
1166             'primary' : false,
1167             'hidden' : false,
1168             'persist' : 'hidden width ordinal',
1169             'render' : function(my) { return my.sitem.edit_date().substr(0,10); }
1170         },
1171         {
1172             'id' : 'holding_code',
1173             'label' : 'Holding Code',
1174             'flex' : 1,
1175             'primary' : false,
1176             'hidden' : true,
1177             'render' : function(my) { return my.sitem.issuance().holding_code(); },
1178             'persist' : 'hidden width ordinal'
1179         },
1180         {
1181             'id' : 'holding_type',
1182             'label' : 'Holding Type',
1183             'flex' : 1,
1184             'primary' : false,
1185             'hidden' : true,
1186             'render' : function(my) { return my.sitem.issuance().holding_type(); },
1187             'persist' : 'hidden width ordinal'
1188         },
1189         {
1190             'id' : 'holding_link_id',
1191             'label' : 'Holding Link ID',
1192             'flex' : 1,
1193             'primary' : false,
1194             'hidden' : true,
1195             'render' : function(my) { return my.sitem.issuance().holding_link_id(); },
1196             'persist' : 'hidden width ordinal'
1197         }
1198     ];
1199     for (var i = 0; i < c.length; i++) {
1200         if (modify[ c[i].id ]) {
1201             for (var j in modify[ c[i].id ]) {
1202                 c[i][j] = modify[ c[i].id ][j];
1203             }
1204         }
1205     }
1206     if (params) {
1207         if (params.just_these) {
1208             JSAN.use('util.functional');
1209             var new_c = [];
1210             for (var i = 0; i < params.just_these.length; i++) {
1211                 var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
1212                 new_c.push( function(y){ return y; }( x ) );
1213             }
1214             c = new_c;
1215         }
1216         if (params.except_these) {
1217             JSAN.use('util.functional');
1218             var new_c = [];
1219             for (var i = 0; i < c.length; i++) {
1220                 var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
1221                 if (!x) new_c.push(c[i]);
1222             }
1223             c = new_c;
1224         }
1225     }
1226     //return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
1227     return c;
1228 };
1229
1230 spawn_sitem_editor = function(params) {
1231     try {
1232         if (!params.sitem_ids && !params.sitems) return;
1233         if (params.sitem_ids && params.sitem_ids.length == 0) return;
1234         if (params.sitems && params.sitems.length == 0) return;
1235         if (params.sitem_ids) params.sitem_ids = js2JSON(params.sitem_ids); // legacy
1236         if (!params.caller_handles_update) params.handle_update = 1; // legacy
1237
1238         var obj = {};
1239         JSAN.use('util.network'); obj.network = new util.network();
1240         JSAN.use('util.error'); obj.error = new util.error();
1241
1242         var title = '';
1243         if (params.sitem_ids && params.sitem_ids.length > 1 && params.do_edit == 1)
1244             title = 'Batch Edit Items';
1245         else /* if(params.sitems && params.sitems.length > 1 && params.do_edit == 1)
1246             title = 'Batch View Items';
1247         else if(params.sitem_ids && params.sitem_ids.length == 1) */
1248             title = 'Edit Item';/*
1249         else
1250             title = 'View Item';*/
1251
1252         JSAN.use('util.window'); var win = new util.window();
1253         params.in_modal = true;
1254         var my_xulG = win.open(
1255             (urls.XUL_SERIAL_ITEM_EDITOR),
1256             title,
1257             'chrome,modal,resizable',
1258             params
1259         );
1260         if (my_xulG.sitems && params.do_edit) {
1261             return my_xulG.sitems;
1262         } else {
1263             return [];
1264         }
1265     } catch(E) {
1266         JSAN.use('util.error'); var error = new util.error();
1267         error.standard_unexpected_error_alert('error in spawn_sitem_editor',E);
1268     }
1269 }
1270
1271 dump('exiting manage_items.js\n');