[open-ils-commits] r16931 - in branches/seials-integration/Open-ILS/xul/staff_client/server: . serial (dbwells)

svn at svn.open-ils.org svn at svn.open-ils.org
Wed Jul 14 14:36:15 EDT 2010


Author: dbwells
Date: 2010-07-14 14:36:11 -0400 (Wed, 14 Jul 2010)
New Revision: 16931

Added:
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/editor_base.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.xul
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/notes.xul
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.xul
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sdist_editor.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sdist_editor.xul
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/select_aou.xul
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/serctrl_main.xul
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/siss_editor.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/siss_editor.xul
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/ssub_editor.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/ssub_editor.xul
Log:
Initial commit of the 'main' serial control view, plus the xul/js supporting files for one tab, the subscriptions manager.


Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/editor_base.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/editor_base.js	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/editor_base.js	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,588 @@
+dump('entering serial/editor_base.js\n');
+// vim:noet:sw=4:ts=4:
+
+if (typeof serial == 'undefined') serial = {};
+
+serial.editor_base = {
+
+    'editor_base_init' : function (params) {
+        var obj = this;
+        try {
+            /******************************************************************************************************/
+            /* setup JSAN and some initial libraries */
+
+            netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+            if (typeof JSAN == 'undefined') {
+                throw( $('commonStrings').getString('common.jsan.missing') );
+            }
+            JSAN.errorLevel = "die"; // none, warn, or die
+            JSAN.addRepository('/xul/server/');
+            JSAN.use('util.error'); obj.error = new util.error();
+            obj.error.sdump('D_TRACE','my_init() for serial/editor_base.js');
+
+            JSAN.use('util.functional');
+            JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
+            JSAN.use('util.network'); obj.network = new util.network();
+
+
+            /******************************************************************************************************/
+            /* base vars */
+
+            obj.docid = xul_param('docid',{'modal_xulG':true});
+            
+            if (typeof params.handle_update == 'undefined') {
+                obj.handle_update = xul_param('handle_update',{'modal_xulG':true});
+            } else {
+                obj.handle_update = params.handle_update;
+            }
+
+            obj.trigger_refresh = params.trigger_refresh;
+            obj.refresh_command = params.refresh_command;
+            var fm_type = obj.fm_type;
+            var fm_type_plural = obj.fm_type_plural;
+            var retrieve_function = params.retrieve_function;
+            var retrieve_params = params.retrieve_params;
+            if (!retrieve_params) {
+                retrieve_params = [];
+            }
+
+            /******************************************************************************************************/
+            /* Get the fm_type ids from various sources and flesh them */
+
+            var fm_type_ids = params[fm_type + '_ids'];
+            if (!fm_type_ids) fm_type_ids = xul_param(fm_type + '_ids',{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xulG':true,'JSON2js_if_xpcom':true,'stash_name':'temp_' + fm_type + '_ids','clear_xpcom':true,'modal_xulG':true});
+            if (!fm_type_ids) fm_type_ids = [];
+
+            obj[fm_type_plural] = [];
+            retrieve_params.push(fm_type_ids);
+            if (fm_type_ids.length > 0) obj[fm_type_plural] = obj.network.simple_request(
+                retrieve_function,
+                retrieve_params
+            );
+
+
+            /******************************************************************************************************/
+            /* And other fleshed copies if any */
+
+            if (!obj[fm_type_plural]) obj[fm_type_plural] = [];
+            var fms = params[fm_type_plural];
+            if (!fms) fms = xul_param(fm_type_plural,{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xpcom':true,'stash_name':'temp_' + fm_type_plural,'clear_xpcom':true,'modal_xulG':true})
+            if (fms) obj[fm_type_plural] = obj[fm_type_plural].concat(fms);
+
+
+            // If we have just one, wrap in array
+            if (!obj[fm_type_plural].length) {
+                obj[fm_type_plural] = [obj[fm_type_plural]];
+            }
+
+
+            /******************************************************************************************************/
+
+            //obj.init_panes0();
+            obj.init_panes();
+
+            /******************************************************************************************************/
+            /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
+
+            var do_edit;
+            if (typeof params.do_edit == 'undefined') {
+                do_edit = xul_params('do_edit',{'modal_xulG':true});
+            } else {
+                do_edit = params.do_edit;
+            }
+
+            if (do_edit) { 
+
+                // Editor desired, but let's check permissions
+                obj.do_edit = false;
+
+                try {
+                    /* FIXME: add permission check
+                    var check = obj.network.simple_request(
+                        'PERM_MULTI_ORG_CHECK',
+                        [ 
+                            ses(), 
+                            obj.data.list.au[0].id(), 
+                            util.functional.map_list(
+                                obj[fm_type_plural],
+                                function (o) {
+                                    var lib;
+                                    var cn_id = o.call_number();
+                                    if (cn_id == -1) {
+                                        lib = o.circ_lib(); // base perms on circ_lib instead of owning_lib if pre-cat
+                                    } else {
+                                        if (! obj.map_acn[ cn_id ]) {
+                                            var req = obj.network.simple_request('FM_ACN_RETRIEVE.authoritative',[ cn_id ]);
+                                            if (typeof req.ilsevent == 'undefined') {
+                                                obj.map_acn[ cn_id ] = req;
+                                                lib = obj.map_acn[ cn_id ].owning_lib();
+                                            } else {
+                                                lib = o.circ_lib();
+                                            }
+                                        } else {
+                                            lib = obj.map_acn[ cn_id ].owning_lib();
+                                        }
+                                    }
+                                    return typeof lib == 'object' ? lib.id() : lib;
+                                }
+                            ),
+                            obj[fm_type_plural].length == 1 ? [ 'UPDATE_COPY' ] : [ 'UPDATE_COPY', 'UPDATE_BATCH_COPY' ]
+                        ]
+                    ); */
+                    var check = [];
+                    obj.do_edit = check.length == 0;
+                } catch(E) {
+                    obj.error.standard_unexpected_error_alert('batch permission check',E);
+                }
+
+                if (obj.do_edit) {
+                    $(fm_type + '_save').setAttribute('hidden','false'); 
+                } else {
+                    $('top_nav').setAttribute('hidden','true');
+                }
+            } else {
+                $('top_nav').setAttribute('hidden','true');
+            }
+
+
+            if (obj[fm_type_plural].length > 0 && obj[fm_type_plural][0].isnew()) {
+                obj.mode = 'create';
+                if (obj.can_have_notes) $(fm_type + '_notes').setAttribute('hidden','true');
+                $(fm_type + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create'));
+                $(fm_type + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create.accesskey'));
+            } else if (obj.mode == 'create') { // switching from create to modify
+                obj.mode = 'modify';
+                if (obj.can_have_notes) $(fm_type + '_notes').setAttribute('hidden','false');
+                $(fm_type + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify'));
+                $(fm_type + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify.accesskey'));
+            }
+/*else {
+                obj.panes_and_field_names.left_pane = 
+                    [
+                        [
+                            $('catStrings').getString('staff.cat.copy_editor.status'),
+                            { 
+                                render: 'typeof fm.status() == "object" ? fm.status().name() : obj.data.hash.ccs[ fm.status() ].name()', 
+                                input: obj.safe_to_edit_copy_status() ? 'c = function(v){ obj.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.data.list.ccs, function(obj) { return [ obj.name(), obj.id(), typeof my_constants.magical_statuses[obj.id()] != "undefined" ? true : false ]; } ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);' : undefined,
+                                //input: 'c = function(v){ obj.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( util.functional.filter_list( obj.data.list.ccs, function(obj) { return typeof my_constants.magical_statuses[obj.id()] == "undefined"; } ), function(obj) { return [ obj.name(), obj.id() ]; } ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                            }
+                        ]
+                    ].concat(obj.panes_and_field_names.left_pane);
+            }*/
+
+            if (obj[fm_type_plural].length != 1) {
+                document.getElementById(fm_type + '_notes').setAttribute('hidden','true');
+            }
+
+            // clear change markers
+            obj.changed = {};
+
+            /******************************************************************************************************/
+            /* Show the Record Details? (only for 'in_modal' mode)*/
+
+            var bdb;
+            if (xul_param('in_modal',{'modal_xulG':true}) && obj.docid) {
+                bdb = document.getElementById('brief_display_box'); while(bdb.firstChild) bdb.removeChild(bdb.lastChild);
+                var brief_display = document.createElement('iframe'); bdb.appendChild(brief_display); 
+                brief_display.setAttribute( 'src', urls.XUL_BIB_BRIEF + '?docid=' + obj.docid); // this is a modal window, so can't push in xulG
+                brief_display.setAttribute( 'flex','1' );
+            }
+
+            /******************************************************************************************************/
+            /* Backup copies :) */
+
+            obj['original_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
+
+        } catch(E) {
+            var err_msg = $("commonStrings").getFormattedString('common.exception', ['serial/' + fm_type +'_editor.js - init', E]);
+            try { obj.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
+            alert(err_msg);
+        }
+    },
+
+    /******************************************************************************************************/
+    /* Restore backup copies */
+
+    'editor_base_reset' : function() {
+        var obj = this;
+        var fm_type_plural = obj.fm_type_plural;
+
+        obj.changed = {};
+        obj[fm_type_plural] = JSON2js( obj['original_' + fm_type_plural] );
+        obj.summarize( obj[fm_type_plural] );
+        obj.render();
+    },
+
+    /******************************************************************************************************/
+    /* Apply a value to a specific field on all the copies being edited */
+    /* Don't forget to use util.money.sanitize if dealing with money values */
+
+    'editor_base_apply' : function(field, value, loop_func) {
+        var obj = this;
+        var fm_type_plural = obj.fm_type_plural;
+
+        var do_loop_func = (typeof loop_func == 'function');
+
+        obj.error.sdump('D_TRACE','applying field = <' + field + '>  value = <' + value + '>\n');
+        if (value == '<HACK:KLUDGE:NULL>') value = null;
+        for (var i = 0; i < obj[fm_type_plural].length; i++) {
+            var fm = obj[fm_type_plural][i];
+            try {
+                fm[field]( value ); fm.ischanged('1');
+                if (do_loop_func) {
+                    loop_func(fm);
+                }
+            } catch(E) {
+                alert(E);
+            }
+        }
+    },
+
+
+    /******************************************************************************************************/
+    /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+    'editor_base_summarize' : function(my_fms) {
+        var obj = this;
+        /******************************************************************************************************/
+        /* Setup */
+
+        JSAN.use('util.date'); JSAN.use('util.money');
+        obj.summary = {};
+        obj.field_names = [];
+        for (var i in obj.panes_and_field_names) {
+            obj.field_names = obj.field_names.concat( obj.panes_and_field_names[i] );
+        }
+
+        /******************************************************************************************************/
+        /* Loop through the field names */
+
+        for (var i = 0; i < obj.field_names.length; i++) {
+
+            var field_name = obj.field_names[i][0];
+            var render = obj.field_names[i][1].render;
+            var attr = obj.field_names[i][1].attr;
+            var value_key = obj.field_names[i][1].value_key;
+            var dropdown_key = obj.field_names[i][1].dropdown_key;
+            obj.summary[ field_name ] = {};
+
+            /******************************************************************************************************/
+            /* Loop through the copies */
+
+            for (var j = 0; j < my_fms.length; j++) {
+
+                var fm = my_fms[j];
+                var cmd = render || ('fm.' + field_name + '();');
+                var value = '???';
+
+                /**********************************************************************************************/
+                /* Try to retrieve the value for this field for this copy */
+
+                try { 
+                    value = eval( cmd );
+                    if (typeof(value) == 'undefined') {
+                        value = "";
+                    }
+                    if (dropdown_key) {
+                        obj.editor_values[value_key] = eval(dropdown_key);
+                    } else if (value_key) {
+                        obj.editor_values[value_key] = value;
+                    }
+                    if (value == "") {
+                        value = "<Unset>";
+                    }
+                } catch(E) { 
+                    obj.error.sdump('D_ERROR','Attempted ' + cmd + '\n' +  E + '\n'); 
+                }
+                if (typeof value == 'object' && value != null) {
+                    alert('FIXME: field_name = <' + field_name + '>  value = <' + js2JSON(value) + '>\n');
+                }
+
+                /**********************************************************************************************/
+                /* Tally the count */
+
+                if (obj.summary[ field_name ][ value ]) {
+                    obj.summary[ field_name ][ value ]++;
+                } else {
+                    obj.summary[ field_name ][ value ] = 1;
+                }
+            }
+        }
+        obj.error.sdump('D_TRACE','summary = ' + js2JSON(obj.summary) + '\n');
+    },
+
+    /******************************************************************************************************/
+    /* Display the summarized data and inputs for editing */
+
+    'editor_base_render' : function() {
+        var obj = this;
+        var fm_type = obj.fm_type;
+
+        /******************************************************************************************************/
+        /* Library setup and clear any existing interface */
+
+        JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
+
+        for (var i in obj.panes_and_field_names) {
+            var p = document.getElementById(i);
+            if (p) util.widgets.remove_children(p);
+        }
+
+        /******************************************************************************************************/
+        /* Prepare the panes */
+
+        var groupbox; var caption; var vbox; var grid; var rows;
+        
+        /******************************************************************************************************/
+        /* Loop through the field names */
+
+        for (h in obj.panes_and_field_names) {
+            if (!document.getElementById(h)) continue;
+            for (var i = 0; i < obj.panes_and_field_names[h].length; i++) {
+                try {
+                    var f = obj.panes_and_field_names[h][i]; var fn = f[0]; var attr = f[1].attr;
+                    groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
+                    if (attr) {
+                        for (var a in attr) {
+                            groupbox.setAttribute(a,attr[a]);
+                        }
+                    }
+                    if (typeof obj.changed[fn] != 'undefined') {
+                        groupbox.setAttribute('class','copy_editor_field_changed');
+                    }
+                    caption = document.createElement('caption'); groupbox.appendChild(caption);
+                    caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
+                    vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
+                    grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
+                    grid.setAttribute('flex','1');
+                    rows = grid.lastChild;
+                    var row;
+                    
+                    /**************************************************************************************/
+                    /* Loop through each value for the field */
+
+                    for (var j in obj.summary[fn]) {
+                        var value = j; var count = obj.summary[fn][j];
+                        row = document.createElement('row'); rows.appendChild(row);
+                        var label1 = document.createElement('description'); row.appendChild(label1);
+                        label1.setAttribute('id',fn + '_label');
+                        //if (obj.special_exception[ fn ]) {
+                        //	obj.special_exception[ fn ]( label1, value );
+                        //} else {
+                            label1.appendChild( document.createTextNode(value) );
+                        //}
+                        var label2 = document.createElement('description'); row.appendChild(label2);
+                        var fm_count;
+                        if (count == 1) {
+                            fm_count = $('serialStrings').getString('staff.serial.' + fm_type +'_editor.count');
+                        } else {
+                            fm_count = $('serialStrings').getFormattedString('staff.serial.' + fm_type +'_editor.count.plural', [count]);
+                        }
+                        label2.appendChild( document.createTextNode(fm_count) );
+                    }
+                    var hbox = document.createElement('hbox'); 
+                    hbox.setAttribute('id',fn);
+                    groupbox.appendChild(hbox);
+                    var hbox2 = document.createElement('hbox');
+                    groupbox.appendChild(hbox2);
+
+                    /**************************************************************************************/
+                    /* Render the input widget */
+
+                    if (f[1].input && obj.do_edit) {
+                        obj.render_input(hbox,f[1]);
+                    }
+
+                } catch(E) {
+                    obj.error.sdump('D_ERROR','copy editor: ' + E + '\n');
+                }
+            }
+        }
+        
+        
+        /******************************************************************************************************/
+        /* Synchronize stat cat visibility with library filter menu, and default template selection */
+        JSAN.use('util.file'); 
+        var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
+        obj[fm_type + '_editor_prefs'] = util.widgets.load_attributes(file);
+        for (var i in obj[fm_type + '_editor_prefs']) {
+            if (i.match(/filter_/) && obj[fm_type + '_editor_prefs'][i].checked == '') {
+                try { 
+                    obj.toggle_stat_cat_display( document.getElementById(i) ); 
+                } catch(E) { alert(E); }
+            }
+        }
+        if (obj.template_menu) obj.template_menu.value = obj.template_menu.getAttribute('value');
+
+    },
+
+    /******************************************************************************************************/
+    /* This actually draws the change button and input widget for a given field */
+    'editor_base_render_input' : function(node, blob) {
+        var obj = this;
+        var fm_type_plural = obj.fm_type_plural;
+
+        try {
+            // node = hbox ;    groupbox ->  hbox, hbox
+
+            var groupbox = node.parentNode;
+            var caption = groupbox.firstChild;
+            var vbox = node.previousSibling;
+            var hbox = node;
+            var hbox2 = node.nextSibling;
+
+            var input_cmd = blob.input;
+            var render_cmd = blob.render;
+            var attr = blob.attr;
+
+            var block = false; var first = true;
+
+            function on_mouseover(ev) {
+                groupbox.setAttribute('style','background: white');
+            }
+
+            function on_mouseout(ev) {
+                groupbox.setAttribute('style','');
+            }
+
+            vbox.addEventListener('mouseover',on_mouseover,false);
+            vbox.addEventListener('mouseout',on_mouseout,false);
+            groupbox.addEventListener('mouseover',on_mouseover,false);
+            groupbox.addEventListener('mouseout',on_mouseout,false);
+            groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
+            groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
+
+            function on_click(ev){
+                try {
+                    if (block) return; block = true;
+
+                    function post_c(v) {
+                        try {
+                            /* dbw2 not needed?
+                            var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
+                            var f;
+                            switch(t) {
+                                case 'attribute' :
+                                    f = input_cmd.match(/apply.?\("(.+?)",/)[1];
+                                break;
+                                case 'stat_cat' :
+                                    f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
+                                break;
+                                case 'owning_lib' :
+                                    f = null;
+                                break;
+                            }
+                            obj.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v }; */
+                            obj.changed[ hbox.id ] = true;
+                            block = false;
+                            setTimeout(
+                                function() {
+                                    obj.summarize( obj[fm_type_plural] );
+                                    obj.render();
+                                    document.getElementById(caption.id).focus();
+                                }, 0
+                            );
+                        } catch(E) {
+                            obj.error.standard_unexpected_error_alert('post_c',E);
+                        }
+                    }
+                    var x; var c; eval( input_cmd );
+                    if (x) {
+                        util.widgets.remove_children(vbox);
+                        util.widgets.remove_children(hbox);
+                        util.widgets.remove_children(hbox2);
+                        hbox.appendChild(x);
+                        var apply = document.createElement('button');
+                        apply.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.apply.label'));
+                        apply.setAttribute('accesskey', $('catStrings').getString('staff.cat.copy_editor.apply.accesskey'));
+                        hbox2.appendChild(apply);
+                        apply.addEventListener('command',function() { c(x.value); },false);
+                        var cancel = document.createElement('button');
+                        cancel.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.cancel.label'));
+                        cancel.addEventListener('command',function() { setTimeout( function() { obj.summarize( obj[fm_type_plural] ); obj.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
+                        hbox2.appendChild(cancel);
+                        setTimeout( function() { x.focus(); }, 0 );
+                    }
+                } catch(E) {
+                    obj.error.standard_unexpected_error_alert('render_input',E);
+                }
+            }
+            vbox.addEventListener('click',on_click, false);
+            hbox.addEventListener('click',on_click, false);
+            caption.addEventListener('click',on_click, false);
+            caption.addEventListener('keypress',function(ev) {
+                if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
+            }, false);
+            caption.setAttribute('style','-moz-user-focus: normal');
+            caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
+            caption.setAttribute('onblur','this.setAttribute("class","")');
+
+        } catch(E) {
+            obj.error.sdump('D_ERROR',E + '\n');
+        }
+    },
+
+    /******************************************************************************************************/
+    /* save or store the updated fms as appropriate */
+
+    'editor_base_save' : function(update_method) {
+        var obj = this;
+        var fm_type_plural = obj.fm_type_plural;
+        var fm_type= obj.fm_type;
+
+        try {
+            if (obj.handle_update) {
+                try {
+                    //send fms to the update function
+                    var r = obj.network.request(
+                        'open-ils.serial',
+                        update_method,
+                        [ ses(), obj[fm_type_plural] ]
+                    );
+                    if (typeof r.ilsevent != 'undefined') {
+                        obj.error.standard_unexpected_error_alert('serial ' + fm_type + ' update',r);
+                    } else {
+                        alert($('serialStrings').getString('staff.serial.editor_base.handle_update.success'));
+                        obj.changed = {};
+                        if (obj.trigger_refresh) {
+                            obj.refresh_command();
+                        } else {
+                            obj.render();
+                        }
+                    }
+                    /* FIXME -- revisit the return value here */
+                } catch(E) {
+                    alert($('serialStrings').getString('staff.serial.editor_base.handle_update.error') + ' ' + js2JSON(E));
+                }
+            } else if (xul_param('in_modal',{'modal_xulG':true})) {
+                // TODO: this is to perhaps allow this editor to be called
+                // in a modal window, but is unfinished functionality
+                var xulG = {};
+                xulG[fm_type_plural] = obj[fm_type_plural];
+                update_modal_xulG(xulG);
+                window.close();
+            } else {
+                obj.data['temp_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
+                obj.data.stash('temp_' + fm_type_plural);
+            }
+        } catch(E) {
+            obj.error.standard_unexpected_error_alert(fm_type + '_editor save',E);
+        }
+    },
+
+    /******************************************************************************************************/
+    'editor_base_save_attributes' : function() {
+        var obj = this;
+        var fm_type = obj.fm_type;
+
+        JSAN.use('util.widgets'); JSAN.use('util.file'); var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
+        var what_to_save = {};
+        for (var i in obj[fm_type + '_editor_prefs']) {
+            what_to_save[i] = [];
+            for (var j in obj[fm_type + '_editor_prefs'][i]) what_to_save[i].push(j);
+        }
+        util.widgets.save_attributes(file, what_to_save );
+    }
+};
+
+dump('exiting serial/editor_base.js\n');

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.js	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.js	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,1657 @@
+dump('entering serial/manage_subs.js\n');
+// vim:noet:sw=4:ts=4:
+
+if (typeof serial == 'undefined') serial = {};
+serial.manage_subs = function (params) {
+    try {
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+        JSAN.use('util.error'); this.error = new util.error();
+    } catch(E) {
+        dump('serial/manage_subs: ' + E + '\n');
+    }
+};
+
+serial.manage_subs.prototype = {
+
+    'map_tree' : {},
+    'map_ssub' : {},
+    'map_sdist' : {},
+    'map_siss' : {},
+    'map_scap' : {},
+    'sel_list' : [],
+    'funcs' : [],
+    'editor_indexes' : { 'ssub' : 1, 'sdist' : 2, 'siss' : 3, 'scap' : 4 },
+
+    'ids_from_sel_list' : function(type) {
+        var obj = this;
+        var list = util.functional.map_list(
+            util.functional.filter_list(
+                obj.sel_list,
+                function (o) {
+                    return o.split(/_/)[0] == type;
+                }
+            ),
+            function (o) {
+                return o.split(/_/)[1];
+            }
+        );
+
+        return list;
+    },
+
+    'editor_init' : function(type, mode, params) {
+        var obj = this;
+        try {
+            $('serial_manage_subs_editor_deck').selectedIndex = obj.editor_indexes[type];
+            var editor_type = type + '_editor';
+            if (typeof obj[editor_type] == 'undefined') {
+                JSAN.use('serial.' + editor_type);
+                obj[editor_type] = new serial[editor_type](); 
+            }
+
+            params.do_edit = true;
+            params.handle_update = true;
+            if (mode == 'add') {
+                params.trigger_refresh = true;
+                params.refresh_command = function () {obj.refresh_list();};
+            }
+            obj[editor_type].init(params);
+        } catch(E) {
+            obj.error.standard_unexpected_error_alert('editor_init() error',E);
+        }
+    },
+
+    'do_delete' : function(type, method, overridable_events) {
+        var obj = this;
+        try {
+            JSAN.use('util.functional');
+
+            var list = util.functional.filter_list(
+                obj.sel_list,
+                function (o) {
+                    return o.split(/_/)[0] == type;
+                }
+            );
+
+            list = util.functional.map_list(
+                list,
+                function (o) {
+                    return JSON2js( js2JSON( obj['map_' + type][ type + '_' + o.split(/_/)[1] ] ) );
+                }
+            );
+
+            //TODO: proper messages
+            var delete_msg;
+            if (list.length != 1) {
+                delete_msg = document.getElementById('serialStrings').getFormattedString('staff.serial.manage_subs.delete_' + type + '.confirm.plural', [list.length]);
+            } else {
+                delete_msg = document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete_' + type + '.confirm');
+            }
+            var r = obj.error.yns_alert(
+                    delete_msg,
+                    document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete_' + type + '.title'),
+                    document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.delete'),
+                    document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.cancel'),
+                    null,
+                    document.getElementById('commonStrings').getString('common.confirm')
+            );
+
+            if (r == 0) {
+                for (var i = 0; i < list.length; i++) {
+                    list[i].isdeleted('1');
+                }
+                var robj = obj.network.request(
+                    'open-ils.serial', 
+                    method, 
+                    [ ses(), list, true ],
+                    null,
+                    {
+                        'title' : document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete_' + type + '.override'),
+                        'overridable_events' : overridable_events
+                    }
+                );
+                if (robj == null) throw(robj);
+                if (typeof robj.ilsevent != 'undefined') {
+                    if (robj.ilsevent != 0) {
+                        var overridable = false;
+                        for (i = 0; i < overridable_events.length; i++) {
+                            if (overridable_events[i] == robj.ilsevent) {
+                                overridable = true;
+                                break;
+                            }
+                        }
+                        if (!overridable) throw(robj);
+                    }
+                }
+                obj.refresh_list();
+            }
+        } catch(E) {
+            obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete.error'),E);
+            obj.refresh_list();
+        }
+    },
+
+    'init' : function( params ) {
+
+        try {
+            netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+            var obj = this;
+
+            obj.docid = params.docid;
+
+            JSAN.use('util.network'); obj.network = new util.network();
+            JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
+            JSAN.use('util.controller'); obj.controller = new util.controller();
+            obj.controller.init(
+                {
+                    control_map : {
+                        'save_columns' : [ [ 'command' ], function() { obj.list.save_columns(); } ],
+                        'sel_clip' : [
+                            ['command'],
+                            function() { obj.list.clipboard(); }
+                        ],
+                        'cmd_broken' : [
+                            ['command'],
+                            function() { 
+                                alert(document.getElementById('commonStrings').getString('common.unimplemented'));
+                            }
+                        ],
+                        'cmd_show_my_libs' : [
+                            ['command'],
+                            function() { 
+                                obj.show_my_libs(); 
+                            }
+                        ],
+                        'cmd_show_all_libs' : [
+                            ['command'],
+                            function() {
+                                obj.show_all_libs();
+                            }
+                        ],
+                        'cmd_show_libs_with_distributions' : [
+                            ['command'],
+                            function() {
+                                obj.show_libs_with_distributions();
+                            }
+                        ],
+                        'cmd_clear' : [
+                            ['command'],
+                            function() {
+                                obj.map_tree = {};
+                                obj.list.clear();
+                            }
+                        ],
+                        'cmd_add_scap' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    JSAN.use('util.functional');
+                                    var list = obj.ids_from_sel_list('ssub');
+                                    if (list.length == 0) return;
+
+                                    /*TODO: permission check?
+                                    //populate 'list' with owning_libs of subs, TODO
+                                    var edit = 0;
+                                    try {
+                                        edit = obj.network.request(
+                                            api.PERM_MULTI_ORG_CHECK.app,
+                                            api.PERM_MULTI_ORG_CHECK.method,
+                                            [ 
+                                                ses(), 
+                                                obj.data.list.au[0].id(), 
+                                                list,
+                                                [ 'CREATE_COPY' ]
+                                            ]
+                                        ).length == 0 ? 1 : 0;
+                                    } catch(E) {
+                                        obj.error.sdump('D_ERROR','batch permission check: ' + E);
+                                    }
+
+                                    if (edit==0) return; // no read-only view for this interface */
+                                    var new_scap = new scap();
+                                    new_scap.subscription(list[0]);//TODO: add multiple at once support?
+                                    new_scap.isnew(1);
+                                    var params = {};
+                                    params.scaps = [new_scap];
+                                    obj.editor_init('scap', 'add', params);
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
+                                }
+                            }
+                        ],
+                        'cmd_add_siss' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    JSAN.use('util.functional');
+                                    var list = obj.ids_from_sel_list('ssub');
+                                    if (list.length == 0) return;
+
+                                    /*TODO: permission check?
+                                    //populate 'list' with owning_libs of subs, TODO
+                                    var edit = 0;
+                                    try {
+                                        edit = obj.network.request(
+                                            api.PERM_MULTI_ORG_CHECK.app,
+                                            api.PERM_MULTI_ORG_CHECK.method,
+                                            [ 
+                                                ses(), 
+                                                obj.data.list.au[0].id(), 
+                                                list,
+                                                [ 'CREATE_COPY' ]
+                                            ]
+                                        ).length == 0 ? 1 : 0;
+                                    } catch(E) {
+                                        obj.error.sdump('D_ERROR','batch permission check: ' + E);
+                                    }
+
+                                    if (edit==0) return; // no read-only view for this interface */
+                                    var new_siss = new siss();
+                                    new_siss.subscription(list[0]);//TODO: add multiple at once support?
+                                    new_siss.isnew(1);
+                                    var params = {};
+                                    params.sisses = [new_siss];
+                                    obj.editor_init('siss', 'add', params);
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
+                                }
+                            }
+                        ],
+                        'cmd_add_sdist' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    JSAN.use('util.functional');
+                                    var list = obj.ids_from_sel_list('ssub');
+                                    if (list.length == 0) list = obj.ids_from_sel_list('sdist-group');
+                                    if (list.length == 0) return;
+
+                                    /*TODO: permission check?
+                                    //populate 'list' with owning_libs of subs, TODO
+                                    var edit = 0;
+                                    try {
+                                        edit = obj.network.request(
+                                            api.PERM_MULTI_ORG_CHECK.app,
+                                            api.PERM_MULTI_ORG_CHECK.method,
+                                            [ 
+                                                ses(), 
+                                                obj.data.list.au[0].id(), 
+                                                list,
+                                                [ 'CREATE_COPY' ]
+                                            ]
+                                        ).length == 0 ? 1 : 0;
+                                    } catch(E) {
+                                        obj.error.sdump('D_ERROR','batch permission check: ' + E);
+                                    }
+
+                                    if (edit==0) return; // no read-only view for this interface */
+                                    var new_sdist = new sdist();
+                                    new_sdist.subscription(list[0]);//TODO: add multiple at once support?
+                                    new_sdist.holding_lib(obj.map_ssub['ssub_' + list[0]].owning_lib());//default to sub owning lib
+                                    new_sdist.label('Default');
+                                    new_sdist.isnew(1);
+                                    var params = {};
+                                    params.sdists = [new_sdist];
+                                    obj.editor_init('sdist', 'add', params);
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
+                                }
+                            }
+                        ],
+                        'cmd_delete_scap' : [
+                            ['command'],
+                            function() {
+                                var overridable_events = [
+                                    11001 // SERIAL_CAPTION_AND_PATTERN_HAS_ISSUANCES
+                                ];
+                                obj.do_delete('scap', 'open-ils.serial.caption_and_pattern.batch.update', overridable_events);
+                            }
+                        ],
+                        'cmd_delete_sdist' : [
+                            ['command'],
+                            function() {
+                                var overridable_events = [ //TODO: proper overrides
+                                ];
+                                obj.do_delete('sdist', 'open-ils.serial.distribution.fleshed.batch.update', overridable_events);
+                            }
+                        ],
+                        'cmd_delete_siss' : [
+                            ['command'],
+                            function() {
+                                var overridable_events = [ //TODO: proper overrides
+                                ];
+                                obj.do_delete('siss', 'open-ils.serial.issuance.fleshed.batch.update', overridable_events);
+                            }
+                        ],
+                        'cmd_delete_ssub' : [
+                            ['command'],
+                            function() {
+                                var overridable_events = [
+                                    11000 // SERIAL_SUBSCRIPTION_NOT_EMPTY
+                                ];
+                                obj.do_delete('ssub', 'open-ils.serial.subscription.fleshed.batch.update', overridable_events);
+                            }
+                        ],
+                        /*dbw2 'cmd_delete_ssub' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    JSAN.use('util.functional');
+
+                                    var list = util.functional.filter_list(
+                                        obj.sel_list,
+                                        function (o) {
+                                            return o.split(/_/)[0] == 'ssub';
+                                        }
+                                    );
+
+                                    list = util.functional.map_list(
+                                        list,
+                                        function (o) {
+                                            return JSON2js( js2JSON( obj.map_ssub[ 'ssub_' + o.split(/_/)[1] ] ) );
+                                        }
+                                    );
+
+                                    var del_prompt;
+                                    if (list.length == 1) {
+                                        //TODO: correct prompts
+                                        del_prompt = document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.prompt');
+                                    } else {
+                                        del_prompt = document.getElementById('catStrings').getFormattedString('staff.cat.copy_browser.delete_volume.prompt.plural', [list.length]);
+                                    }
+
+                                    var r = obj.error.yns_alert(
+                                            del_prompt,
+                                            document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.title'),
+                                            document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.delete'),
+                                            document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.cancel'),
+                                            null,
+                                            document.getElementById('commonStrings').getString('common.confirm')
+                                    );
+
+                                    if (r == 0) {
+                                        for (var i = 0; i < list.length; i++) {
+                                            list[i].isdeleted('1');
+                                        }
+                                        var robj = obj.network.simple_request(
+                                            'FM_ACN_TREE_UPDATE', 
+                                            [ ses(), list, true ],
+                                            null,
+                                            {
+                                                'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.override'),
+                                                'overridable_events' : [
+                                                ]
+                                            }
+                                        );
+                                        if (robj == null) throw(robj);
+                                        if (typeof robj.ilsevent != 'undefined') {
+                                            if (robj.ilsevent == 1206 ) { // VOLUME_NOT_EMPTY
+                                                alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.copies_remain'));
+                                                return;
+                                            }
+                                            if (robj.ilsevent != 0) throw(robj);
+                                        }
+                                        alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.success'));
+                                        obj.refresh_list();
+                                    }
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.exception'),E);
+                                    obj.refresh_list();
+                                }
+
+                            }
+                        ], dbw2*/
+                        'cmd_mark_library' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    var list = obj.ids_from_sel_list('aou');
+                                    if (list.length == 1) {
+                                        obj.data.marked_library = { 'lib' : list[0], 'docid' : obj.docid };
+                                        obj.data.stash('marked_library');
+                                        alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_library.alert'));
+                                    } else {
+                                        obj.error.yns_alert(
+                                                document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_library.prompt'),
+                                                document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_library.title'),
+                                                document.getElementById('commonStrings').getString('common.ok'),
+                                                null,
+                                                null,
+                                                document.getElementById('commonStrings').getString('common.confirm')
+                                                );
+                                    }
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert('manage_subs.js -> mark library',E);
+                                }
+                            }
+                        ],
+
+                        'cmd_mark_subscription' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    var list = obj.ids_from_sel_list('ssub');
+                                    if (list.length == 1) {
+                                        obj.data.marked_subscription = list[0];
+                                        obj.data.stash('marked_subscription');
+                                        alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_volume.alert'));
+                                    } else {
+                                        obj.error.yns_alert(
+                                                document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_volume.prompt'),
+                                                document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_volume.title'),
+                                                document.getElementById('commonStrings').getString('common.ok'),
+                                                null,
+                                                null,
+                                                document.getElementById('commonStrings').getString('common.confirm')
+                                                );
+                                    }
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert('manage_subs.js -> mark subscription',E);
+                                }
+                            }
+                        ],
+                        'cmd_add_subscriptions' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    JSAN.use('util.functional');
+                                    var list = obj.ids_from_sel_list('aou');
+                                    if (list.length == 0) return;
+                                    //TODO: permission check?
+                                    /*var edit = 0;
+                                    try {
+                                        edit = obj.network.request(
+                                            api.PERM_MULTI_ORG_CHECK.app,
+                                            api.PERM_MULTI_ORG_CHECK.method,
+                                            [ 
+                                                ses(), 
+                                                obj.data.list.au[0].id(), 
+                                                list,
+                                                [ 'CREATE_VOLUME', 'CREATE_COPY' ]
+                                            ]
+                                        ).length == 0 ? 1 : 0;
+                                    } catch(E) {
+                                        obj.error.sdump('D_ERROR','batch permission check: ' + E);
+                                    }
+
+                                    if (edit==0) {
+                                        alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.add_volume.permission_error'));
+                                        return; // no read-only view for this interface
+                                    } */
+                                    var new_ssub = new ssub();
+                                    new_ssub.owning_lib(list[0]);//TODO: add multiple at once support?
+                                    new_ssub.isnew(1);
+                                    new_ssub.record_entry(obj.docid);
+                                    var params = {};
+                                    params.ssubs = [new_ssub];
+                                    obj.editor_init('ssub', 'add', params);
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
+                                }
+                            }
+                        ],
+                        'cmd_transfer_subscription' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    obj.data.stash_retrieve();
+                                    if (!obj.data.marked_library) {
+                                        alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer_volume.alert'));
+                                        return;
+                                    }
+                                    
+                                    JSAN.use('util.functional');
+
+                                    var list = obj.ids_from_sel_list('ssub');
+
+                                    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
+
+                                    var ssub_list = util.functional.map_list(
+                                        list,
+                                        function (o) {
+                                            return obj.map_ssub[ 'ssub_' + o ].start_date();
+                                        }
+                                    ).join(document.getElementById('commonStrings').getString('common.grouping_string'));
+
+                                    var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: auto">';
+                                    xml += '<description>';
+                                    xml += document.getElementById('catStrings').getFormattedString('staff.cat.copy_browser.transfer.prompt', [ssub_list, obj.data.hash.aou[ obj.data.marked_library.lib ].shortname()]);
+                                    xml += '</description>';
+                                    xml += '<hbox><button label="' + document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.submit.label') + '" name="fancy_submit"/>';
+                                    xml += '<button label="' 
+                                        + document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.cancel.label') 
+                                        + '" accesskey="' 
+                                        + document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.cancel.accesskey') 
+                                        + '" name="fancy_cancel"/></hbox>';
+                                    xml += '<iframe style="overflow: scroll" flex="1" src="' + urls.XUL_BIB_BRIEF + '?docid=' + obj.data.marked_library.docid + '"/>';
+                                    xml += '</vbox>';
+                                    JSAN.use('OpenILS.data');
+                                    var data = new OpenILS.data(); data.init({'via':'stash'});
+                                    //data.temp_transfer = xml; data.stash('temp_transfer');
+                                    JSAN.use('util.window'); var win = new util.window();
+                                    var fancy_prompt_data = win.open(
+                                        urls.XUL_FANCY_PROMPT,
+                                        //+ '?xml_in_stash=temp_transfer'
+                                        //+ '&title=' + window.escape('Volume Transfer'),
+                                        'fancy_prompt', 'chrome,resizable,modal,width=500,height=300',
+                                        {
+                                            'xml' : xml,
+                                            'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.title')
+                                        }
+                                    );
+
+                                    if (fancy_prompt_data.fancy_status == 'incomplete') {
+                                        alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.incomplete'));
+                                        return;
+                                    }
+
+                                    var robj = obj.network.simple_request(
+                                        'FM_ACN_TRANSFER', 
+                                        [ ses(), { 'docid' : obj.data.marked_library.docid, 'lib' : obj.data.marked_library.lib, 'subscriptions' : list } ],
+                                        null,
+                                        {
+                                            'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.override.failure'),
+                                            'overridable_events' : [
+                                                1208, // TITLE_LAST_COPY
+                                                1219, // COPY_REMOTE_CIRC_LIB
+                                            ],
+                                        }
+                                    );
+
+                                    if (typeof robj.ilsevent != 'undefined') {
+                                        if (robj.ilsevent == 1221) { // ORG_CANNOT_HAVE_VOLS
+                                            alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.ineligible_destination'));
+                                        } else {
+                                            throw(robj);
+                                        }
+                                    } else {
+                                        alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.success'));
+                                    }
+
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.unexpected_error'),E);
+                                }
+                                obj.refresh_list();
+                            }
+                        ],
+
+                        'cmd_transfer_sdists' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    obj.data.stash_retrieve();
+                                    if (!obj.data.marked_subscription) {
+                                        alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer_items.missing_volume'));
+                                        return;
+                                    }
+                                    
+                                    JSAN.use('util.functional');
+
+                                    var list = obj.ids_from_sel_list('sdist');
+                                    var subscription = obj.network.simple_request('FM_ACN_RETRIEVE.authoritative',[ obj.data.marked_subscription ]);
+
+                                    JSAN.use('cat.util'); cat.util.transfer_copies( { 
+                                        'distribution_ids' : list, 
+                                        'docid' : subscription.record(),
+                                        'subscription_label' : subscription.start_date(),
+                                        'owning_lib' : subscription.owning_lib(),
+                                    } );
+
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer_items.unexpected_error'),E);
+                                }
+                                obj.refresh_list();
+                            }
+                        ],
+                        'cmd_refresh_list' : [
+                            ['command'],
+                            function() {
+                                obj.refresh_list();
+                            }
+                        ],
+/*dbw2                      'sel_distribution_details' : [
+                            ['command'],
+                            function() {
+                                JSAN.use('util.functional');
+
+                                var list = util.functional.filter_list(
+                                    obj.sel_list,
+                                    function (o) {
+                                        return o.split(/_/)[0] == 'sdist';
+                                    }
+                                );
+
+                                list = util.functional.map_list(
+                                    list,
+                                    function (o) {
+                                        return o.split(/_/)[1];
+                                    }
+                                );
+    
+                                JSAN.use('circ.util');
+                                for (var i = 0; i < list.length; i++) {
+                                    circ.util.show_copy_details( list[i] );
+                                }
+                            }
+                        ],
+                        'cmd_edit_sdists' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    JSAN.use('util.functional');
+
+                                    var list = util.functional.filter_list(
+                                        obj.sel_list,
+                                        function (o) {
+                                            return o.split(/_/)[0] == 'sdist';
+                                        }
+                                    );
+
+                                    list = util.functional.map_list(
+                                        list,
+                                        function (o) {
+                                            return o.split(/_/)[1];
+                                        }
+                                    );
+
+                                    JSAN.use('cat.util'); cat.util.spawn_copy_editor( { 'copy_ids' : list, 'edit' : 1 } );
+                                    obj.refresh_list();
+
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_items.error'),E);
+                                }
+                            }
+                        ], dbw2*/
+
+/*dbw2                      'cmd_print_spine_labels' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    JSAN.use('util.functional');
+                                    
+                                    var list = util.functional.filter_list(
+                                        obj.sel_list,
+                                        function (o) {
+                                            return o.split(/_/)[0] == 'sdist';
+                                        }
+                                    );
+
+                                    list = util.functional.map_list(
+                                        list,
+                                        function (o) {
+                                            return obj.map_sdist[ o ];
+                                        }
+                                    );
+
+                                    obj.data.temp_barcodes_for_labels = util.functional.map_list( list, function(o){return o.barcode();}) ; 
+                                    obj.data.stash('temp_barcodes_for_labels');
+                                    xulG.new_tab(
+                                        xulG.url_prefix( urls.XUL_SPINE_LABEL ),
+                                        { 'tab_name' : document.getElementById('catStrings').getString('staff.cat.copy_browser.print_spine.tab') },
+                                        {}
+                                    );
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.print_spine.error'),E);
+                                }
+                            }
+                        ],
+                        'cmd_edit_subscriptions' : [
+                            ['command'],
+                            function() {
+                                try {
+                                    JSAN.use('util.functional');
+                                    var list = util.functional.map_list(
+                                        util.functional.filter_list(
+                                            obj.sel_list,
+                                            function (o) {
+                                                return o.split(/_/)[0] == 'ssub';
+                                            }
+                                        ),
+                                        function (o) {
+                                            return o.split(/_/)[1];
+                                        }
+                                    );
+                                    if (list.length == 0) return;
+
+                                    var edit = 0;
+                                    try {
+                                        edit = obj.network.request(
+                                            api.PERM_MULTI_ORG_CHECK.app,
+                                            api.PERM_MULTI_ORG_CHECK.method,
+                                            [ 
+                                                ses(), 
+                                                obj.data.list.au[0].id(), 
+                                                util.functional.map_list(
+                                                    list,
+                                                    function (o) {
+                                                        return obj.map_ssub[ 'ssub_' + o ].owning_lib();
+                                                    }
+                                                ),
+                                                [ 'UPDATE_VOLUME' ]
+                                            ]
+                                        ).length == 0 ? 1 : 0;
+                                    } catch(E) {
+                                        obj.error.sdump('D_ERROR','batch permission check: ' + E);
+                                    }
+
+                                    if (edit==0) {
+                                        alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.permission_error'));
+                                        return; // no read-only view for this interface
+                                    }
+
+                                    list = util.functional.map_list(
+                                        list,
+                                        function (o) {
+                                            var my_ssub = obj.map_ssub['ssub_' + o];
+                                            return function(r){return r;}(my_ssub);
+                                        }
+                                    );
+
+                                    var title;
+                                    if (list.length == 1) {
+                                        title = document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.title');
+                                    } else {
+                                        title = document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.title.plural');
+                                    }
+
+                                    JSAN.use('util.window'); var win = new util.window();
+                                    //obj.data.volumes_temp = js2JSON( list );
+                                    //obj.data.stash('volumes_temp');
+                                    var my_xulG = win.open(
+                                        window.xulG.url_prefix(urls.XUL_VOLUME_EDITOR),
+                                        title,
+                                        'chrome,modal,resizable',
+                                        { 'subscriptions' : JSON2js(js2JSON(list)) }
+                                    );
+
+                                    // FIXME -- need to unique the temp space, and not rely on modalness of window
+                                    //obj.data.stash_retrieve();
+                                    if (typeof my_xulG.update_these_subscriptions == 'undefined') { return; }
+                                    var subscriptions = my_xulG.subscriptions;
+                                    if (!subscriptions) return;
+                                
+                                    subscriptions = util.functional.filter_list(
+                                        subscriptions,
+                                        function (o) {
+                                            return o.ischanged() == '1';
+                                        }
+                                    );
+
+                                    subscriptions = util.functional.map_list(
+                                        subscriptions,
+                                        function (o) {
+                                            o.record( obj.docid ); // staff client 2 did not do this.  Does it matter?
+                                            return o;
+                                        }
+                                    );
+
+                                    if (subscriptions.length == 0) return;
+
+                                    try {
+                                        var r = obj.network.request(
+                                            api.FM_ACN_TREE_UPDATE.app,
+                                            api.FM_ACN_TREE_UPDATE.method,
+                                            [ ses(), subscriptions, true ]
+                                        );
+                                        if (typeof r.ilsevent != 'undefined') {
+                                            switch(Number(r.ilsevent)) {
+                                                case 1705 : // VOLUME_LABEL_EXISTS
+                                                    alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.failed'));
+                                                    break;
+                                                default: throw(r);
+                                            }
+                                        } else {
+                                            alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.success'));
+                                        }
+                                    } catch(E) {
+                                        obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.error'),E);
+                                    }
+                                    obj.refresh_list();
+
+                                } catch(E) {
+                                    obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.exception'),E);
+                                }
+                            }
+                        ], dbw2*/
+                    }
+                }
+            );
+
+            obj.list_init(params);
+
+            obj.org_ids = obj.network.simple_request('FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
+            if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
+            JSAN.use('util.functional'); 
+            obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
+
+            var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
+            //obj.show_libs( org );
+
+            //obj.show_my_libs();
+
+            JSAN.use('util.file'); JSAN.use('util.widgets');
+
+            var file; var list_data; var ml; 
+
+            file = new util.file('offline_ou_list'); 
+            if (file._file.exists()) {
+                list_data = file.get_object(); file.close();
+                ml = util.widgets.make_menulist( list_data[0], list_data[1] );
+                ml.setAttribute('id','lib_menu'); document.getElementById('serial_sub_lib_menu').appendChild(ml);
+                //TODO: class this menu properly
+                for (var i = 0; i < obj.org_ids.length; i++) {
+                    ml.getElementsByAttribute('value',obj.org_ids[i])[0].setAttribute('class','has_distributions');
+                }
+                ml.firstChild.addEventListener(
+                    'popupshown',
+                    function(ev) {
+                        document.getElementById('legend').setAttribute('hidden','false');
+                    },
+                    false
+                );
+                ml.firstChild.addEventListener(
+                    'popuphidden',
+                    function(ev) {
+                        document.getElementById('legend').setAttribute('hidden','true');
+                    },
+                    false
+                );
+                ml.addEventListener(
+                    'command',
+                    function(ev) {
+                        if (document.getElementById('refresh_button')) document.getElementById('refresh_button').focus(); 
+                        JSAN.use('util.file'); var file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
+                        util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_ssubs' : [ 'checked' ], 'show_groups' : [ 'checked' ] });
+                        obj.refresh_list();
+                    },
+                    false
+                );
+            } else {
+                throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n');
+            }
+
+            file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
+            util.widgets.load_attributes(file);
+            ml.value = ml.getAttribute('value');
+            if (! ml.value) {
+                ml.value = org.id();
+                ml.setAttribute('value',ml.value);
+            }
+
+            document.getElementById('show_ssubs').addEventListener(
+                'command',
+                function(ev) {
+                    JSAN.use('util.file'); var file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
+                    util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_ssubs' : [ 'checked' ], 'show_groups' : [ 'checked' ] });
+                },
+                false
+            );
+
+            document.getElementById('show_groups').addEventListener(
+                'command',
+                function(ev) {
+                    JSAN.use('util.file'); var file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
+                    util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_ssubs' : [ 'checked' ], 'show_groups' : [ 'checked' ] });
+                },
+                false
+            );
+
+            obj.show_my_libs( ml.value );
+
+            JSAN.use('util.exec'); var exec = new util.exec(20); exec.timer(obj.funcs,100);
+
+        } catch(E) {
+            this.error.standard_unexpected_error_alert('serial/manage_subs.init: ',E);
+        }
+    },
+
+    'show_my_libs' : function(org) {
+        var obj = this;
+        try {
+            if (!org) {
+                org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
+            } else {
+                if (typeof org != 'object') org = obj.data.hash.aou[ org ];
+            }
+            obj.show_libs( org, false );
+        
+            var p_org = obj.data.hash.aou[ org.parent_ou() ];
+            if (p_org) {
+                obj.funcs.push( function() { 
+                    document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
+                    document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
+                    document.getElementById('lib_menu').setAttribute('disabled','true'); 
+                } );
+                for (var i = 0; i < p_org.children().length; i++) {
+                    obj.funcs.push(
+                        function(o) {
+                            return function() {
+                                obj.show_libs( o, false );
+                            }
+                        }( p_org.children()[i] )
+                    );
+                }
+                obj.funcs.push( function() { 
+                    document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
+                    document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
+                    document.getElementById('lib_menu').setAttribute('disabled','false'); 
+                } );
+            }
+        } catch(E) {
+            alert(E);
+        }
+    },
+
+    'show_all_libs' : function() {
+        var obj = this;
+        try {
+            obj.show_my_libs();
+
+            obj.show_libs( obj.data.tree.aou );
+
+            obj.funcs.push( function() { 
+                document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
+                document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
+                document.getElementById('lib_menu').setAttribute('disabled','true'); 
+            } );
+
+            for (var i = 0; i < obj.data.tree.aou.children().length; i++) {
+                obj.funcs.push(
+                    function(o) {
+                        return function() {
+                            obj.show_libs( o );
+                        }
+                    }( obj.data.tree.aou.children()[i] )
+                );
+            }
+            obj.funcs.push( function() { 
+                document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
+                document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
+                document.getElementById('lib_menu').setAttribute('disabled','false'); 
+            } );
+
+        } catch(E) {
+            alert(E);
+        }
+    },
+
+    'show_libs_with_distributions' : function() {
+        var obj = this;
+        try {
+            JSAN.use('util.functional');
+
+            var orgs = util.functional.map_list(
+                obj.org_ids,
+                function(id) { return obj.data.hash.aou[id]; }
+            ).sort(
+                function( a, b ) {
+                    if (a.shortname() < b.shortname()) return -1;
+                    if (a.shortname() > b.shortname()) return 1;
+                    return 0;
+                }
+            );
+            obj.funcs.push( function() { 
+                document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
+                document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
+                document.getElementById('lib_menu').setAttribute('disabled','true'); 
+            } );
+
+            for (var i = 0; i < orgs.length; i++) {
+                obj.funcs.push(
+                    function(o) {
+                        return function() {
+                            obj.show_libs(o,false);
+                        }
+                    }( orgs[i] )
+                );
+            }
+            obj.funcs.push( function() { 
+                document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
+                document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
+                document.getElementById('lib_menu').setAttribute('disabled','false'); 
+            } );
+
+        } catch(E) {
+            alert(E);
+        }
+    },
+
+    'show_libs' : function(start_aou,show_open) {
+        var obj = this;
+        try {
+            if (!start_aou) throw('show_libs: Need a start_aou');
+            JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
+            JSAN.use('util.functional'); 
+
+            var parents = [];
+            var temp_aou = start_aou;
+            while ( temp_aou.parent_ou() ) {
+                temp_aou = obj.data.hash.aou[ temp_aou.parent_ou() ];
+                parents.push( temp_aou );
+            }
+            parents.reverse();
+
+            for (var i = 0; i < parents.length; i++) {
+                obj.funcs.push(
+                    function(o,p) {
+                        return function() { 
+                            obj.append_org(o,p,{'container':'true','open':'true'}); 
+                        };
+                    }(parents[i], obj.data.hash.aou[ parents[i].parent_ou() ])
+                );
+            }
+
+            obj.funcs.push(
+                function(o,p) {
+                    return function() { obj.append_org(o,p); };
+                }(start_aou,obj.data.hash.aou[ start_aou.parent_ou() ])
+            );
+
+            obj.funcs.push(
+                function() {
+                    if (start_aou.children()) {
+                        var x = obj.map_tree[ 'aou_' + start_aou.id() ];
+                        x.setAttribute('container','true');
+                        if (show_open) x.setAttribute('open','true');
+                        for (var i = 0; i < start_aou.children().length; i++) {
+                            obj.funcs.push(
+                                function(o,p) {
+                                    return function() { obj.append_org(o,p); };
+                                }( start_aou.children()[i], start_aou )
+                            );
+                        }
+                    }
+                }
+            );
+
+        } catch(E) {
+            alert(E);
+        }
+    },
+
+    'on_select' : function(list,twisty) {
+        var obj = this;
+        for (var i = 0; i < list.length; i++) {
+            var node = obj.map_tree[ list[i] ];
+            var row_type = list[i].split('_')[0];
+            var id = list[i].split('_')[1];
+
+            switch(row_type) {
+                case 'aou' : obj.on_select_org(id,twisty); break;
+                case 'ssub' : obj.on_select_ssub(id,twisty); break;
+                case 'sdist' : obj.on_select_sdist(id,twisty); break;
+                case 'siss' : obj.on_select_siss(id,twisty); break;
+                case 'scap' : obj.on_select_scap(id,twisty); break;
+                default: break;
+            }
+        }
+    },
+
+    'on_select_ssub' : function(ssub_id,twisty) {
+        var obj = this;
+        try {
+            //typo? var ssub_tree = obj.map_sdist[ 'ssub_' + ssub_id ];
+            var ssub_tree = obj.map_ssub[ 'ssub_' + ssub_id ];
+            obj.funcs.push( function() { 
+                document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
+                document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
+                document.getElementById('lib_menu').setAttribute('disabled','true'); 
+            } );
+            if (ssub_tree.distributions()) {
+                for (var i = 0; i < ssub_tree.distributions().length; i++) {
+                    obj.funcs.push(
+                        function(c,a) {
+                            return function() {
+                                obj.append_member(c,a,[],'sdist');
+                            }
+                        }( ssub_tree.distributions()[i], ssub_tree )
+                    )
+                }
+            }
+            if (ssub_tree.issuances()) {
+                for (var i = 0; i < ssub_tree.issuances().length; i++) {
+                    obj.funcs.push(
+                        function(c,a) {
+                            return function() {
+                                obj.append_member(c,a,[],'siss');
+                            }
+                        }( ssub_tree.issuances()[i], ssub_tree )
+                    )
+                }
+            }
+            if (ssub_tree.scaps()) {
+                for (var i = 0; i < ssub_tree.scaps().length; i++) {
+                    obj.funcs.push(
+                        function(c,a) {
+                            return function() {
+                                obj.append_member(c,a,[],'scap');
+                            }
+                        }( ssub_tree.scaps()[i], ssub_tree )
+                    )
+                }
+            }
+            obj.funcs.push( function() { 
+                document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
+                document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
+                document.getElementById('lib_menu').setAttribute('disabled','false'); 
+            } );
+
+            // draw ssub editor
+            if (typeof twisty == 'undefined') {
+                var params = {};
+                params.ssub_ids = [ssub_id];
+                obj.editor_init('ssub', 'edit', params);
+            }
+        } catch(E) {
+            alert(E);
+        }
+    },
+
+    'on_select_sdist' : function(sdist_id,twisty) {
+        var obj = this;
+        try {
+            // draw sdist editor
+            if (typeof twisty == 'undefined') {
+                var params = {};
+                params.sdist_ids = [sdist_id];
+                obj.editor_init('sdist', 'edit', params);
+            }
+        } catch(E) {
+            alert(E);
+        }
+    },
+
+    'on_select_siss' : function(siss_id,twisty) {
+        var obj = this;
+        try {
+            // draw siss editor
+            if (typeof twisty == 'undefined') {
+                var params = {};
+                params.siss_ids = [siss_id];
+                obj.editor_init('siss', 'edit', params);
+            }
+        } catch(E) {
+            alert(E);
+        }
+    },
+
+    'on_select_scap' : function(scap_id,twisty) {
+        var obj = this;
+        try {
+            // draw scap editor
+            if (typeof twisty == 'undefined') {
+                var params = {};
+                params.scap_ids = [scap_id];
+                obj.editor_init('scap', 'edit', params);
+            }
+        } catch(E) {
+            alert(E);
+        }
+    },
+
+    'on_select_org' : function(org_id,twisty) {
+        var obj = this;
+        var org = obj.data.hash.aou[ org_id ];
+        if (obj.data.hash.aout[ org.ou_type() ].depth() == 0 && ! get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) return;
+        obj.funcs.push( function() { 
+            document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
+            document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true'); 
+            document.getElementById('lib_menu').setAttribute('disabled','true'); 
+        } );
+        if (org.children()) {
+            for (var i = 0; i < org.children().length; i++) {
+                obj.funcs.push(
+                    function(o,p) {
+                        return function() {
+                            obj.append_org(o,p)
+                        }
+                    }(org.children()[i],org)
+                );
+            }
+        } 
+        if (obj.map_ssub[ 'aou_' + org_id ]) {
+            for (var i = 0; i < obj.map_ssub[ 'aou_' + org_id ].length; i++) {
+                obj.funcs.push(
+                    function(o,a) {
+                        return function() {
+                            obj.append_ssub(o,a);
+                        }
+                    }( org, obj.map_ssub[ 'aou_' + org_id ][i] )
+                );
+            }
+        }
+        obj.funcs.push( function() { 
+            document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
+            document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false'); 
+            document.getElementById('lib_menu').setAttribute('disabled','false'); 
+        } );
+
+        // remove current editor
+        if (typeof twisty == 'undefined') {
+            document.getElementById('serial_manage_subs_editor_deck').selectedIndex = 0;
+        }
+    },
+
+    'append_org' : function (org,parent_org,params) {
+        var obj = this;
+        try {
+            if (obj.map_tree[ 'aou_' + org.id() ]) {
+                var x = obj.map_tree[ 'aou_' + org.id() ];
+                if (params) {
+                    for (var i in params) {
+                        x.setAttribute(i,params[i]);
+                    }
+                }
+                return x;
+            }
+
+            var data = {
+                'row' : {
+                    'my' : {
+                        'aou' : org,
+                    }
+                },
+                'skip_all_columns_except' : [0,1,2],
+                'retrieve_id' : 'aou_' + org.id(),
+                'to_bottom' : true,
+                'no_auto_select' : true,
+            };
+        
+            var ssub_tree_list;
+            if ( obj.org_ids.indexOf( Number( org.id() ) ) == -1 ) {
+                if ( get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) {
+                    data.row.my.subscription_count = '0';
+                    //data.row.my.distribution_count = '<0>';
+                } else {
+                    data.row.my.subscription_count = '';
+                    //data.row.my.distribution_count = '';
+                }
+            } else {
+                var v_count = 0; var d_count = 0;
+                ssub_tree_list = obj.network.simple_request(
+                    'FM_SSUB_TREE_LIST_RETRIEVE_VIA_RECORD_ID_AND_ORG_IDS.authoritative',
+                    [ ses(), obj.docid, [ org.id() ] ]
+                );
+                for (var i = 0; i < ssub_tree_list.length; i++) {
+                    v_count++;
+                    obj.map_ssub[ 'ssub_' + ssub_tree_list[i].id() ] = function(r){return r;}(ssub_tree_list[i]);
+                    var distributions = ssub_tree_list[i].distributions();
+                    //if (distributions) d_count += distributions.length;
+                    for (var j = 0; j < distributions.length; j++) {
+                        obj.map_sdist[ 'sdist_' + distributions[j].id() ] = function(r){return r;}(distributions[j]);
+                    }
+                    var issuances = ssub_tree_list[i].issuances();
+                    for (var j = 0; j < issuances.length; j++) {
+                        obj.map_siss[ 'siss_' + issuances[j].id() ] = function(r){return r;}(issuances[j]);
+                    }
+                    var scaps = ssub_tree_list[i].scaps();
+                    for (var j = 0; j < scaps.length; j++) {
+                        obj.map_scap[ 'scap_' + scaps[j].id() ] = function(r){return r;}(scaps[j]);
+                    }
+                }
+                data.row.my.subscription_count = v_count;
+                //data.row.my.distribution_count = '<' + d_count + '>';
+            }
+            if (parent_org) {
+                data.node = obj.map_tree[ 'aou_' + parent_org.id() ];
+            }
+            var nparams = obj.list.append(data);
+            var node = nparams.my_node;
+            if (params) {
+                for (var i in params) {
+                    node.setAttribute(i,params[i]);
+                }
+            }
+            obj.map_tree[ 'aou_' + org.id() ] = node;
+
+            if (org.children()) {
+                node.setAttribute('container','true');
+            }
+
+            if (parent_org) {
+                if ( obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ].parent_ou() == parent_org.id() ) {
+                    data.node.setAttribute('open','true');
+                }
+            } else {
+                obj.map_tree[ 'aou_' + org.id() ].setAttribute('open','true');
+            }
+
+            if (ssub_tree_list) {
+                obj.map_ssub[ 'aou_' + org.id() ] = ssub_tree_list;
+                node.setAttribute('container','true');
+            }
+
+            if (document.getElementById('show_ssubs').checked) {
+                if (! ( obj.data.hash.aout[ org.ou_type() ].depth() == 0 && ! get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) )) {
+                    node.setAttribute('open','true');
+                    obj.funcs.push( function() { obj.on_select_org( org.id() ); } );
+                }
+            }
+
+        } catch(E) {
+            dump(E+'\n');
+            alert(E);
+        }
+    },
+
+    'append_ssub' : function( org, ssub_tree, params ) {
+        var obj = this;
+        try {
+            if (obj.map_tree[ 'ssub_' + ssub_tree.id() ]) {
+                var x = obj.map_tree[ 'ssub_' + ssub_tree.id() ];
+                if (params) {
+                    for (var i in params) {
+                        x.setAttribute(i,params[i]);
+                    }
+                }
+                return x;
+            }
+
+            var parent_node = obj.map_tree[ 'aou_' + org.id() ];
+            var data = {
+                'row' : {
+                    'my' : {
+                        'aou' : org,
+                        'ssub' : ssub_tree,
+                        'subscription_count' : '',
+                        //'distribution_count' : ssub_tree.distributions() ? ssub_tree.distributions().length : '0',
+                    }
+                },
+                'skip_all_columns_except' : [0,1,2],
+                'retrieve_id' : 'ssub_' + ssub_tree.id(),
+                'node' : parent_node,
+                'to_bottom' : true,
+                'no_auto_select' : true,
+            };
+            var nparams = obj.list.append(data);
+            var node = nparams.my_node;
+            obj.map_tree[ 'ssub_' + ssub_tree.id() ] =  node;
+            if (params) {
+                for (var i in params) {
+                    node.setAttribute(i,params[i]);
+                }
+            }
+            if (ssub_tree.distributions() || ssub_tree.scaps() || ssub_tree.issuances()) {
+                //did this support a later typo? obj.map_sdist[ 'ssub_' + ssub_tree.id() ] = ssub_tree;
+                node.setAttribute('container','true');
+            }
+            if (document.getElementById('show_groups').checked) {
+                node.setAttribute('open','true');
+                obj.funcs.push( function() { obj.on_select_ssub( ssub_tree.id(), true ); } );
+            }
+            var sdist_group_node_data = {
+                'row' : {
+                    'my' : {
+                        'label' : 'Distributions',
+                    }
+                },
+                'retrieve_id' : 'sdist-group_' + ssub_tree.id(),
+                'node' : node,
+                'to_bottom' : true,
+                'no_auto_select' : true,
+            };
+            nparams = obj.list.append(sdist_group_node_data);
+            obj.map_tree[ 'ssub_sdist_group_' + ssub_tree.id() ] =  nparams.my_node;
+
+            var siss_group_node_data = {
+                'row' : {
+                    'my' : {
+                        'label' : 'Issuances',
+                    }
+                },
+                'retrieve_id' : 'siss-group_' + ssub_tree.id(),
+                'node' : node,
+                'to_bottom' : true,
+                'no_auto_select' : true,
+            };
+            nparams = obj.list.append(siss_group_node_data);
+            obj.map_tree[ 'ssub_siss_group_' + ssub_tree.id() ] =  nparams.my_node;
+
+            var scap_group_node_data = {
+                'row' : {
+                    'my' : {
+                        'label' : 'Captions/Patterns',
+                    }
+                },
+                'retrieve_id' : 'scap-group_' + ssub_tree.id(),
+                'node' : node,
+                'to_bottom' : true,
+                'no_auto_select' : true,
+            };
+            nparams = obj.list.append(scap_group_node_data);
+            obj.map_tree[ 'ssub_scap_group_' + ssub_tree.id() ] =  nparams.my_node;
+        } catch(E) {
+            dump(E+'\n');
+            alert(E);
+        }
+    },
+
+    'append_member' : function( item, ssub_tree, attributes, type ) {
+        var obj = this;
+        try {
+            if (obj.map_tree[ type + '_' + item.id() ]) {
+                var x = obj.map_tree[ type + '_' + item.id() ];
+                if (attributes) {
+                    for (var i in attributes) {
+                        x.setAttribute(i,attributes[i]);
+                    }
+                }
+                return x;
+            }
+
+            var parent_node = obj.map_tree[ 'ssub_' + type + '_group_' + ssub_tree.id() ];
+            var data = {
+                'row' : {
+                    'my' : {
+                        'aou' : obj.data.hash.aou[ ssub_tree.owning_lib() ],
+                        'ssub' : ssub_tree,
+                        'subscription_count' : '',
+                        //'distribution_count' : '',
+                    }
+                },
+                'retrieve_id' : type + '_' + item.id(),
+                'node' : parent_node,
+                'to_bottom' : true,
+                'no_auto_select' : true,
+            };
+            data['row']['my'][type] = item;
+            var nparams = obj.list.append(data);
+            var node = nparams.my_node;
+            obj.map_tree[ type + '_' + item.id() ] =  node;
+            if (attributes) {
+                for (var i in attributes) {
+                    node.setAttribute(i,attributes[i]);
+                }
+            }
+
+        } catch(E) {
+            dump(E+'\n');
+            alert(E);
+        }
+    },
+
+    'list_init' : function( params ) {
+
+        try {
+            netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+            var obj = this;
+            
+            JSAN.use('circ.util');
+            var columns = [
+                {
+                    'id' : 'tree_location',
+                    'label' : document.getElementById('catStrings').getString('staff.cat.copy_browser.list_init.tree_location'),
+                    'flex' : 1, 'primary' : true, 'hidden' : false, 
+                    '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 : "???"; },
+                },
+                {
+                    'id' : 'subscription_count',
+                    'label' : 'Subscriptions',
+                    'flex' : 0, 'primary' : false, 'hidden' : false, 
+                    'render' : function(my) { return my.subscription_count; },
+                },
+                /*{
+                    'id' : 'distribution_count',
+                    'label' : 'Members',
+                    'flex' : 0,
+                    'primary' : false, 'hidden' : false, 
+                    'render' : function(my) { return my.distribution_count; },
+                },*/
+            ];
+            JSAN.use('util.list'); obj.list = new util.list('subs_tree');
+            obj.list.init(
+                {
+                    'no_auto_select' : true,
+                    'columns' : columns,
+                    'map_row_to_columns' : circ.util.std_map_row_to_columns(' '),
+                    'retrieve_row' : function(params) {
+
+                        var row = params.row;
+                        obj.funcs.push(
+                            function() {
+
+                                if (typeof params.on_retrieve == 'function') {
+                                    params.on_retrieve(row);
+                                }
+
+                            }
+                        );
+
+                        return row;
+                    },
+                    'on_click' : function(ev) {
+                        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserRead');
+                        var row = {}; var col = {}; var nobj = {};
+                        obj.list.node.treeBoxObject.getCellAt(ev.clientX,ev.clientY,row,col,nobj); 
+                        if ((row.value == -1)||(nobj.value != 'twisty')) { return; }
+                        var node = obj.list.node.contentView.getItemAtIndex(row.value);
+                        var list = [ node.getAttribute('retrieve_id') ];
+                        if (typeof obj.on_select == 'function') {
+                            obj.on_select(list,true);
+                        }
+                        if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
+                            window.xulG.on_select(list);
+                        }
+                    },
+                    'on_select' : function(ev) {
+                        JSAN.use('util.functional');
+                        var sel = obj.list.retrieve_selection();
+                        obj.controller.view.sel_clip.disabled = sel.length < 1;
+                        obj.sel_list = util.functional.map_list(
+                            sel,
+                            function(o) { return o.getAttribute('retrieve_id'); }
+                        );
+                        obj.toggle_actions();
+                        if (typeof obj.on_select == 'function') {
+                            obj.on_select(obj.sel_list);
+                        }
+                        if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
+                            window.xulG.on_select(obj.sel_list);
+                        }
+                    },
+                }
+            );
+
+            obj.controller.render();
+
+        } catch(E) {
+            this.error.sdump('D_ERROR','serial/manage_subs.list_init: ' + E + '\n');
+            alert(E);
+        }
+    },
+
+    'toggle_actions' : function() {
+        var obj = this;
+        try {
+            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;
+            var found_aou_with_can_have_vols = false;
+            for (var i = 0; i < obj.sel_list.length; i++) {
+                var type = obj.sel_list[i].split(/_/)[0];
+                switch(type) {
+                    case 'aou' : 
+                        found_aou = true; 
+                        var org = obj.data.hash.aou[ obj.sel_list[i].split(/_/)[1] ];
+                        if ( get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) found_aou_with_can_have_vols = true;
+                    break;
+                    case 'ssub' : found_ssub = true; break;
+                    case 'sdist' : found_sdist = true; break;
+                    case 'siss' : found_siss = true; break;
+                    case 'scap' : found_scap = true; break;
+                    case 'sdist-group' : found_sdist_group = true; break;
+                    case 'siss-group' : found_siss_group = true; break;
+                    case 'scap-group' : found_scap_group = true; break;
+                }
+            }
+            obj.controller.view.cmd_add_sdist.setAttribute('disabled','true');
+            obj.controller.view.cmd_add_siss.setAttribute('disabled','true');
+            obj.controller.view.cmd_add_scap.setAttribute('disabled','true');
+            obj.controller.view.cmd_delete_sdist.setAttribute('disabled','true');
+            obj.controller.view.cmd_delete_siss.setAttribute('disabled','true');
+            obj.controller.view.cmd_delete_scap.setAttribute('disabled','true');
+            obj.controller.view.cmd_add_subscriptions.setAttribute('disabled','true');
+            obj.controller.view.cmd_mark_library.setAttribute('disabled','true');
+            obj.controller.view.cmd_delete_ssub.setAttribute('disabled','true');
+            obj.controller.view.cmd_mark_subscription.setAttribute('disabled','true');
+            obj.controller.view.cmd_transfer_subscription.setAttribute('disabled','true');
+            obj.controller.view.cmd_transfer_sdists.setAttribute('disabled','true');
+            if (found_aou && found_aou_with_can_have_vols) {
+                obj.controller.view.cmd_add_subscriptions.setAttribute('disabled','false');
+                obj.controller.view.cmd_mark_library.setAttribute('disabled','false');
+            }
+            if (found_ssub) {
+                obj.controller.view.cmd_delete_ssub.setAttribute('disabled','false');
+                obj.controller.view.cmd_mark_subscription.setAttribute('disabled','false');
+                obj.controller.view.cmd_add_sdist.setAttribute('disabled','false');
+                obj.controller.view.cmd_add_siss.setAttribute('disabled','false');
+                obj.controller.view.cmd_add_scap.setAttribute('disabled','false');
+                obj.controller.view.cmd_transfer_subscription.setAttribute('disabled','false');
+            }
+            if (found_sdist_group) {
+                obj.controller.view.cmd_add_sdist.setAttribute('disabled','false');
+            }
+            if (found_siss_group) {
+                obj.controller.view.cmd_add_siss.setAttribute('disabled','false');
+            }
+            if (found_scap_group) {
+                obj.controller.view.cmd_add_scap.setAttribute('disabled','false');
+            }
+            if (found_sdist) {
+                obj.controller.view.cmd_delete_sdist.setAttribute('disabled','false');
+                obj.controller.view.cmd_transfer_sdists.setAttribute('disabled','false');
+            }
+            if (found_siss) {
+                obj.controller.view.cmd_delete_siss.setAttribute('disabled','false');
+            }
+            if (found_scap) {
+                obj.controller.view.cmd_delete_scap.setAttribute('disabled','false');
+            }
+        } catch(E) {
+            obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.actions.error'),E);
+        }
+    },
+
+    'refresh_list' : function() { 
+        try {
+            var obj = this;
+            obj.list.clear();
+            obj.map_tree = {};
+            obj.map_ssub = {};
+            obj.map_sdist = {};
+            obj.map_siss = {};
+            obj.map_scap = {};
+            obj.org_ids = obj.network.simple_request('FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
+            if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
+            JSAN.use('util.functional'); 
+            obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
+            /*
+            var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
+            obj.show_libs( org );
+            */
+            obj.show_my_libs( document.getElementById('lib_menu').value );
+        } catch(E) {
+            this.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.refresh_list.error'),E);
+        }
+    },
+};
+
+dump('exiting serial/manage_subs.js\n');

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.xul	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Manage Subscriptions Overlay -->
+<!--
+vim:noet:sw=4:ts=4:
+-->
+<!DOCTYPE overlay PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<?xul-overlay href="/xul/server/serial/ssub_editor.xul"?>
+<?xul-overlay href="/xul/server/serial/sdist_editor.xul"?>
+<?xul-overlay href="/xul/server/serial/siss_editor.xul"?>
+<?xul-overlay href="/xul/server/serial/scap_editor.xul"?>
+<overlay id="serial_manage_subs_overlay" 
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+            <tab id="serial_manage_subs_tab" label="Subscriptions" oncommand="manage_subs_init()"/>
+            <tabpanel id="serial_manage_subs" orient="vertical" flex="1">
+                 <script>
+                    <![CDATA[
+                        manage_subs_inited = 0;
+                        function manage_subs_init() {
+                            if (manage_subs_inited) {
+                                return;
+                            }
+                            try {
+                                netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+                                if (typeof JSAN == 'undefined') { 
+                                    throw( document.getElementById("commonStrings").getString('common.jsan.missing') );
+                                }
+                                JSAN.errorLevel = "die"; // none, warn, or die
+                                JSAN.addRepository('/xul/server/');
+                                JSAN.use('util.error'); g.error = new util.error();
+                                g.error.sdump('D_TRACE','my_init() for serial/manage_subs.xul');
+                                //JSAN.use('serial2.init');
+                                JSAN.use('serial.manage_subs'); g.manage_subs = new serial.manage_subs();
+
+                                g.manage_subs.init( { 'docid' : xul_param('docid') } );
+                                manage_subs_inited = 1;
+
+                            } catch(E) {
+                                var err_msg = document.getElementById("commonStrings").getFormattedString('common.exception', ['serial/manage_subs.xul', E]);
+                                try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
+                                alert(err_msg);
+                            }
+                        }
+
+                    ]]>
+                </script>
+
+                <popupset>
+                    <popup id="serial_manage_subs_popup">
+                        <menuitem command="cmd_add_subscriptions" label="Add Subscription"/>
+                        <menuitem command="cmd_add_sdist" label="Add Distribution"/>
+                        <menuitem command="cmd_add_siss" label="Add Issuance"/>
+                        <menuitem command="cmd_add_scap" label="Add Caption/Pattern"/>
+                        <menuitem command="cmd_delete_ssub" label="Delete Subscription"/>
+                        <menuitem command="cmd_delete_sdist" label="Delete Distribution"/>
+                        <menuitem command="cmd_delete_siss" label="Delete Issuance"/>
+                        <menuitem command="cmd_delete_scap" label="Delete Caption/Pattern"/>
+                    </popup>
+                </popupset>
+
+                <hbox flex="1">
+                    <vbox flex="1">
+                        <hbox id="serial_sub_lib_menu"/>
+                        <hbox>
+                            <checkbox id="show_ssubs" label="Show Subs." />
+                            <checkbox id="show_groups" label="Show Groups" />
+                            <button id="serial_sub_add_button" label="&staff.cat.copy_browser.holdings_maintenance.refresh_button.label;" command="cmd_refresh_list" />
+                            <spacer flex="1"/>
+                            <menubar>
+                                <menu label="Actions for Selected Row">
+                                    <menupopup>
+                                        <menuitem command="cmd_add_subscriptions" label="Add Subscription"/>
+                                        <menuitem command="cmd_add_sdist" label="Add Distribution"/>
+                                        <menuitem command="cmd_add_siss" label="Add Issuance"/>
+                                        <menuitem command="cmd_add_scap" label="Add Caption/Pattern"/>
+                                        <menuitem command="cmd_delete_ssub" label="Delete Subscription"/>
+                                        <menuitem command="cmd_delete_sdist" label="Delete Distribution"/>
+                                        <menuitem command="cmd_delete_siss" label="Delete Issuance"/>
+                                        <menuitem command="cmd_delete_scap" label="Delete Caption/Pattern"/>
+                                    </menupopup>
+                                </menu>
+                            </menubar>
+                        </hbox>
+                        <tree id="subs_tree" flex="15" enableColumnDrag="true" context="serial_manage_subs_popup"/>
+                    </vbox>
+                    <splitter state="open" collapse="before" resizebefore="closest" resizeafter="farthest"/>
+                    <deck id="serial_manage_subs_editor_deck" flex="20">
+                        <description value="Please select an object to edit"/>
+                        <vbox id="serial_ssub_editor_panel" />
+                        <vbox id="serial_sdist_editor_panel" />
+                        <vbox id="serial_siss_editor_panel" />
+                        <vbox id="serial_scap_editor_panel" />
+                    </deck>
+                </hbox>
+            </tabpanel>
+
+</overlay>

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/notes.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/notes.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/notes.xul	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Serial Notes -->
+<!--
+ vim:noet:sw=4:ts=4
+-->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/patron_display.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+	<!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+
+<window id="notes_win" width="700" height="550"
+	onload="try{ my_init(); font_helper(); } catch(E) { alert(E); }"
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+	<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+	<!-- BEHAVIOR -->
+        <script type="text/javascript">var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};</script>
+        <scripts id="openils_util_scripts"/>
+
+	<script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+	<script>
+	<![CDATA[
+
+		function $(id) { return document.getElementById(id); }
+
+		function my_init() {
+			try {
+				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+				if (typeof JSAN == 'undefined') { 
+					throw( $("commonStrings").getString('common.jsan.missing') );
+				}
+				JSAN.errorLevel = "die"; // none, warn, or die
+				JSAN.addRepository('/xul/server/');
+
+				JSAN.use('util.error'); g.error = new util.error();
+				JSAN.use('util.network'); g.network = new util.network();
+				JSAN.use('util.date'); JSAN.use('util.money'); 
+				JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
+
+				g.error.sdump('D_TRACE','my_init() for notes.xul');
+
+				g.object_type = xul_param('object_type',{'modal_xulG':true});
+				g.object_id = xul_param('object_id',{'modal_xulG':true});
+				g.function_type = xul_param('function_type',{'modal_xulG':true});
+				g.constructor = xul_param('constructor',{'modal_xulG':true});
+
+				refresh();
+
+			} catch(E) {
+				var err_msg = $("commonStrings").getFormattedString('common.exception', ['serial/notes.xul', js2JSON(E)]);
+				try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
+				alert(err_msg);
+			}
+		}
+
+		function refresh() {
+			retrieve_notes(); render_notes();
+		}
+
+		function retrieve_notes() {
+			g.notes = g.network.simple_request('FM_'+g.function_type+'_RETRIEVE_ALL',[ { 'authtoken' : ses(), 'object_id' : g.object_id } ]).reverse();
+		}
+
+		function apply(node,field,value) {
+			util.widgets.apply(
+				node,'name',field,
+				function(n) {
+					switch(n.nodeName) {
+						case 'description' : n.appendChild( document.createTextNode( value ) ); break;
+						case 'label' : n.value = value; break;
+						default : n.value = value; break;
+					}
+				}
+			);
+		}
+
+		function render_notes() {
+			JSAN.use('util.widgets'); util.widgets.remove_children('notes_panel');
+			var np = $('notes_panel');
+				var hbox = document.createElement('hbox'); np.appendChild(hbox);
+					var btn = document.createElement('button'); hbox.appendChild(btn);
+						btn.setAttribute('label', $('catStrings').getString('staff.cat.copy_notes.render_notes.label'));
+						btn.setAttribute('accesskey', $('catStrings').getString('staff.cat.copy_notes.render_notes.accesskey'));
+						btn.setAttribute('oncommand','new_note()');
+
+			for (var i = 0; i < g.notes.length; i++) {
+
+				/* template */
+				var node = $('note_template').cloneNode(true); np.appendChild(node); node.hidden = false;
+				apply(node,'create_date',g.notes[i].create_date().toString().substr(0,10));
+				util.widgets.apply(node,'name','create_date',
+					function(n) {
+						n.setAttribute(
+							"tooltiptext",
+							$('catStrings').getString('staff.cat.copy_notes.widgets_apply.note_id') + " "
+							+ g.notes[i].id() + " " 
+							+ $('catStrings').getString('staff.cat.copy_notes.widgets_apply.creator_id') + " "
+							+ g.notes[i].creator()
+						);
+					}
+				);
+				apply(node,'title',g.notes[i].title());
+				apply(node,'pub',get_bool( g.notes[i].pub() ) ? $('catStrings').getString('staff.cat.copy_notes.widgets.public') : $('catStrings').getString('staff.cat.copy_notes.widgets.private'));
+				apply(node,'value',g.notes[i].value());
+				apply(node,'id',g.notes[i].id());
+				apply(node,'creator',g.notes[i].creator());
+
+				/* button bar */
+				var hb = document.createElement('hbox'); np.appendChild(hb);
+					var btn1 = document.createElement('button'); hb.appendChild(btn1);
+						btn1.setAttribute('label', $('catStrings').getString('staff.cat.copy_notes.delete_note.label'));
+						btn1.setAttribute('image',"/xul/server/skin/media/images/up_arrow.gif");
+
+						btn1.addEventListener(
+							'command',
+							function(id){ return function() { 
+								var r = g.error.yns_alert(
+									$('catStrings').getFormattedString('staff.cat.copy_notes.delete_note.prompt.msg', [g.notes[id].title(), g.notes[id].create_date().toString().substr(0,10)]),
+									$('catStrings').getString('staff.cat.copy_notes.delete_note.prompt.title'),
+									$('catStrings').getString('staff.cat.copy_notes.delete_note.prompt.yes'),
+									$('catStrings').getString('staff.cat.copy_notes.delete_note.prompt.no'),
+									null,
+									$('commonStrings').getString('common.confirm')
+								); 
+								if (r == 0) {
+									g.network.simple_request('FM_'+g.function_type+'_DELETE',[ses(),g.notes[id].id()]);
+									setTimeout(function() { 
+										alert($('catStrings').getString('staff.cat.copy_notes.delete_note.success'));
+										refresh(); },0
+									);
+								}
+							} }(i),
+							false
+						);
+					var spacer = document.createElement('spacer'); hb.appendChild(spacer); spacer.flex = 1;
+					var btn2 = document.createElement('button'); hb.appendChild(btn2);
+						btn2.setAttribute('label', $('catStrings').getString('staff.cat.copy_notes.delete_note.close_window'));
+						btn2.setAttribute('oncommand','window.close();');
+			}
+
+		}
+		
+		function new_note() {
+			try {
+				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect UniversalBrowserWrite");
+				var xml = '<groupbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1"> \
+					<caption label="' + $('catStrings').getString('staff.cat.copy_notes.new_note.label') + '"/> \
+					<grid flex="1"><columns><column/><column flex="1"/></columns> \
+						<rows> \
+							<row><label value="' + $('catStrings').getString('staff.cat.copy_notes.new_note.public') + '"/><checkbox id="pub" name="fancy_data" checked="false"/></row> \
+							<row><label value="' + $('catStrings').getString('staff.cat.copy_notes.new_note.title') + '"/><textbox id="title" name="fancy_data" context="clipboard"/></row> \
+							<row><label value="' + $('catStrings').getString('staff.cat.copy_notes.new_note.note') + '"/><textbox multiline="true" id="note" name="fancy_data" context="clipboard"/></row> \
+							<row><spacer/><hbox> \
+								<button label="' + $('catStrings').getString('staff.cat.copy_notes.new_note.cancel.label') + '" name="fancy_cancel" accesskey="' + $('catStrings').getString('staff.cat.copy_notes.new_note.cancel.accesskey') + '"/> \
+								<button label="' + $('catStrings').getString('staff.cat.copy_notes.new_note.add_note.label') + '" accesskey="' + $('catStrings').getString('staff.cat.copy_notes.new_note.add_note.accesskey') + '" name="fancy_submit"/></hbox></row> \
+						</rows></grid></groupbox>';
+				//g.data.init({'via':'stash'});
+				//g.data.temp_note_xml = xml; g.data.stash('temp_note_xml');
+				JSAN.use('util.window'); var win = new util.window();
+				var fancy_prompt_data = win.open(
+					urls.XUL_FANCY_PROMPT,
+					//+ '?xml_in_stash=temp_note_xml'
+					//+ '&focus=' + window.escape('title')
+					//+ '&title=' + window.escape('Add Note'),
+					'fancy_prompt', 'chrome,resizable,modal,width=700,height=500',
+					{ 'xml' : xml, 'focus' : 'title', 'title' : $('catStrings').getString('staff.cat.copy_notes.new_note.add_note.label') }
+				);
+				//g.data.init({'via':'stash'});
+				if (fancy_prompt_data.fancy_status == 'complete') {
+					//alert(js2JSON(g.data.fancy_prompt_data));
+					var note = new g.constructor();
+					note.isnew(1);
+					note.title( fancy_prompt_data.title );
+					note.value( fancy_prompt_data.note );
+					note.pub( get_bool( fancy_prompt_data.pub ) ? get_db_true() : get_db_false() );
+					note[g.object_type]( g.object_id );
+					var r = g.network.simple_request('FM_'+g.function_type+'_CREATE',[ ses(), note ]);
+					if (typeof r.ilsevent != 'undefined') throw(r);
+					setTimeout(function() {
+						alert($('catStrings').getString('staff.cat.copy_notes.new_note.success'));
+						refresh();},0
+					);
+				}
+			} catch(E) {
+				g.error.standard_unexpected_error_alert($('catStrings').getString('staff.cat.copy_notes.new_note.error'),E);
+			}
+		}
+
+	]]>
+	</script>
+
+	<messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+	<messagecatalog id="circStrings" src="/xul/server/locale/<!--#echo var='locale'-->/circ.properties" />
+
+	<stack hidden="true" id="note_template" flex="1">
+		<groupbox flex="1" style="background-color: black;"/>
+		<groupbox flex="1" style="background-color: #FFDE00; -moz-border-radius-topright: 35px;" >
+			<hbox>
+				<description name="title" style="font-weight: bold"/>
+				<spacer flex="1"/>
+				<description name="create_date" style="font-weight: bold"/>
+				<description name="pub" style="font-weight: bold"/>
+			</hbox>
+			<description name="value"/>
+		</groupbox>
+	</stack>
+
+	<vbox flex="1" class="my_overflow" id="notes_panel">
+	</vbox>
+
+
+</window>
+

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.js	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.js	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,139 @@
+dump('entering serial/scap_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.scap_editor = function (params) {
+    try {
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+        JSAN.use('util.error'); this.error = new util.error();
+        JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+        JSAN.use('util.network'); this.network = new util.network();
+    } catch(E) {
+        dump('serial/scap_editor: ' + E + '\n');
+    }
+
+    /* This keeps track of what fields have been edited for styling purposes */
+    this.changed = {};
+
+    /* This holds the original values for prepopulating the field editors */
+    this.editor_values = {};
+
+};
+
+serial.scap_editor.prototype = {
+    // we could do this with non-standard '__proto__' property instead
+    'editor_base_init' : serial.editor_base.editor_base_init,
+    'editor_base_apply' : serial.editor_base.editor_base_apply,
+    'editor_base_save' : serial.editor_base.editor_base_save,
+
+    'fm_type' : 'scap',
+    'fm_type_plural' : 'scaps',
+
+    'init' : function (params) {
+        var obj = this;
+
+        params.retrieve_function = 'FM_SCAP_BATCH_RETRIEVE.authoritative';
+
+        obj.editor_base_init(params);
+
+        /* Do it */
+        obj.summarize( obj.scaps );
+        obj.render();
+    },
+
+    /******************************************************************************************************/
+    /* Restore backup copies */
+
+    'reset' :  serial.editor_base.editor_base_reset,
+
+    /******************************************************************************************************/
+    /* Apply a value to a specific field on all the copies being edited */
+
+    'apply' : function(field,value) {
+        var obj = this;
+
+        obj.editor_base_apply(field, value);
+    },
+
+    /******************************************************************************************************/
+
+    'init_panes' : function () {
+        var obj = this;
+        obj.panes_and_field_names = {
+
+        /* These get shown in the left panel */
+        'scap_editor_left_pane' :
+        [
+            [
+                'ID',
+                { 
+                    render: '"ID : " + fm.id();', 
+                    //input: 'c = function(v){ obj.apply("distribution",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+
+                }
+            ],
+            [
+                $('catStrings').getString('staff.cat.copy_editor.field.creation_date.label'),
+                {
+                    render: 'fm.create_date() == null ? "<Unset>" : util.date.formatted_date( fm.create_date(), "%F");',
+                }
+            ],
+            [
+                'Type',
+                {
+                    render: 'fm.type();',
+                    input: 'c = function(v){ obj.apply("type",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ ["basic", "basic"], ["index", "index"], ["supplement", "supplement"] ] ); x.setAttribute("value",obj.editor_values.type); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'type'
+                }
+            ],
+            [
+                'Active?',
+                {
+                    render: 'fm.active() == null ? $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null") : ( get_bool( fm.active() ) ? $("catStrings").getString("staff.cat.copy_editor.field.circulate.yes_or_true") : $("catStrings").getString("staff.cat.copy_editor.field.circulate.no_or_false") )',
+                    input: 'c = function(v){ obj.apply("active",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ $("catStrings").getString("staff.cat.copy_editor.field.circulate.yes_or_true"), get_db_true() ], [ $("catStrings").getString("staff.cat.copy_editor.field.circulate.no_or_false"), get_db_false() ] ] ); x.setAttribute("value",obj.editor_values.active); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'active',
+                    dropdown_key: 'fm.active()'
+                }
+            ],
+            [
+                'Pattern Code (temporary)',
+                { 
+                    render: 'fm.pattern_code() == null ? "" : fm.pattern_code();',
+                    input: 'c = function(v){ obj.apply("pattern_code",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.pattern_code); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'pattern_code'
+                }
+            ]
+        ]
+
+        };
+    },
+
+    /******************************************************************************************************/
+    /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+    'summarize' :  serial.editor_base.editor_base_summarize,
+
+    /******************************************************************************************************/
+    /* Display the summarized data and inputs for editing */
+
+    'render' :  serial.editor_base.editor_base_render,
+
+    /******************************************************************************************************/
+    /* This actually draws the change button and input widget for a given field */
+    'render_input' : serial.editor_base.editor_base_render_input,
+
+    /******************************************************************************************************/
+    /* save the caption/patterns */
+
+    'save' : function() {
+        var obj = this;
+        obj.editor_base_save('open-ils.serial.caption_and_pattern.batch.update');
+    },
+
+    /******************************************************************************************************/
+    'save_attributes' : serial.editor_base.editor_base_save_attributes
+};
+
+dump('exiting serial/scap_editor.js\n');

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.xul	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Caption/Pattern Editor Overlay -->
+
+<!-- LOCALIZATION -->
+<!DOCTYPE overlay PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<overlay id="serial_scap_editor_panel_overlay" 
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+	<vbox flex="1" id="serial_scap_editor_panel" class="my_overflow">
+        <vbox id="brief_display_box"/>
+
+		<hbox flex="1" style="overflow: auto">
+			<vbox flex="1">
+				<label value="Caption and Pattern" style="font-weight: bold; font-size: large"/>
+				<vbox id="scap_editor_left_pane" flex="1"/>
+			</vbox>
+        </hbox>
+
+		<hbox id="scap_editor_nav">
+			<spacer flex="1"/>
+			<button id="scap_save" label="&staff.serial.scap_editor.modify;" hidden="true" accesskey="&staff.serial.scap_editor.modify.accesskey;" oncommand="g.manage_subs.scap_editor.save()" />
+			<!--<button id="cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>-->
+		</hbox>
+
+		<spacer/>
+	</vbox>
+
+</overlay>
+

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sdist_editor.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sdist_editor.js	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sdist_editor.js	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,407 @@
+dump('entering serial/sdist_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.sdist_editor = function (params) {
+    try {
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+        JSAN.use('util.error'); this.error = new util.error();
+        JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+        JSAN.use('util.network'); this.network = new util.network();
+    } catch(E) {
+        dump('serial/sdist_editor: ' + E + '\n');
+    }
+
+    /* This keeps track of what fields have been edited for styling purposes */
+    this.changed = {};
+
+    /* This holds the original values for prepopulating the field editors */
+    this.editor_values = {};
+
+    // setup sre arrays
+    var mfhd_details = this.data.mfhd.details;
+    this.sre_id_map = {};
+    this.sres_ou_map = {};
+    for (var i = 0; i < mfhd_details.length; i++) {
+        var mfhd_detail = mfhd_details[i];
+        mfhd_detail.label = mfhd_detail.label + ' (' + (mfhd_detail.entryNum + 1) + ')';
+        var sre_id = mfhd_detail.id;
+        var org_unit_id = mfhd_detail.owning_lib;
+        this.sre_id_map[sre_id] = mfhd_detail;
+        if (!this.sres_ou_map[org_unit_id]) {
+            this.sres_ou_map[org_unit_id] = [];
+        }
+        this.sres_ou_map[org_unit_id].push(mfhd_detail);
+    }
+};
+
+serial.sdist_editor.prototype = {
+    // we could do this with non-standard '__proto__' property instead
+    'editor_base_init' : serial.editor_base.editor_base_init,
+    'editor_base_apply' : serial.editor_base.editor_base_apply,
+    'editor_base_save' : serial.editor_base.editor_base_save,
+
+    'fm_type' : 'sdist',
+    'fm_type_plural' : 'sdists',
+    'can_have_notes' : true,
+
+    'init' : function (params) {
+        var obj = this;
+
+        params.retrieve_function = 'FM_SDIST_FLESHED_BATCH_RETRIEVE.authoritative';
+
+        obj.editor_base_init(params);
+
+        obj.multi_org_edit = false;
+        var org_unit = obj.sdists[0].holding_lib();
+        for (var i = 1; i < obj.sdists.length; i++) {
+            if (obj.sdists[i].holding_lib() != org_unit) {
+                obj.multi_org_edit = true;
+                break;
+            }
+        }        
+
+        /* Do it */
+        obj.summarize( obj.sdists );
+        obj.render();
+    },
+
+    /******************************************************************************************************/
+    /* Restore backup copies */
+
+    'reset' :  serial.editor_base.editor_base_reset,
+
+    /******************************************************************************************************/
+    /* Apply a value to a specific field on all the copies being edited */
+
+    'apply' : function(field,value) {
+        var obj = this;
+
+        // null out call number if the holding lib is changed
+        obj.holding_lib_changed = (field == 'holding_lib');
+        var loop_func = function(sdist) {
+            if (obj.holding_lib_changed) {
+                sdist['bind_call_number'](null);
+                obj.changed['Bind Call Number'] = true;
+                sdist['receive_call_number'](null);
+                obj.changed['Receive Call Number'] = true;
+                sdist['bind_unit_template'](null);
+                obj.changed['Bind Unit Template'] = true;
+                sdist['receive_unit_template'](null);
+                obj.changed['Receive Unit Template'] = true;
+                sdist['record_entry'](null);
+                obj.changed['Legacy Record Entry'] = true;
+            }
+        }
+        obj.editor_base_apply(field, value, loop_func);
+        obj.holding_lib_changed = false;
+    },
+
+    /******************************************************************************************************/
+
+    'render_call_number' : function(cn) {
+        var obj = this;
+        if (cn === null) {
+            return "<Unset>";
+        } else if (typeof cn != 'object') {
+            return obj.acn_label_map[cn];
+        } else {
+            return cn.label()
+        }
+    },
+
+    'render_unit_template' : function(ut) {
+        var obj = this;
+        if (ut === null) {
+            return "<Unset>";
+        } else if (typeof ut != 'object') {
+            return obj.act_name_map[ut];
+        } else {
+            return ut.name()
+        }
+    },
+
+    'render_record_entry' : function(sre) {
+        var obj = this;
+        var sre_id;
+        if (sre === null) {
+            return "<Unset>";
+        } else if (typeof sre != 'object') {
+            sre_id = sre;
+        } else {
+            sre_id = sre.id();
+        }
+        return obj.sre_id_map[sre_id].label;
+    },
+
+    'init_panes' : function () {
+        var obj = this;
+        obj.panes_and_field_names = {
+
+        /* These get shown in the left panel */
+        'sdist_editor_left_pane' :
+        [
+            [
+                'ID',
+                { 
+                    render: '"ID : " + fm.id();', 
+                    //input: 'c = function(v){ obj.apply("distribution",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+
+                }
+            ],
+            [
+                'Label',
+                { 
+                    render: 'fm.label() == null ? "" : fm.label();',
+                    input: 'c = function(v){ obj.apply("label",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.label); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'label'
+                }
+            ],
+            [
+                'Unit Label Prefix',
+                {
+                    render: 'fm.unit_label_prefix() == null ? "" : fm.unit_label_prefix();',
+                    input: 'c = function(v){ obj.apply("unit_label_prefix",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.unit_label_prefix); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'unit_label_prefix'
+                }
+            ],
+            [
+                'Unit Label Suffix',
+                { 
+                    render: 'fm.unit_label_suffix() == null ? "" : fm.unit_label_suffix();',
+                    input: 'c = function(v){ obj.apply("unit_label_suffix",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.unit_label_suffix); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'unit_label_suffix'
+                }
+            ],
+        ],
+        /* These get shown in the right panel */
+            'sdist_editor_right_pane' :
+        [
+            [
+                'Holding Lib',
+                {
+                    render: 'typeof fm.holding_lib() == "object" ? fm.holding_lib().shortname() : obj.data.hash.aou[ fm.holding_lib() ].shortname()',
+                    input: 'c = function(v){ if (obj.editor_values.holding_lib != v) obj.apply("holding_lib",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.data.list.aou, function(myobj) { var sname = myobj.shortname(); for (i = sname.length; i < 20; i++) sname += " "; return [ myobj.name() ? sname + " " + myobj.name() : myobj.shortname(), myobj.id(), ( ! get_bool( obj.data.hash.aout[ myobj.ou_type() ].can_have_vols() ) ), ( obj.data.hash.aout[ myobj.ou_type() ].depth() * 2), ]; }), obj.data.list.au[0].ws_ou()); x.setAttribute("value",obj.editor_values.holding_lib); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'holding_lib',
+                    dropdown_key: 'typeof fm.holding_lib() == "object" ? fm.holding_lib().id() : fm.holding_lib()',
+                }
+            ],
+        ],
+        /* These get shown in the right 'library-specific-options' panel */
+        'sdist_editor_lso_pane' :
+        [
+            [
+                'Legacy Record Entry',
+                {
+                    render: 'obj.render_record_entry(fm.record_entry())',
+                    input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("record_entry",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_sre_details_list(), function(obj) { return [ obj.label, obj.id ]; }).sort()); x.setAttribute("value",obj.editor_values.record_entry); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+                    value_key: 'record_entry',
+                    dropdown_key: 'fm.record_entry() == null ? null : typeof fm.record_entry() == "object" ? fm.record_entry().id() : fm.record_entry()'
+                }
+            ],
+            [
+                'Receive Call Number',
+                {
+                    render: 'obj.render_call_number(fm.receive_call_number())',
+                    input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("receive_call_number",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_acn_list(), function(obj) { return [ obj.label(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.receive_call_number); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+                    value_key: 'receive_call_number',
+                    dropdown_key: 'fm.receive_call_number() == null ? null : typeof fm.receive_call_number() == "object" ? fm.receive_call_number().id() : fm.receive_call_number()'
+                }
+            ],
+            [
+                'Bind Call Number',
+                {
+                    render: 'obj.render_call_number(fm.bind_call_number())',
+                    input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("bind_call_number",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_acn_list(), function(obj) { return [ obj.label(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.bind_call_number); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+                    value_key: 'bind_call_number',
+                    dropdown_key: 'fm.bind_call_number() == null ? null : typeof fm.bind_call_number() == "object" ? fm.bind_call_number().id() : fm.bind_call_number()'
+                }
+            ],
+            [
+                'Receive Unit Template',
+                {
+                    render: 'obj.render_unit_template(fm.receive_unit_template())',
+                    input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("receive_unit_template",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_act_list(), function(obj) { return [ obj.name(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.receive_unit_template); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+                    value_key: 'receive_unit_template',
+                    dropdown_key: 'fm.receive_unit_template() == null ? null : typeof fm.receive_unit_template() == "object" ? fm.receive_unit_template().id() : fm.receive_unit_template()'
+                }
+            ],
+            [
+                'Bind Unit Template',
+                {
+                    render: 'obj.render_unit_template(fm.bind_unit_template())',
+                    input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("bind_unit_template",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_act_list(), function(obj) { return [ obj.name(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.bind_unit_template); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+                    value_key: 'bind_unit_template',
+                    dropdown_key: 'fm.bind_unit_template() == null ? null : typeof fm.bind_unit_template() == "object" ? fm.bind_unit_template().id() : fm.bind_unit_template()'
+                }
+            ],
+        ],
+
+        };
+    },
+
+    /******************************************************************************************************/
+    /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+    'summarize' :  serial.editor_base.editor_base_summarize,
+
+    /******************************************************************************************************/
+    /* Display the summarized data and inputs for editing */
+
+    'render' :  serial.editor_base.editor_base_render,
+
+    /******************************************************************************************************/
+    /* This actually draws the change button and input widget for a given field */
+    'render_input' : serial.editor_base.editor_base_render_input,
+
+    /******************************************************************************************************/
+    /* save the distributions */
+
+    'save' : function() {
+        var obj = this;
+        obj.editor_base_save('open-ils.serial.distribution.fleshed.batch.update');
+    },
+
+    /******************************************************************************************************/
+    /* spawn notes interface */
+
+    'notes' : function() {
+        var obj = this;
+        JSAN.use('util.window'); var win = new util.window();
+        win.open(
+            urls.XUL_SERIAL_NOTES, 
+            //+ '?copy_id=' + window.escape(obj.sdists[0].id()),
+            'Distribution Notes','chrome,resizable,modal',
+            { 'object_id' : obj.sdists[0].id(), 'function_type' : 'SDISTN', 'object_type' : 'distribution', 'constructor' : sdistn }
+        );
+    },
+
+    /******************************************************************************************************/
+    'save_attributes' : serial.editor_base.editor_base_save_attributes,
+
+    /******************************************************************************************************/
+    /* This returns a list of sre details appropriate for the distributions being edited */
+
+    'get_sre_details_list' : function() {
+        var obj = this;
+        try {
+            /* we only show this list if dealing with one org_unit, default to first sdist*/
+            var lib_id = typeof obj.sdists[0].holding_lib() == 'object' ? obj.sdists[0].holding_lib().id() : obj.sdists[0].holding_lib();
+            var sre_details_list = obj.sres_ou_map[lib_id];
+            if (sre_details_list == null) {
+                return [];
+            } else {
+                return sre_details_list;
+            }
+        } catch(E) {
+            obj.error.standard_unexpected_error_alert('get_sre_details_list',E);
+            return [];
+        }
+    },
+
+    /******************************************************************************************************/
+    /* This returns a list of acn's appropriate for the distributions being edited */
+
+    'get_acn_list' : function() {
+        var obj = this;
+        try {
+            var lib_id = typeof obj.sdists[0].holding_lib() == 'object' ? obj.sdists[0].holding_lib().id() : obj.sdists[0].holding_lib();
+
+            if (!obj.acn_lists) {
+                obj.acn_lists = {};
+            }
+
+            // return cached version if we have it
+            if (obj.acn_lists[lib_id]) {
+                return obj.acn_lists[lib_id];
+            }
+
+            /* we only show this list if dealing with one org_unit, default to first sdist*/
+            var my_sre = obj.network.request(
+                'open-ils.pcrud',
+                'open-ils.pcrud.retrieve.sre',
+                [ ses(), obj.sdists[0].record_entry() ]
+            );
+
+            if (!my_sre) {
+                return [];
+            }
+
+            var acn_list = obj.network.request(
+                'open-ils.pcrud',
+                'open-ils.pcrud.search.acn',
+                [ ses(), {"record" : my_sre.record(), "owning_lib" : lib_id, "deleted" : 'f' }, {"order_by" : {"acn" : "label"} } ]
+            );
+
+            if (!acn_list) {
+                return [];
+            } else if (!acn_list.length) {
+                acn_list = [acn_list];
+            }
+
+            // build label map
+            obj.acn_label_map = {};
+            for (i = 0; i < acn_list.length; i++) {
+                obj.acn_label_map[acn_list[i].id()] = acn_list[i].label();
+            }
+
+            // cache the list
+            obj.acn_lists[lib_id] = acn_list;
+            return acn_list;
+
+        } catch(E) {
+            obj.error.standard_unexpected_error_alert('get_acn_list',E);
+            return [];
+        }
+    },
+
+    /******************************************************************************************************/
+    /* This returns a list of asset copy templates appropriate for the distributions being edited */
+
+    'get_act_list' : function() {
+        var obj = this;
+        try {
+            /* we only show this list if dealing with one org_unit, default to first sdist*/
+            var lib_id = typeof obj.sdists[0].holding_lib() == 'object' ? obj.sdists[0].holding_lib().id() : obj.sdists[0].holding_lib();
+
+            if (!obj.act_lists) {
+                obj.act_lists = {};
+            }
+
+            // return cached version if we have it
+            if (obj.act_lists[lib_id]) {
+                return obj.act_lists[lib_id];
+            }
+            
+            var act_list = obj.network.request(
+                'open-ils.pcrud',
+                'open-ils.pcrud.search.act',
+                [ ses(), {"owning_lib" : lib_id }, {"order_by" : {"act" : "name"} } ]
+            );
+
+            if (act_list == null) {
+                return [];
+            } else if (!act_list.length) {
+                act_list = [act_list];
+            }
+
+            // build name map
+            obj.act_name_map = {};
+            for (i = 0; i < act_list.length; i++) {
+                obj.act_name_map[act_list[i].id()] = act_list[i].name();
+            }
+
+            // cache the list
+            obj.act_lists[lib_id] = act_list;
+            return act_list;
+        } catch(E) {
+            obj.error.standard_unexpected_error_alert('get_act_list',E);
+            return [];
+        }
+    }
+
+};
+
+dump('exiting serial/sdist_editor.js\n');

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sdist_editor.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sdist_editor.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sdist_editor.xul	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Distribution Editor Overlay -->
+
+<!-- LOCALIZATION -->
+<!DOCTYPE overlay PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<overlay id="serial_sdist_editor_panel_overlay" 
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+	<vbox flex="1" id="serial_sdist_editor_panel" class="my_overflow">
+        <vbox id="brief_display_box"/>
+
+		<hbox flex="1" style="overflow: auto">
+			<vbox flex="1">
+				<label value="Distribution" style="font-weight: bold; font-size: large"/>
+				<vbox id="sdist_editor_left_pane" flex="1"/>
+			</vbox>
+			<splitter><grippy /></splitter>
+			<vbox flex="1">
+				<vbox id="sdist_editor_right_pane"/>
+                <groupbox>
+                    <caption label="Library Specific Options" />
+                    <description>Note: Changing the 'Holding Lib' will unset all of these values</description>
+                    <vbox id="sdist_editor_lso_pane" flex="1"/>
+                </groupbox>
+			</vbox>
+		</hbox>
+
+		<hbox id="sdist_editor_nav">
+			<spacer flex="1"/>
+			<button id="sdist_notes" label="&staff.serial.sdist_editor.notes;" accesskey="&staff.serial.sdist_editor.notes.accesskey;" oncommand="g.manage_subs.sdist_editor.notes()" />
+			<button id="sdist_save" label="&staff.serial.sdist_editor.modify;" hidden="true" accesskey="&staff.serial.ssub_editor.modify.accesskey;" oncommand="g.manage_subs.sdist_editor.save()" />
+			<!--<button id="cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>-->
+		</hbox>
+
+		<spacer/>
+	</vbox>
+
+</overlay>
+

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/select_aou.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/select_aou.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/select_aou.xul	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Select AOU Dialog -->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/cat.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+	<!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+
+<window id="select_aou_win" title="Select Org Unit"
+	onload="try { my_init(); font_helper(); persist_helper(); } catch(E) { alert(E); }" oils_persist="height width"
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+	<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+	<!-- BEHAVIOR -->
+	<script type="text/javascript">var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};</script>
+	<scripts id="openils_util_scripts"/>
+
+	<script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+	<script>
+	<![CDATA[
+		function $(id) { return document.getElementById(id); }
+		function $c(n) { return document.createElement(n); }
+
+		function my_init() {
+			try {
+				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+                if (typeof JSAN == 'undefined') { throw( $("commonStrings").getString('common.jsan.missing') ); }
+				JSAN.errorLevel = "die"; // none, warn, or die
+				JSAN.addRepository('/xul/server/');
+				JSAN.use('util.error'); g.error = new util.error();
+				g.error.sdump('D_TRACE','my_init() for serial/select_aou.xul');
+
+                JSAN.use('util.file'); JSAN.use('util.widgets');
+
+                var file; var list_data; var ml;
+
+                file = new util.file('offline_ou_list');
+                if (file._file.exists()) {
+                    list_data = file.get_object(); file.close();
+                    ml = util.widgets.make_menulist( list_data[0], list_data[1] );
+                    ml.setAttribute('id','lib_menu');
+                    document.getElementById('x_lib_menu').appendChild(ml);
+                    ml.addEventListener(
+                        'command',
+                        function(ev) {
+                            //if (document.getElementById('refresh_button')) document.getElementById('refresh_button').focus();
+                            JSAN.use('util.file'); var file = new util.file('mfhd_create_prefs.'+opener.g.data.server_unadorned);
+                            util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ] });
+                        },
+                        false
+                    );
+                } else {
+                    throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n');  //TODO: different error?
+                }
+
+                file = new util.file('mfhd_create_prefs.'+opener.g.data.server_unadorned);
+                util.widgets.load_attributes(file);
+                ml.value = ml.getAttribute('value');
+            } catch(E) {
+                //TODO: better error
+                g.error.standard_unexpected_error_alert('', E);
+            }
+        }
+
+        g.select_aou = function() {
+            opener.g.data.create_mfhd_aou = $('lib_menu').value;
+            window.close();
+        }
+
+	]]>
+	</script>
+	
+	<messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+
+	<vbox flex="1" style="overflow: auto">
+	<groupbox flex="1">
+<!--TODO: label strings -->
+		<caption label="Select an Org Unit"/>
+		<description id="desc">Please select an Org Unit</description>
+        <hbox id="x_lib_menu"/>
+		<hbox>
+			<button label="Select"
+				accesskey="s" oncommand="g.select_aou()"/>
+			<button label="&staff.cat.record_buckets_quick.cancel.label;"
+				accesskey="&staff.cat.record_buckets_quick.cancel.accesskey;" oncommand="window.close()"/>
+		</hbox>
+		<hbox>
+		</hbox>
+	</groupbox>
+	</vbox>
+
+</window>
+

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/serctrl_main.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/serctrl_main.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/serctrl_main.xul	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,121 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Serial Control Main -->
+<!--
+vim:noet:sw=4:ts=4:
+-->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/cat.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+<!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+<?xul-overlay href="/xul/server/serial/manage_items.xul"?>
+<?xul-overlay href="/xul/server/serial/manage_subs.xul"?>
+
+<window id="serial_serctrl_main" 
+	onload="try { my_init(); font_helper(); } catch(E) { alert(E); }"
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+	<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+	<!-- BEHAVIOR -->
+	<script type="text/javascript">
+		var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};
+	</script>
+	<scripts id="openils_util_scripts"/>
+
+	<script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+
+	<messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+	<messagecatalog id="circStrings" src="/xul/server/locale/<!--#echo var='locale'-->/circ.properties" />
+    <messagecatalog id="patronStrings" src="/xul/server/locale/<!--#echo var='locale'-->/patron.properties"/>
+    <messagecatalog id="serialStrings" src="/xul/server/locale/<!--#echo var='locale'-->/serial.properties"/>
+
+	<commandset id="serial_commands">
+		<command id="cmd_add_item"/>
+		<command id="cmd_add_scap"/>
+		<command id="cmd_add_sdist"/>
+		<command id="cmd_add_siss"/>
+		<command id="cmd_add_subscriptions"/>
+		<command id="cmd_broken" />
+		<command id="cmd_clear" />
+		<command id="cmd_edit_items"/>
+        <command id="cmd_edit_sdists"/>
+        <command id="cmd_edit_subscriptions"/>
+		<command id="cmd_edit_sunit"/>
+		<command id="cmd_delete_items"/>
+		<command id="cmd_delete_scap"/>
+		<command id="cmd_delete_sdist"/>
+		<command id="cmd_delete_siss"/>
+        <command id="cmd_delete_ssub"/>
+        <command id="cmd_mark_library"/>
+        <command id="cmd_mark_subscription"/>
+		<command id="cmd_predict_items"/>
+		<command id="cmd_print_spine_labels"/>
+		<command id="cmd_receive_items"/>
+		<command id="cmd_refresh_list"/>
+		<command id="cmd_replace_barcode"/>
+        <command id="cmd_show_all_libs" />
+        <command id="cmd_show_libs_with_distributions" />
+        <command id="cmd_show_my_libs" />
+		<command id="cmd_transfer_items"/>
+        <command id="cmd_transfer_sdists"/>
+        <command id="cmd_transfer_subscription"/>
+		<command id="save_columns" />
+		<command id="sel_clip" />
+		<command id="sel_mark_items_damaged" />
+		<command id="sel_mark_items_missing" />
+        <command id="sel_mark_sdists_damaged" />
+        <command id="sel_mark_sdists_missing" />
+	</commandset>
+
+	<!--<popupset>
+		<popup id="serctrl_main_actions">
+			<menuitem command="cmd_add_items" label="&staff.cat.copy_browser.actions.cmd_add_items.label;" accesskey="&staff.cat.copy_browser.actions.cmd_add_items.accesskey;"/>
+			<menuitem command="cmd_edit_items" label="Edit Item Attributes" accesskey="&staff.cat.copy_browser.actions.cmd_edit_items.accesskey;"/>
+			<menuitem command="cmd_delete_items" label="Delete Item" accesskey="&staff.cat.copy_browser.actions.cmd_delete_items.accesskey;"/>
+			<menuitem command="sel_clip" label="&staff.cat.copy_browser.actions.sel_clip.label;" accesskey="&staff.cat.copy_browser.actions.sel_clip.accesskey;"/>
+			<menuseparator/>
+			<menuitem command="cmd_edit_volumes" label="&staff.cat.copy_browser.actions.cmd_edit_volumes.label;" accesskey="&staff.cat.copy_browser.actions.cmd_edit_volumes.accesskey;"/>
+			<menuitem command="cmd_mark_volume" label="&staff.cat.copy_browser.actions.cmd_mark_volume.label;" accesskey="&staff.cat.copy_browser.actions.cmd_mark_volume.accesskey;"/>
+			<menuitem command="cmd_transfer_volume" label="&staff.cat.copy_browser.actions.cmd_transfer_volume.label;" accesskey="&staff.cat.copy_browser.actions.cmd_transfer_volume.accesskey;"/>
+			<menuitem command="cmd_delete_volumes" label="&staff.cat.copy_browser.actions.cmd_delete_volumes.label;" accesskey=""/>
+			<menuseparator/>
+			<menuitem command="save_columns" label="&staff.cat.copy_browser.actions.save_columns.label;"/>
+			<menuitem command="cmd_refresh_list" label="&staff.cat.copy_browser.actions.cmd_refresh_list.label;" accesskey="&staff.cat.copy_browser.actions.cmd_refresh_list.accesskey;"/>
+		</popup>
+	</popupset> -->
+
+<!--	<groupbox flex="1" class="my_overflow"> -->
+        <tabbox id="serial_tabbox" flex="1">
+            <caption label="Serial Control"/>
+            <tabs>
+                <tab label="Items" />
+                <tab label="Units" />
+                <tab label="Summaries" />
+                <tab id="serial_manage_subs_tab" label="Subscriptions" />
+                <tab label="Claims" />
+            </tabs>
+            <tabpanels flex="1">
+                <tabpanel id="serial_manage_items" />
+                <tabpanel id="serial_manage_units" />
+                <tabpanel id="serial_manage_summaries" />
+                <tabpanel id="serial_manage_subs" />
+                <tabpanel id="serial_manage_claims" />
+            </tabpanels>
+        </tabbox>
+<!--	</groupbox> -->
+
+</window>
+

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/siss_editor.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/siss_editor.js	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/siss_editor.js	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,195 @@
+dump('entering serial/siss_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.siss_editor = function (params) {
+    try {
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+        JSAN.use('util.error'); this.error = new util.error();
+        JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+        JSAN.use('util.network'); this.network = new util.network();
+    } catch(E) {
+        dump('serial/siss_editor: ' + E + '\n');
+    }
+
+    /* This keeps track of what fields have been edited for styling purposes */
+    this.changed = {};
+
+    /* This holds the original values for prepopulating the field editors */
+    this.editor_values = {};
+};
+
+serial.siss_editor.prototype = {
+    // we could do this with non-standard '__proto__' property instead
+    'editor_base_init' : serial.editor_base.editor_base_init,
+    'editor_base_apply' : serial.editor_base.editor_base_apply,
+    'editor_base_save' : serial.editor_base.editor_base_save,
+
+    'fm_type' : 'siss',
+    'fm_type_plural' : 'sisses',
+    'can_have_notes' : true,
+
+    'init' : function (params) {
+        var obj = this;
+        
+        params.retrieve_function = 'FM_SISS_FLESHED_BATCH_RETRIEVE.authoritative';
+
+        obj.editor_base_init(params);
+
+        /* Do it */
+        obj.summarize( obj.sisses );
+        obj.render();
+    },
+
+    /******************************************************************************************************/
+    /* Restore backup copies */
+
+    'reset' : serial.editor_base.editor_base_reset,
+
+    /******************************************************************************************************/
+    /* Apply a value to a specific field on all the copies being edited */
+
+    'apply' : function(field,value) {
+        var obj = this;
+        if (field == 'date_published') {
+            if (value == '') { value = null; }
+        }
+        obj.editor_base_apply(field, value);
+    },
+
+    /******************************************************************************************************/
+    /* Initialize the panes */
+
+    'init_panes' : function () {
+        var obj = this;
+        obj.panes_and_field_names = {
+
+    /* These get shown in the left panel */
+            'siss_editor_left_pane' :
+        [
+            [
+                $('catStrings').getString('staff.cat.copy_editor.field.creation_date.label') + ' ', //adding extra spaces to satisfy summarize uniqueness requirements
+                {
+                    render: 'fm.create_date() == null ? "<Unset>" : util.date.formatted_date( fm.create_date(), "%F");',
+                }
+            ],
+            [
+                $('catStrings').getString('staff.cat.copy_editor.field.creator.label') + ' ',
+                {
+                    render: 'fm.creator().usrname() == null ? "<Unset>" : fm.creator().usrname();',
+                }
+            ],
+            [
+                $('catStrings').getString('staff.cat.copy_editor.field.last_edit_date.label') + ' ',
+                {
+                    render: 'fm.edit_date() == null ? "<Unset>" : util.date.formatted_date( fm.edit_date(), "%F");',
+                }
+            ],
+            [
+                $('catStrings').getString('staff.cat.copy_editor.field.last_editor.label') + ' ',
+                {
+                    render: 'fm.editor().usrname() == null ? "<Unset>" : fm.editor().usrname();',
+                }
+            ],
+        ],
+
+        'siss_editor_middle_pane' :
+        [
+/*rjs7 don't think we need these anymore            [
+                'Holding Type',
+                {
+                    render: 'fm.holding_type();',
+                    input: 'c = function(v){ obj.apply("holding_type",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ ["basic", "basic"], ["index", "index"], ["supplement", "supplement"] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                }
+            ],
+            [
+                'Holding Link ID',
+                {
+                    render: 'fm.holding_link_id();',
+                    input: 'c = function(v){ obj.apply("holding_link_id",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.holding_link_id); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'holding_link_id'
+                }
+            ],*/
+            [
+                'Holding Code',
+                {
+                    render: 'fm.holding_code();',
+                    input: 'c = function(v){ obj.apply("holding_code",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.holding_code); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'holding_code'
+                }
+            ],
+            [
+                'Caption/Pattern', //TODO: make this a drop-down selector, perhaps?
+                {
+                    render: 'fm.caption_and_pattern();',
+                    input: 'c = function(v){ obj.apply("caption_and_pattern",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.caption_and_pattern); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'caption_and_pattern'
+                }
+            ],
+        ],
+
+        'siss_editor_right_pane' :
+        [
+            [
+                'Date Published',
+                {
+                    render: 'fm.date_published() == null ? "" : util.date.formatted_date( fm.date_published(), "%F");',
+                    input: 'c = function(v){ obj.apply("date_published",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.date_published); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'date_published'
+                }
+            ],
+            [
+                'Issuance Label',
+                {
+                    render: 'fm.label() == null ? "" : fm.label();',
+                    input: 'c = function(v){ obj.apply("label",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.label); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'label'
+                }
+            ],
+        ],
+
+        };
+    },
+
+    /******************************************************************************************************/
+    /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+    'summarize' : serial.editor_base.editor_base_summarize,
+
+    /******************************************************************************************************/
+    /* Display the summarized data and inputs for editing */
+
+    'render' : serial.editor_base.editor_base_render,
+
+    /******************************************************************************************************/
+    /* This actually draws the change button and input widget for a given field */
+    'render_input' : serial.editor_base.editor_base_render_input,
+
+    /******************************************************************************************************/
+    /* update the issuances */
+
+    'save' : function() {
+        var obj = this;
+        obj.editor_base_save('open-ils.serial.issuance.fleshed.batch.update');
+    },
+
+    /******************************************************************************************************/
+    /* spawn issuance notes interface */
+
+    'notes' : function() {
+        var obj = this;
+        JSAN.use('util.window'); var win = new util.window();
+        win.open(
+            urls.XUL_SERIAL_NOTES, 
+            'Issuance Notes','chrome,resizable,modal',
+            { 'object_id' : obj.sisses[0].id(), 'function_type' : 'SISSN', 'object_type' : 'issuance', 'constructor' : sissn }
+        );
+    },
+
+    /******************************************************************************************************/
+    'save_attributes' : serial.editor_base.editor_base_save_attributes
+};
+
+dump('exiting serial/siss_editor.js\n');

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/siss_editor.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/siss_editor.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/siss_editor.xul	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Issuance Editor Overlay -->
+
+<!-- LOCALIZATION -->
+<!DOCTYPE overlay PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<overlay id="serial_siss_editor_panel_overlay" 
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+	<vbox flex="1" id="serial_siss_editor_panel" class="my_overflow">
+        <vbox id="brief_display_box"/>
+
+		<hbox flex="1" style="overflow: auto">
+			<vbox flex="1">
+				<label value="Issuance" style="font-weight: bold; font-size: large"/>
+				<vbox id="siss_editor_left_pane" flex="1"/>
+			</vbox>
+			<splitter><grippy /></splitter>
+			<vbox flex="1">
+				<vbox id="siss_editor_middle_pane"/>
+			</vbox>
+			<splitter><grippy /></splitter>
+			<vbox flex="1">
+				<vbox id="siss_editor_right_pane"/>
+			</vbox>
+		</hbox>
+
+		<hbox id="siss_editor_nav">
+			<spacer flex="1"/>
+			<button id="siss_notes" label="Issuance Notes" accesskey="&staff.cat.copy_editor.copy_notes.accesskey;" oncommand="g.manage_subs.siss_editor.notes()" />
+			<button id="siss_save" label="Modify Issuances" hidden="true" accesskey="&staff.cat.copy_editor.save.accesskey;" oncommand="g.manage_subs.siss_editor.save()" />
+			<!--<button id="cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>-->
+		</hbox>
+
+		<spacer/>
+	</vbox>
+
+</overlay>
+

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/ssub_editor.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/ssub_editor.js	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/ssub_editor.js	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,193 @@
+dump('entering serial/ssub_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.ssub_editor = function (params) {
+    try {
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+        JSAN.use('util.error'); this.error = new util.error();
+    } catch(E) {
+        dump('serial/ssub_editor: ' + E + '\n');
+    }
+
+    /* This keeps track of what fields have been edited for styling purposes */
+    this.changed = {};
+
+    /* This holds the original values for prepopulating the field editors */
+    this.editor_values = {};
+
+};
+
+serial.ssub_editor.prototype = {
+    // we could do this with non-standard '__proto__' property instead
+    'editor_base_init' : serial.editor_base.editor_base_init,
+    'editor_base_apply' : serial.editor_base.editor_base_apply,
+    'editor_base_save' : serial.editor_base.editor_base_save,
+
+    'fm_type' : 'ssub',
+    'fm_type_plural' : 'ssubs',
+    'can_have_notes' : true,
+
+    'init' : function (params) {
+        var obj = this;
+
+        params.retrieve_function = 'FM_SSUB_FLESHED_BATCH_RETRIEVE.authoritative';
+
+        obj.editor_base_init(params);
+
+        /* Do it */
+        obj.summarize( obj.ssubs );
+        obj.render();
+    },
+
+    /******************************************************************************************************/
+    /* Restore backup copies */
+
+    'reset' : serial.editor_base.editor_base_reset,
+
+    /******************************************************************************************************/
+    /* Apply a value to a specific field on all the copies being edited */
+
+    'apply' : function(field, value) {
+        var obj = this;
+
+        if (field == 'start_date' || field == 'end_date') {
+            if (value == '') { value = null; }
+        }
+
+        obj.editor_base_apply(field, value);
+    },
+
+
+    /******************************************************************************************************/
+    /* These need data from the middle layer to render */
+
+    /*
+    function init_panes0() {
+    obj.special_exception = {};
+    obj.special_exception[$('catStrings').getString('staff.cat.copy_editor.field.owning_library.label')] = function(label,value) {
+            JSAN.use('util.widgets');
+            if (value>0) { // an existing call number
+                obj.network.simple_request(
+                    'FM_ACN_RETRIEVE.authoritative',
+                    [ value ],
+                    function(req) {
+                        var cn = '??? id = ' + value;
+                        try {
+                            cn = req.getResultObject();
+                        } catch(E) {
+                            obj.error.sdump('D_ERROR','callnumber retrieve: ' + E);
+                        }
+                        util.widgets.set_text(label,obj.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
+                    }
+                );
+            } else { // a yet to be created call number
+                if (obj.callnumbers) {
+                    util.widgets.set_text(label,obj.data.hash.aou[ obj.callnumbers[value].owning_lib ].shortname() + ' : ' + obj.callnumbers[value].label);
+                }
+            }
+        };
+    },
+    */
+
+    /******************************************************************************************************/
+    /* These get show in the left panel */
+
+    'init_panes' : function () {
+        var obj = this;
+        obj.panes_and_field_names = {
+
+        'left_pane' :
+        [
+            [
+                'ID',
+                { 
+                    render: '"ID : " + fm.id();', 
+                    //input: 'c = function(v){ obj.apply("distribution",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+
+                }
+            ],
+            [
+                'Owning Lib',
+                {
+                    render: 'typeof fm.owning_lib() == "object" ? fm.owning_lib().shortname() : obj.data.hash.aou[ fm.owning_lib() ].shortname()',
+                    input: 'c = function(v){ obj.apply("owning_lib",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.data.list.aou, function(myobj) { var sname = myobj.shortname(); for (i = sname.length; i < 20; i++) sname += " "; return [ myobj.name() ? sname + " " + myobj.name() : myobj.shortname(), myobj.id(), ( ! get_bool( obj.data.hash.aout[ myobj.ou_type() ].can_have_vols() ) ), ( obj.data.hash.aout[ myobj.ou_type() ].depth() * 2), ]; }), obj.data.list.au[0].ws_ou()); x.setAttribute("value",obj.editor_values.owning_lib); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'owning_lib',
+                    dropdown_key: 'fm.owning_lib() == null ? null : typeof fm.owning_lib() == "object" ? fm.owning_lib().id() : fm.owning_lib()',
+                }
+            ],
+        ],
+
+            'right_pane' :
+        [
+            [
+                'Start Date',
+                { 
+                    render: 'fm.start_date() == null ? "" : util.date.formatted_date( fm.start_date(), "%F");',
+                    input: 'c = function(v){ obj.apply("start_date",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.start_date); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'start_date'
+                }
+            ],
+            [
+                'End Date',
+                {
+                    render: 'fm.end_date() == null ? "" : util.date.formatted_date( fm.end_date(), "%F");',
+                    input: 'c = function(v){ obj.apply("end_date",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.end_date); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'end_date'
+                }
+            ],
+            [
+                'Date Offset',
+                { 
+                    render: 'fm.expected_date_offset() == null ? "" : fm.expected_date_offset();',
+                    input: 'c = function(v){ obj.apply("expected_date_offset",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.expected_date_offset); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'expected_date_offset'
+                }
+            ],
+        ],
+
+        };
+    },
+
+    /******************************************************************************************************/
+    /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+    'summarize' : serial.editor_base.editor_base_summarize,
+
+    /******************************************************************************************************/
+    /* Display the summarized data and inputs for editing */
+
+    'render' : serial.editor_base.editor_base_render,
+
+    /******************************************************************************************************/
+    /* This actually draws the change button and input widget for a given field */
+    'render_input' : serial.editor_base.editor_base_render_input,
+
+    /******************************************************************************************************/
+    /* save the subscriptions */
+
+    'save' : function() {
+        var obj = this;
+        obj.editor_base_save('open-ils.serial.subscription.fleshed.batch.update');
+    },
+
+    /******************************************************************************************************/
+    /* spawn notes interface */
+
+    'notes' : function() {
+        var obj = this;
+        JSAN.use('util.window'); var win = new util.window();
+        win.open(
+            urls.XUL_SERIAL_NOTES, 
+            'Subscription Notes','chrome,resizable,modal',
+            { 'object_id' : obj.ssubs[0].id(), 'function_type' : 'SSUBN', 'object_type' : 'subscription', 'constructor' : ssubn }
+        );
+    },
+
+    /******************************************************************************************************/
+    'save_attributes' : serial.editor_base.editor_base_save_attributes
+};
+
+dump('exiting serial/ssub_editor.js\n');

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/ssub_editor.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/ssub_editor.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/ssub_editor.xul	2010-07-14 18:36:11 UTC (rev 16931)
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Subscription Editor Overlay -->
+
+<!-- LOCALIZATION -->
+<!DOCTYPE overlay PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<overlay id="serial_ssub_editor_panel_overlay" 
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+	<vbox flex="1" id="serial_ssub_editor_panel" class="my_overflow">
+        <vbox id="brief_display_box"/>
+
+		<hbox flex="1" style="overflow: auto">
+			<vbox flex="1">
+				<label value="Subscription" style="font-weight: bold; font-size: large"/>
+				<vbox id="left_pane" flex="1"/>
+			</vbox>
+			<splitter><grippy /></splitter>
+			<vbox flex="1">
+				<label value=" " style="font-weight: bold; font-size: large"/>
+				<vbox id="right_pane" flex="1"/>
+			</vbox>
+		</hbox>
+
+		<hbox id="nav">
+			<spacer flex="1"/>
+			<button id="ssub_notes" label="&staff.serial.ssub_editor.notes;" accesskey="&staff.serial.ssub_editor.notes.accesskey;" oncommand="g.manage_subs.ssub_editor.notes()" />
+			<button id="ssub_save" label="&staff.serial.ssub_editor.modify;" hidden="true" accesskey="&staff.serial.ssub_editor.modify.accesskey;" oncommand="g.manage_subs.ssub_editor.save()" />
+			<!--<button id="cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>-->
+		</hbox>
+
+		<spacer/>
+	</vbox>
+
+</overlay>
+



More information about the open-ils-commits mailing list