Bring Conifer patron XUL into line with 2.0
authordbs <dbs@6d9bc8c9-1ec2-4278-b937-99fde70a366f>
Tue, 12 Apr 2011 13:54:03 +0000 (13:54 +0000)
committerdbs <dbs@6d9bc8c9-1ec2-4278-b937-99fde70a366f>
Tue, 12 Apr 2011 13:54:03 +0000 (13:54 +0000)
Eliminate date of birth and net_access display elements

git-svn-id: svn://svn.open-ils.org/ILS-Contrib/conifer/branches/rel_2_0@1333 6d9bc8c9-1ec2-4278-b937-99fde70a366f

xul/server/patron/summary.js
xul/server/patron/summary_overlay.xul
xul/server/patron/ue.xhtml [deleted file]
xul/server/patron/ue_config.js [deleted file]
xul/server/patron/util.js

index cb094d1..52f72dc 100644 (file)
@@ -7,770 +7,989 @@ var offlineStrings = $('offlineStrings');
 if (typeof patron == 'undefined') patron = {};
 patron.summary = function (params) {
 
-       JSAN.use('util.error'); this.error = new util.error();
-       JSAN.use('util.window'); this.window = new util.window();
-       JSAN.use('util.network'); this.network = new util.network();
-       this.w = window;
+    JSAN.use('util.error'); this.error = new util.error();
+    JSAN.use('util.window'); this.window = new util.window();
+    JSAN.use('util.network'); this.network = new util.network();
+    JSAN.use('util.widgets'); JSAN.use('util.date');
+    this.w = window;
 }
 
 patron.summary.prototype = {
 
-       'init' : function( params ) {
-
-               var obj = this;
-
-               obj.barcode = params['barcode'];
-               obj.id = params['id'];
-               if (params['show_name']) {
-                       document.getElementById('patron_name').hidden = false;
-                       document.getElementById('patron_name').setAttribute('hidden','false');
-               }
-
-               JSAN.use('OpenILS.data'); this.OpenILS = {}; 
-               obj.OpenILS.data = new OpenILS.data(); obj.OpenILS.data.init({'via':'stash'});
-
-               JSAN.use('util.controller'); obj.controller = new util.controller();
-               obj.controller.init(
-                       {
-                               control_map : {
-                                       'cmd_broken' : [
-                                               ['command'],
-                                               function() { alert($("commonStrings").getString('common.unimplemented')); }
-                                       ],
-                                       'patron_alert' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() {
-                                                               JSAN.use('util.widgets');
-                                                               util.widgets.remove_children( e );
-                                                               if (obj.patron.alert_message()) {
-                                                                       e.appendChild(
-                                                                               document.createTextNode(
-                                                                                       obj.patron.alert_message()
-                                                                               )
-                                                                       );
-                                                                       e.parentNode.hidden = false;
-                                                               } else {
-                                                                       e.parentNode.hidden = true;
-                                                               }
-                                                       };
-                                               }
-                                       ],
-                                       'patron_usrname' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() {
-                                                               e.setAttribute('value',obj.patron.usrname());
-                                                       };
-                                               }
-                                       ],
-                                       'patron_profile' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.OpenILS.data.hash.pgt[
-                                                                               obj.patron.profile()
-                                                                       ].name()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_net_access' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               // not applicable to Conifer
-                                                       };
-                                               }
-                                       ],
-                                       'patron_standing_penalties' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() {
-                                                               JSAN.use('util.widgets');
-                                                               util.widgets.remove_children(e);
-                                                               var penalties = obj.patron.standing_penalties();
-                                if (penalties.length == 0) {
-                                                                       var row = document.createElement('row');
-                                                                       var label = document.createElement('label');
-                                    label.setAttribute('value',patronStrings.getString('staff.patron.summary.standing_penalty.none'));
-                                    addCSSClass(label,'NO_PENALTY');
-                                                                       row.appendChild(label);
-                                                                       e.appendChild(row);
+    'init' : function( params ) {
+
+        var obj = this;
+
+        obj.barcode = params['barcode'];
+        obj.id = params['id'];
+        if (params['show_name']) {
+            document.getElementById('patron_name').hidden = false;
+            document.getElementById('patron_name').setAttribute('hidden','false');
+        }
+
+        JSAN.use('OpenILS.data'); this.OpenILS = {}; 
+        obj.OpenILS.data = new OpenILS.data(); obj.OpenILS.data.init({'via':'stash'});
+        var obscure_dob = String( obj.OpenILS.data.hash.aous['circ.obscure_dob'] ) == 'true';
+
+        JSAN.use('util.functional'); JSAN.use('patron.util'); JSAN.use('util.list'); 
+
+        if (document.getElementById('group_list')) {
+            obj.group_list = new util.list('group_list');
+            obj.group_list.init( {
+                'columns' : [
+                    { 'id' : 'gl_family_name', 'flex' : 1, 
+                        'label' : patronStrings.getString('staff.patron.summary.group_list.column.family_name.label'),
+                        'render' : function(my) { return my.family_name; } },
+                    { 'id' : 'gl_first_given_name', 'flex' : 1, 
+                        'label' : patronStrings.getString('staff.patron.summary.group_list.column.first_given_name.label'),
+                        'render' : function(my) { return my.first_given_name; } },
+                    { 'id' : 'gl_second_given_name', 'flex' : 1, 'hidden' : true, 
+                        'label' : patronStrings.getString('staff.patron.summary.group_list.column.second_given_name.label'),
+                        'render' : function(my) { return my.second_given_name; } },
+                    { 'id' : 'gl_home_lib', 'flex' : 1, 'hidden' : true, 
+                        'label' : patronStrings.getString('staff.patron.summary.group_list.column.home_ou.label'),
+                        'render' : function(my) { return obj.OpenILS.data.hash.aou[ my.home_ou ].shortname(); } },
+                    { 'id' : 'gl_balance_owed', 'flex' : 1, 'sort_type' : 'money',
+                        'label' : patronStrings.getString('staff.patron.summary.group_list.column.balance_owed.label'),
+                        'render' : function(my) { return my.balance_owed; } }
+                ],
+                'retrieve_row' : function(params) {
+                    var id = params.retrieve_id;
+                    var blob = patron.util.retrieve_name_via_id( ses(), id );
+                    var row = params.row; if (typeof row.my == 'undefined') { row.my = {}; }
+                    row.my.family_name = blob[0];
+                    row.my.first_given_name = blob[1];
+                    row.my.second_given_name = blob[2];
+                    row.my.home_ou = blob[3];
+                    if (obj.group_owed[ id ]) {
+                        row.my.balance_owed = obj.group_owed[ id ];
+                    }
+                    if (typeof params.on_retrieve == 'function') {
+                        params.on_retrieve(row);
+                    }
+                    return row;
+                }
+            } );
+            $('group_list_actions').appendChild( obj.group_list.render_list_actions() );
+            obj.group_list.set_list_actions();
+        }
+
+        if (document.getElementById('stat_cat_list')) {
+            obj.stat_cat_list = new util.list('stat_cat_list');
+            obj.stat_cat_list.init( {
+                'columns' : [].concat(
+                    obj.stat_cat_list.fm_columns( 'actsc', {
+                        'actsc_id' : { 'hidden' : true },
+                        'actsc_opac_visible' : { 'hidden' : true },
+                        'actsc_usr_summary' : { 'hidden' : true }
+                    } )
+                ).concat(
+                    obj.stat_cat_list.fm_columns( 'actscecm', {
+                        'actscecm_id' : { 'hidden' : true }
+                    } )
+                )
+            } );
+            $('stat_cat_list_actions').appendChild( obj.stat_cat_list.render_list_actions() );
+            obj.stat_cat_list.set_list_actions();
+        }
+
+        JSAN.use('util.controller'); obj.controller = new util.controller();
+        obj.controller.init(
+            {
+                control_map : {
+                    'cmd_broken' : [
+                        ['command'],
+                        function() { alert($("commonStrings").getString('common.unimplemented')); }
+                    ],
+                    'radio_address' : [
+                        ['render'],
+                        function(e) {
+                            return function() {
+                                if (e.value == 'physical') { e.selectedIndex = 1; $('address_deck').selectedIndex = 1; }
+                            };
+                        }
+                    ],
+                    'group_tab' : [
+                        ['command'],
+                        function() {
+                            try {
+                                if (! obj.group_frame_loaded) {
+                                    obj.group_frame();
+                                    obj.group_frame_loaded = true;
                                 }
-                                                               for (var i = 0; i < penalties.length; i++) {
-
-                                                                       var row = document.createElement('row');
-                                                                       var label = document.createElement('label');
-
-                                                                       //x.setAttribute('value',penalties[i].penalty_type());
-                                                                       label.setAttribute('value',penalties[i].standing_penalty().label());
-                                                                       row.appendChild(label);
-
-                                                               var button = document.createElement('button');
-                                                               button.setAttribute('label', patronStrings.getString('staff.patron.summary.standing_penalty.remove'));
-                                    button.setAttribute('image','/xul/server/skin/media/images/icon_delete.gif');
-                                                               button.setAttribute('disabled','true');
-                                                               button.setAttribute('hidden','true');
-                                    button.setAttribute('retrieve_ausp_id',penalties[i].id());
-                                                               row.appendChild(button);
-
-                                    // XXX check a permission here? How to fire the remove action ??? XXX
-                                    if (penalties[i].standing_penalty().id() > 100) {
-                                                                   button.setAttribute('disabled','false');
-                                                                   button.setAttribute('hidden','false');
-                                        button.addEventListener(
-                                            'command',
-                                            function(ev) {
-                                                try {
-                                                    JSAN.use('util.functional');
-                                                    var id = ev.target.getAttribute('retrieve_ausp_id');
-                                                    var penalty = util.functional.find_list( obj.patron.standing_penalties(), function(o) { return o.id() == id; } );
-                                                    penalty.isdeleted(1);
-
-                                                    var req = obj.network.simple_request( 'FM_AUSP_REMOVE', [ ses(), penalty ] );
-                                                    if (typeof req.ilsevent != 'undefined' || String(req) != '1') {
-                                                        obj.error.standard_unexpected_error_alert(
-                                                            patronStrings.getFormattedString(
-                                                                'staff.patron.standing_penalty.remove_error',
-                                                                [obj.data.hash.csp[id].name()]
-                                                            ),
-                                                            req
-                                                        );
-                                                    }
-                                                    if (typeof xulG.refresh == 'function') { xulG.refresh(); }
-                                                } catch(F) {
-                                                    obj.error.standard_unexpected_error_alert(
-                                                        patronStrings.getFormattedString(
-                                                            'staff.patron.standing_penalty.remove_error',
-                                                            [ev.target.getAttribute('retrieve_ausp_id')]
-                                                        ),
-                                                        F
-                                                    );
-                                                }
-                                            },
-                                            false
-                                        );
+                            } catch(E) {
+                                alert('Error in summary.js, group_tab: ' + E);
+                            }
+                        }
+                    ],
+                    'stat_cat_tab' : [
+                        ['command'],
+                        function() {
+                            try {
+                                var rows = $('patron_info_rows');
+                                obj.stat_cat_list.clear();
+                                var entries = obj.patron.stat_cat_entries();
+                                for (var i = 0; i < entries.length; i++) {
+                                    var stat_cat = obj.OpenILS.data.hash.my_actsc[ entries[i].stat_cat() ];
+                                    if (!stat_cat) {
+                                        stat_cat = obj.OpenILS.data.lookup('actsc',entries[i].stat_cat());
                                     }
-
-                                    if (penalties[i].standing_penalty().block_list()) {
-                                        if (penalties[i].standing_penalty().block_list().match(/RENEW/)) addCSSClass(label,'PENALTY_RENEW');
-                                        if (penalties[i].standing_penalty().block_list().match(/HOLD/)) addCSSClass(label,'PENALTY_HOLD');
-                                        if (penalties[i].standing_penalty().block_list().match(/CIRC/)) addCSSClass(label,'PENALTY_CIRC');
+                                    if (!stat_cat) { continue; }
+                                    // Every stat cat gets rendered in the Stat Cats tab
+                                    obj.stat_cat_list.append( {
+                                        'row' : {
+                                            'my' : {
+                                                'actsc' : stat_cat,
+                                                'actscecm' : entries[i],
+                                            }
+                                        }
+                                    } );
+                                    // But only a proud few share the Patron Info pane
+                                    if (rows && get_bool( stat_cat.usr_summary() )) {
+                                        var row_id = 'stat_cat_id_' + stat_cat.id();
+                                        var row; var label1; var label2;
+                                        if ($(row_id)) {
+                                            row = $(row_id);
+                                            label1 = row.firstChild;
+                                            label2 = row.lastChild;
+                                        } else {
+                                            row = document.createElement('row');
+                                            row.setAttribute('id',row_id);
+                                            label1 = document.createElement('label');
+                                            label2 = document.createElement('label');
+                                            row.appendChild(label1);
+                                            row.appendChild(label2);
+                                            rows.appendChild(row);
+                                        }
+                                        label1.setAttribute('value',stat_cat.name());
+                                        label1.setAttribute('tooltiptext','stat cat id ' + stat_cat.id());
+                                        label2.setAttribute('value',entries[i].stat_cat_entry());
                                     }
-
-                                                                       e.appendChild(row);
-                                                               }
-                                                       };
-                                               }
-                                       ],
-                                       'patron_credit' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               JSAN.use('util.money');
-                                                               e.setAttribute('value',
-                                                                       '$' + 
-                                                                       util.money.sanitize(
-                                                                               obj.patron.credit_forward_balance()
-                                                                       )
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_bill' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value','...');
+                                }
+                            } catch(E) {
+                                alert('Error in summary.js, stat_cat_tab: ' + E);
+                            }
+                        }
+                    ],
+                    'spawn_group_interface' : [
+                        ['command'],
+                        function() {
+                            try {
+                                window.xulG.spawn_group_interface();
+                            } catch(E) {
+                                alert('Error in summary.js, spawn_group_interface: ' + E);
+                            }
+                        }
+                    ],
+                    'group_tab_retrieve_patron' : [
+                        ['command'],
+                        function() {
+                            var selected_ids = util.functional.map_list(
+                                obj.group_list.retrieve_selection(),
+                                function(o) {
+                                    return o.getAttribute('retrieve_id');
+                                }
+                            );
+                            for (var i = 0; i < selected_ids.length; i++) {
+                                try {
+                                    window.xulG.new_patron_tab(
+                                        { 'tab_name' : patronStrings.getString('staff.patron.info_group.retrieve_patron.tab_name') },
+                                        {
+                                            'id' : selected_ids[i],
+                                            'url_prefix' : xulG.url_prefix,
+                                            'new_tab' : xulG.new_tab,
+                                            'set_tab' : xulG.set_tab
+                                        }
+                                    );
+                                } catch(E) {
+                                    alert('Error in summary.js, group_tab_retrieve_patron: ' + E);
+                                }
+                            }
+                        }
+                    ],
+                    'patron_alert' : [
+                        ['render'],
+                        function(e) {
+                            return function() {
+                                util.widgets.set_text( e, obj.patron.alert_message() || '' );
+                                if (obj.patron.alert_message()) {
+                                    e.parentNode.hidden = false;
+                                } else {
+                                    e.parentNode.hidden = true;
+                                }
+                            };
+                        }
+                    ],
+                    'patron_usrname' : [
+                        ['render'],
+                        function(e) {
+                            return function() {
+                                util.widgets.set_text(e,obj.patron.usrname());
+                            };
+                        }
+                    ],
+                    'patron_profile' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    obj.OpenILS.data.hash.pgt[
+                                        obj.patron.profile()
+                                    ].name()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_net_access' : [
+                        ['render'],
+                        function(e) {
+                            // not applicable to Conifer
+                        }
+                    ],
+                    'patron_credit' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                JSAN.use('util.money');
+                                util.widgets.set_text(e,
+                                    '$' + 
+                                    util.money.sanitize(
+                                        obj.patron.credit_forward_balance()
+                                    )
+                                );
+                            };
+                        }
+                    ],
+                    'patron_bill' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,'...');
                                 var under_btn; 
                                 if (xulG) {
                                     if (xulG.display_window) {
                                         under_btn = xulG.display_window.document.getElementById('under_bills');
-                                        if (under_btn) under_btn.setAttribute('value','...');
+                                        if (under_btn) util.widgets.set_text(under_btn,'...');
                                     }
                                 }
-                                                               obj.network.simple_request(
-                                                                       'FM_MOUS_RETRIEVE.authoritative',
-                                                                       [ ses(), obj.patron.id() ],
-                                                                       function(req) {
-                                                                               JSAN.use('util.money');
-                                                                               var robj = req.getResultObject();
-                                                                               e.setAttribute('value', patronStrings.getFormattedString('staff.patron.summary.patron_bill.money', [util.money.sanitize( robj.balance_owed() )]));
-                                                                               if (under_btn) under_btn.setAttribute('value', 
-                                            patronStrings.getFormattedString('staff.patron.summary.patron_bill.money', [util.money.sanitize( robj.balance_owed() )]));
-                                                                       }
-                                                               );
-                                                               /*
-                                                               obj.network.simple_request(
-                                                                       'FM_MBTS_IDS_RETRIEVE_ALL_HAVING_BALANCE.authoritative',
-                                                                       [ ses(), obj.patron.id() ],
-                                                                       function(req) {
-                                                                               JSAN.use('util.money');
-                                                                               var list = req.getResultObject();
-                                                                               if (typeof list.ilsevent != 'undefined') {
-                                                                                       e.setAttribute('value', '??? See Bills');
-                                                                                       return;
-                                                                               }
-                                                                               var sum = 0;
-                                                                               for (var i = 0; i < list.length; i++) {
-                                                                                       var robj = typeof list[i] == 'object' ? list[i] : obj.network.simple_request('FM_MBTS_RETRIEVE.authoritative',[ses(),list[i]]);
-                                                                                       sum += util.money.dollars_float_to_cents_integer( robj.balance_owed() );
-                                                                               } 
-                                                                               if (sum > 0) addCSSClass(document.documentElement,'PATRON_HAS_BILLS');
-                                                                               JSAN.use('util.money');
-                                                                               e.setAttribute('value', '$' + util.money.sanitize( util.money.cents_as_dollars( sum ) ));
-                                                                       }
-                                                               );
-                                                               */
-                                                       };
-                                               }
-                                       ],
-                                       'patron_checkouts' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value','...');
-                                                               var e2 = document.getElementById( 'patron_overdue' ); if (e2) e2.setAttribute('value','...');
-                                                               var e3 = document.getElementById( 'patron_claimed_returned' ); if (e3) e3.setAttribute('value','...');
-                                                               var e4 = document.getElementById( 'patron_long_overdue' ); if (e4) e4.setAttribute('value','...');
-                                                               var e5 = document.getElementById( 'patron_lost' ); if (e5) e5.setAttribute('value','...');
-                                                               var e6 = document.getElementById( 'patron_noncat' ); if (e6) e6.setAttribute('value','...');
+                                obj.network.simple_request(
+                                    'BLOB_BALANCE_OWED_VIA_USERGROUP',
+                                    [ ses(), obj.patron.usrgroup() ],
+                                    function(req) {
+                                        try {
+                                            JSAN.use('util.money');
+                                            var robj = req.getResultObject();
+                                            if (typeof robj.ilsevent != 'undefined') { throw(robj); }
+
+                                            var sum = 0; /* in cents */
+                                            obj.group_owed = {};
+
+                                            function render_main_patron_bill_summary(bs) {
+                                                try {
+                                                    util.widgets.set_text(
+                                                        e, 
+                                                        patronStrings.getFormattedString('staff.patron.summary.patron_bill.money', [util.money.sanitize( bs.balance_owed )])
+                                                    );
+                                                    if (under_btn) {
+                                                        util.widgets.set_text(
+                                                            under_btn, 
+                                                            patronStrings.getFormattedString('staff.patron.summary.patron_bill.money', [util.money.sanitize( bs.balance_owed )])
+                                                        );
+                                                    }
+                                                    var show_billing_tab_on_bills = String( obj.OpenILS.data.hash.aous['ui.circ.show_billing_tab_on_bills'] ) == 'true';
+                                                    if (show_billing_tab_on_bills && Number(bs.balance_owed) > 0) {
+                                                        if (xulG) {
+                                                            if (xulG.display_window) {
+                                                                if (! obj.show_billing_tab_on_bills_done_once ) {
+                                                                    xulG.display_window.g.patron.skip_hide_summary = true;
+                                                                    xulG.display_window.util.widgets.dispatch('command','cmd_patron_bills');
+                                                                    obj.show_billing_tab_on_bills_done_once = 1;
+                                                                }
+                                                            }
+                                                        }
+                                                    };
+                                                    obj.bills_summary = bs;
+                                                    if (obj.holds_summary && obj.bills_summary)  {
+                                                        if (typeof window.xulG == 'object' && typeof window.xulG.stop_sign_page == 'function') {
+                                                            window.xulG.stop_sign_page( obj.patron, { 'holds_summary' : obj.holds_summary, 'bills_summary' : obj.bills_summary } ); 
+                                                        }
+                                                    }
+                                                } catch(E) {
+                                                    alert('Error in summary.js, render_main_patron_bill_summary(): ' + E);
+                                                }
+                                            }
+
+                                            var rendered_main_patron_bill_summary = false;
+                                            for (var i = 0; i < robj.length; i++) {
+                                                if (robj[i].usr == obj.patron.id()) {
+                                                    render_main_patron_bill_summary( robj[i] );
+                                                    rendered_main_patron_bill_summary = true;
+                                                } else {
+                                                    sum += util.money.dollars_float_to_cents_integer( robj[i].balance_owed );
+                                                    obj.group_owed[ robj[i].usr ] = robj[i].balance_owed;
+                                                }
+                                            }
+                                            if (!rendered_main_patron_bill_summary) {
+                                                render_main_patron_bill_summary( { balance_owed: 0.00, usr: obj.patron.id() } );
+                                            }
+                                            var tab = $('group_tab');
+                                            if (tab) {
+                                                if (sum > 0) {
+                                                    addCSSClass(tab,'balance_owed');
+                                                } else {
+                                                    removeCSSClass(tab,'balance_owed');
+                                                }
+                                                tab.setAttribute(
+                                                    'label',
+                                                    patronStrings.getFormattedString('staff.patron.summary.tab.group_list_with_total_owed.label',[ util.money.cents_as_dollars( sum ) ])
+                                                );
+                                            }
+                                        } catch(E) {
+                                            alert('Error in summary.js, patron_bill callback: ' + E);
+                                        }
+                                    }
+                                );
+                            };
+                        }
+                    ],
+                    'patron_checkouts' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,'...');
+                                var e2 = document.getElementById( 'patron_overdue' ); if (e2) util.widgets.set_text(e2,'...');
+                                var e3 = document.getElementById( 'patron_claimed_returned' ); if (e3) util.widgets.set_text(e3,'...');
+                                var e4 = document.getElementById( 'patron_long_overdue' ); if (e4) util.widgets.set_text(e4,'...');
+                                var e5 = document.getElementById( 'patron_lost' ); if (e5) util.widgets.set_text(e5,'...');
+                                var e6 = document.getElementById( 'patron_noncat' ); if (e6) util.widgets.set_text(e6,'...');
                                 var under_btn; 
                                 if (xulG) {
                                     if (xulG.display_window) {
                                         under_btn = xulG.display_window.document.getElementById('under_items');
-                                        if (under_btn) under_btn.setAttribute('value','...');
+                                        if (under_btn) util.widgets.set_text(under_btn,'...');
                                     }
                                 }
-                                                               obj.network.simple_request(
-                                                                       'FM_CIRC_COUNT_RETRIEVE_VIA_USER.authoritative',
-                                                                       [ ses(), obj.patron.id() ],
-                                                                       function(req) {
-                                                                               try {
-                                                                                       var robj = req.getResultObject();
-                                                                                       e.setAttribute('value', robj.out + robj.overdue + robj.claims_returned + robj.long_overdue );
-                                                                                       if (e2) e2.setAttribute('value', robj.overdue   );
-                                                                                       if (e3) e3.setAttribute('value', robj.claims_returned   );
-                                                                                       if (e4) e4.setAttribute('value', robj.long_overdue      );
-                                                                                       if (e5) e5.setAttribute('value', robj.lost      );
-                                            if (under_btn) under_btn.setAttribute('value', 
-                                                String( robj.out + robj.overdue + robj.claims_returned + robj.long_overdue) + 
-                                                ( robj.overdue > 0 || robj.claims_returned > 0 || robj.long_overdue > 0 ? '*' : '' )
+                                obj.network.simple_request(
+                                    'FM_CIRC_COUNT_RETRIEVE_VIA_USER.authoritative',
+                                    [ ses(), obj.patron.id() ],
+                                    function(req) {
+                                        try {
+                                            var robj = req.getResultObject();
+                                            var do_not_tally_claims_returned = String( obj.OpenILS.data.hash.aous['circ.do_not_tally_claims_returned'] ) == 'true';
+                                            util.widgets.set_text(e,
+                                                robj.out
+                                                + robj.overdue
+                                                + (do_not_tally_claims_returned ? 0 : robj.claims_returned)
+                                                + robj.long_overdue
+                                            );
+                                            if (e2) util.widgets.set_text(e2, robj.overdue    );
+                                            if (e3) util.widgets.set_text(e3, robj.claims_returned    );
+                                            if (e4) util.widgets.set_text(e4, robj.long_overdue    );
+                                            if (e5) util.widgets.set_text(e5, robj.lost    );
+                                            if (under_btn) util.widgets.set_text(under_btn, 
+                                                String(
+                                                    robj.out
+                                                    + robj.overdue
+                                                    + (do_not_tally_claims_returned ? 0 : robj.claims_returned)
+                                                    + robj.long_overdue
+                                                ) 
+                                                /* + ( robj.overdue > 0 ? '*' : '' ) */
                                             );
-                                                                               } catch(E) {
-                                                                                       alert(E);
-                                                                               }
-                                                                       }
-                                                               );
-                                                               obj.network.simple_request(
-                                                                       'FM_ANCC_RETRIEVE_VIA_USER.authoritative',
-                                                                       [ ses(), obj.patron.id() ],
-                                                                       function(req) {
-                                                                               var robj = req.getResultObject();
-                                                                               if (e6) e6.setAttribute('value',robj.length);
-                                                                       }
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_overdue' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               /* handled by 'patron_checkouts' */
-                                                       };
-                                               }
-                                       ],
-                                       'patron_holds' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value','...');
-                                                               var e2 = document.getElementById('patron_holds_available');
-                                                               if (e2) e2.setAttribute('value','...');
+                                        } catch(E) {
+                                            alert(E);
+                                        }
+                                    }
+                                );
+                                obj.network.simple_request(
+                                    'FM_ANCC_RETRIEVE_VIA_USER.authoritative',
+                                    [ ses(), obj.patron.id() ],
+                                    function(req) {
+                                        var robj = req.getResultObject();
+                                        if (e6) util.widgets.set_text(e6,robj.length);
+                                    }
+                                );
+                            };
+                        }
+                    ],
+                    'patron_overdue' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                /* handled by 'patron_checkouts' */
+                            };
+                        }
+                    ],
+                    'patron_holds' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,'...');
+                                var e2 = document.getElementById('patron_holds_available');
+                                if (e2) util.widgets.set_text(e2,'...');
                                 var under_btn; 
                                 if (xulG) {
                                     if (xulG.display_window) {
                                         under_btn = xulG.display_window.document.getElementById('under_holds');
-                                        if (under_btn) under_btn.setAttribute('value','...');
+                                        if (under_btn) util.widgets.set_text(under_btn,'...');
+                                    }
+                                }
+                                obj.network.simple_request(
+                                    'FM_AHR_COUNT_RETRIEVE.authoritative',
+                                    [ ses(), obj.patron.id() ],
+                                    function(req) {
+                                        var robj = req.getResultObject();
+                                        util.widgets.set_text(e,
+                                            robj.total
+                                        );
+                                        if (e2) util.widgets.set_text(e2,
+                                            robj.ready
+                                        );
+                                        if (under_btn) util.widgets.set_text(under_btn, req.getResultObject().ready + '/' + req.getResultObject().total );
+                                        obj.holds_summary = robj;
+                                        if (obj.holds_summary && obj.bills_summary) 
+                                            if (typeof window.xulG == 'object' && typeof window.xulG.stop_sign_page == 'function')
+                                                window.xulG.stop_sign_page( obj.patron, { 'holds_summary' : obj.holds_summary, 'bills_summary' : obj.bills_summary } ); 
                                     }
+                                );
+                            };
+                        }
+                    ],
+                    'patron_holds_available' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                /* handled by 'patron_holds' */
+                            };
+                        }
+                    ],
+                    'patron_card' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    obj.patron.card().barcode()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_ident_type_1' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                var ident_string = '';
+                                var ident = obj.OpenILS.data.hash.cit[
+                                    obj.patron.ident_type()
+                                ];
+                                if (ident) ident_string = ident.name()
+                                util.widgets.set_text(e,
+                                    ident_string
+                                );
+                            };
+                        }
+                    ],
+                    'patron_ident_value_1' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                var val = obj.patron.ident_value();
+                                if (val) val = val.replace(/.+(\d\d\d\d)$/,'xxxx$1');   // must avoid val.replace if val is NULL
+                                util.widgets.set_text(e, val);
+                            };
+                        }
+                    ],
+                    'patron_ident_type_2' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                var ident_string = '';
+                                var ident = obj.OpenILS.data.hash.cit[
+                                    obj.patron.ident_type2()
+                                ];
+                                if (ident) ident_string = ident.name()
+                                util.widgets.set_text(e,
+                                    ident_string
+                                );
+                            };
+                        }
+                    ],
+                    'patron_ident_value_2' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                var val = obj.patron.ident_value2();
+                                if (val) val = val.replace(/.+(\d\d\d\d)$/,'xxxx$1');   // must avoid val.replace if val is NULL
+                                util.widgets.set_text(e, val);
+                            };
+                        }
+                    ],
+                    'patron_date_of_exp' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    patronStrings.getString('staff.patron.summary.expires_on') + ' ' + (
+                                        obj.patron.expire_date() ?
+                                        util.date.formatted_date( obj.patron.expire_date(), '%{localized_date}' ) :
+                                        patronStrings.getString('staff.patron.field.unset') 
+                                    )
+                                );
+                            };
+                        }
+                    ],
+                    'patron_hold_alias' : [
+                        ['render'],
+                        function(e) {
+                            return function() {
+                                util.widgets.set_text(e,
+                                    obj.patron.alias() ? obj.patron.alias() : ''
+                                );
+                            }
+                        }
+                    ],
+                    'patron_date_of_birth' : [
+                        ['render'],
+                        function(e) {
+                            // not applicable to Conifer
+                        }
+                    ],
+                    'patron_day_phone' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    obj.patron.day_phone()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_evening_phone' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    obj.patron.evening_phone()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_other_phone' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    obj.patron.other_phone()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_email' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    obj.patron.email()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_alias' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    obj.patron.alias()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_photo_url' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                e.setAttribute('src',
+                                    obj.patron.photo_url()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_library' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    obj.OpenILS.data.hash.aou[
+                                        obj.patron.home_ou()
+                                    ].shortname()
+                                );
+                                e.setAttribute('tooltiptext',
+                                    obj.OpenILS.data.hash.aou[
+                                        obj.patron.home_ou()
+                                    ].name()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_last_library' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                util.widgets.set_text(e,
+                                    obj.OpenILS.data.hash.aou[
+                                        obj.patron.home_ou()
+                                    ].shortname()
+                                );
+                                e.setAttribute('tooltiptext',
+                                    obj.OpenILS.data.hash.aou[
+                                        obj.patron.home_ou()
+                                    ].name()
+                                );
+                            };
+                        }
+                    ],
+                    'patron_mailing_address_street1' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().street1()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
+                            };
+                        }
+                    ],
+                    'patron_mailing_address_street2' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().street2()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
+                            };
+                        }
+                    ],
+                    'patron_mailing_address_city' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().city()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
+                            };
+                        }
+                    ],
+                    'patron_mailing_address_state' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().state()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
+                            };
+                        }
+                    ],
+                    'patron_mailing_address_post_code' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().post_code()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
+                            };
+                        }
+                    ],
+                    'patron_physical_address_street1' : [
+                        ['render'],
+                        function(e) {
+                            return function() { 
+                                if (obj.patron.billing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().street1()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
+                            };
+                        }
+                    ],
+                    'patron_physical_address_street2' : [
+                        ['render'],
+                        function(e) {
+                            return function() {
+                                if (obj.patron.billing_address()) { 
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().street2()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
+                            };
+                        }
+                    ],
+                    'patron_physical_address_city' : [
+                        ['render'],
+                        function(e) {
+                            return function() {
+                                if (obj.patron.billing_address()) { 
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().city()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
+                            };
+                        }
+                    ],
+                    'patron_physical_address_state' : [
+                        ['render'],
+                        function(e) {
+                            return function() {
+                                if (obj.patron.billing_address()) { 
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().state()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
+                            };
+                        }
+                    ],
+                    'patron_physical_address_post_code' : [
+                        ['render'],
+                        function(e) {
+                            return function() {
+                                if (obj.patron.billing_address()) { 
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().post_code()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
                                 }
-                                                               obj.network.simple_request(
-                                                                       'FM_AHR_COUNT_RETRIEVE.authoritative',
-                                                                       [ ses(), obj.patron.id() ],
-                                                                       function(req) {
-                                                                               e.setAttribute('value',
-                                                                                       req.getResultObject().total
-                                                                               );
-                                                                               if (e2) e2.setAttribute('value',
-                                                                                       req.getResultObject().ready
-                                                                               );
-                                        if (under_btn) under_btn.setAttribute( 'value', req.getResultObject().ready + '/' + req.getResultObject().total );
-                                                                       }
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_holds_available' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               /* handled by 'patron_holds' */
-                                                       };
-                                               }
-                                       ],
-                                       'patron_card' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.card().barcode()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_ident_type_1' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               var ident_string = '';
-                                                               var ident = obj.OpenILS.data.hash.cit[
-                                                                       obj.patron.ident_type()
-                                                               ];
-                                                               if (ident) ident_string = ident.name()
-                                                               e.setAttribute('value',
-                                                                       ident_string
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_ident_value_1' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               var val = obj.patron.ident_value();
-                                                               val = val.replace(/.+(\d\d\d\d)$/,'xxxx$1');
-                                                               e.setAttribute('value', val);
-                                                       };
-                                               }
-                                       ],
-                                       'patron_ident_type_2' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               var ident_string = '';
-                                                               var ident = obj.OpenILS.data.hash.cit[
-                                                                       obj.patron.ident_type2()
-                                                               ];
-                                                               if (ident) ident_string = ident.name()
-                                                               e.setAttribute('value',
-                                                                       ident_string
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_ident_value_2' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               var val = obj.patron.ident_value2();
-                                                               val = val.replace(/.+(\d\d\d\d)$/,'xxxx$1');
-                                                               e.setAttribute('value', val);
-                                                       };
-                                               }
-                                       ],
-                                       'patron_date_of_exp' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       patronStrings.getString('staff.patron.summary.expires_on') + ' ' + (
-                                                                               obj.patron.expire_date() ?
-                                                                               obj.patron.expire_date().substr(0,10) :
-                                                                           patronStrings.getString('staff.patron.field.unset') 
-                                                                       )
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_date_of_birth' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               // not applicable to Conifer
-                                                       };
-                                               }
-                                       ],
-                                       'patron_day_phone' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.day_phone()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_evening_phone' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.evening_phone()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_other_phone' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.other_phone()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_email' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.email()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_alias' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.alias()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_photo_url' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('src',
-                                                                       obj.patron.photo_url()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_library' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.OpenILS.data.hash.aou[
-                                                                               obj.patron.home_ou()
-                                                                       ].shortname()
-                                                               );
-                                                               e.setAttribute('tooltiptext',
-                                                                       obj.OpenILS.data.hash.aou[
-                                                                               obj.patron.home_ou()
-                                                                       ].name()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_last_library' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.OpenILS.data.hash.aou[
-                                                                               obj.patron.home_ou()
-                                                                       ].shortname()
-                                                               );
-                                                               e.setAttribute('tooltiptext',
-                                                                       obj.OpenILS.data.hash.aou[
-                                                                               obj.patron.home_ou()
-                                                                       ].name()
-                                                               );
-                                                       };
-                                               }
-                                       ],
-                                       'patron_mailing_address_street1' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.mailing_address().street1()
-                                                               );
-                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ],
-                                       'patron_mailing_address_street2' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.mailing_address().street2()
-                                                               );
-                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ],
-                                       'patron_mailing_address_city' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.mailing_address().city()
-                                                               );
-                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ],
-                                       'patron_mailing_address_state' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.mailing_address().state()
-                                                               );
-                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ],
-                                       'patron_mailing_address_post_code' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.mailing_address().post_code()
-                                                               );
-                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ],
-                                       'patron_physical_address_street1' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.billing_address().street1()
-                                                               );
-                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ],
-                                       'patron_physical_address_street2' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.billing_address().street2()
-                                                               );
-                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ],
-                                       'patron_physical_address_city' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.billing_address().city()
-                                                               );
-                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ],
-                                       'patron_physical_address_state' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.billing_address().state()
-                                                               );
-                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ],
-                                       'patron_physical_address_post_code' : [
-                                               ['render'],
-                                               function(e) {
-                                                       return function() { 
-                                                               e.setAttribute('value',
-                                                                       obj.patron.billing_address().post_code()
-                                                               );
-                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
-                                                       };
-                                               }
-                                       ]
-                               }
-                       }
-               );
-
-               obj.retrieve();
-
-               try {
-                       var caption = document.getElementById("PatronSummaryContact_caption");
-                       var arrow = document.getAnonymousNodes(caption)[0];
-                       var gb_content = document.getAnonymousNodes(caption.parentNode)[1];
-                       arrow.addEventListener(
-                               'click',
-                               function() {
-                                       setTimeout(
-                                               function() {
-                                                       //alert('setting shrink_state to ' + gb_content.hidden);
-                                                       //caption.setAttribute('shrink_state',gb_content.hidden);
-                                                       netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-                                                       JSAN.use('util.file'); var file = new util.file('patron_id_shrink');
-                                                       file.set_object(String(gb_content.hidden)); file.close();
-                                               }, 0
-                                       );
-                               }, false
-                       );
-                       //var shrink_state = caption.getAttribute('shrink_state');
-                       var shrink_state = false;
-                       netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-                       JSAN.use('util.file'); var file = new util.file('patron_id_shrink');
-                       if (file._file.exists()) {
-                               shrink_state = file.get_object(); file.close();
-                       }
-                       //alert('shrink_state retrieved as ' + shrink_state);
-                       if (shrink_state != 'false' && shrink_state) {
-                               JSAN.use('util.widgets');
-                               //alert('clicking the widget');
-                               util.widgets.click( arrow );
-                       }
-               } catch(E) {
-                       obj.error.sdump('D_ERROR','with shrink_state in summary.js: ' + E);
-               }
-       },
-
-       'retrieve' : function() {
-
-               try {
-
-                       var obj = this;
-
-                       var chain = [];
-
-                       // Retrieve the patron
-                               function blah_retrieve() {
-                                       try {
-                                               var robj;
-                                               if (obj.barcode && obj.barcode != 'null') {
-                                                       robj = obj.network.simple_request(
-                                                               'FM_AU_RETRIEVE_VIA_BARCODE.authoritative',
-                                                               [ ses(), obj.barcode ]
-                                                       );
-                                               } else if (obj.id && obj.id != 'null') {
-                                                       robj = obj.network.simple_request(
-                                                               'FM_AU_FLESHED_RETRIEVE_VIA_ID.authoritative',
-                                                               [ ses(), obj.id ]
-                                                       );
-                                               } else {
-                                                       throw(patronStrings.getString('staff.patron.summary.retrieve.no_barcode'));
-                                               }
-                                               if (robj) {
-
-                                                       if (instanceOf(robj,au)) {
-
-                                                               obj.patron = robj;
-                                                               JSAN.use('patron.util');
-                                                               document.getElementById('patron_name').setAttribute('value',
-                                                                       ( obj.patron.prefix() ? obj.patron.prefix() + ' ' : '') + 
-                                                                       obj.patron.family_name() + ', ' + 
-                                                                       obj.patron.first_given_name() + ' ' +
-                                                                       ( obj.patron.second_given_name() ? obj.patron.second_given_name() + ' ' : '' ) +
-                                                                       ( obj.patron.suffix() ? obj.patron.suffix() : '')
-                                                               );
-                                                               patron.util.set_penalty_css(obj.patron);
-                                                               JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
-                                                               data.last_patron = obj.patron.id(); data.stash('last_patron');
-
-                                                       } else {
-
-                                                               throw(robj);
-
-                                                       }
-                                               } else {
-
-                                                       throw(robj);
-
-                                               }
-
-                                       } catch(E) {
-                                               throw(E);
-                                       }
-                               };
-                               blah_retrieve();
-
-                       /*
-                       // Retrieve the survey responses for required surveys
-                       chain.push(
-                               function() {
-                                       try {
-                                               var surveys = obj.OpenILS.data.list.my_asv;
-                                               var survey_responses = {};
-                                               for (var i = 0; i < surveys.length; i++) {
-                                                       var s = obj.network.request(
-                                                               api.FM_ASVR_RETRIEVE.app,
-                                                               api.FM_ASVR_RETRIEVE.method,
-                                                               [ ses(), surveys[i].id(), obj.patron.id() ]
-                                                       );
-                                                       survey_responses[ surveys[i].id() ] = s;
-                                               }
-                                               obj.patron.survey_responses( survey_responses );
-                                       } catch(E) {
-                                               var error = ('patron.summary.retrieve : ' + js2JSON(E));
-                                               obj.error.sdump('D_ERROR',error);
-                                               throw(error);
-                                       }
-                               }
-                       );
-                       */
-
-                       // Update the screen
-                       chain.push( function() { obj.controller.render(); } );
-
-                       // On Complete
-
-                       chain.push( function() {
-
-                               if (typeof window.xulG == 'object' && typeof window.xulG.on_finished == 'function') {
-                                       obj.error.sdump('D_PATRON_SUMMARY',
-                                               'patron.summary: Calling external .on_finished()\n');
-                                       window.xulG.on_finished(obj.patron);
-                               } else {
-                                       obj.error.sdump('D_PATRON_SUMMARY','patron.summary: No external .on_finished()\n');
-                               }
-
-                       } );
-
-                       // Do it
-                       JSAN.use('util.exec'); obj.exec = new util.exec();
-                       obj.exec.on_error = function(E) {
-
-                               if (typeof window.xulG == 'object' && typeof window.xulG.on_error == 'function') {
-                                       window.xulG.on_error(E);
-                               } else {
-                                       alert(js2JSON(E));
-                               }
-
-                       }
-                       this.exec.chain( chain );
-
-               } catch(E) {
-                       if (typeof window.xulG == 'object' && typeof window.xulG.on_error == 'function') {
-                               window.xulG.on_error(E);
-                       } else {
-                               alert(js2JSON(E));
-                       }
-               }
-       }
+                            };
+                        }
+                    ]
+                }
+            }
+        );
+
+        obj.retrieve();
+
+        try {
+            var caption = document.getElementById("PatronSummaryContact_caption");
+            var arrow = document.getAnonymousNodes(caption)[0];
+            var gb_content = document.getAnonymousNodes(caption.parentNode)[1];
+            arrow.addEventListener(
+                'click',
+                function() {
+                    setTimeout(
+                        function() {
+                            //alert('setting shrink_state to ' + gb_content.hidden);
+                            //caption.setAttribute('shrink_state',gb_content.hidden);
+                            netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+                            JSAN.use('util.file'); var file = new util.file('patron_id_shrink');
+                            file.set_object(String(gb_content.hidden)); file.close();
+                        }, 0
+                    );
+                }, false
+            );
+            //var shrink_state = caption.getAttribute('shrink_state');
+            var shrink_state = false;
+            netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+            JSAN.use('util.file'); var file = new util.file('patron_id_shrink');
+            if (file._file.exists()) {
+                shrink_state = file.get_object(); file.close();
+            }
+            //alert('shrink_state retrieved as ' + shrink_state);
+            if (shrink_state != 'false' && shrink_state) {
+                //alert('clicking the widget');
+                util.widgets.click( arrow );
+            }
+        } catch(E) {
+            obj.error.sdump('D_ERROR','with shrink_state in summary.js: ' + E);
+        }
+    },
+
+    'retrieve' : function() {
+
+        try {
+
+            var obj = this;
+
+            var chain = [];
+
+            // Retrieve the patron
+                function blah_retrieve() {
+                    try {
+                        var robj;
+                        if (obj.barcode && obj.barcode != 'null') {
+                            robj = obj.network.simple_request(
+                                'FM_AU_RETRIEVE_VIA_BARCODE.authoritative',
+                                [ ses(), obj.barcode ]
+                            );
+                        } else if (obj.id && obj.id != 'null') {
+                            robj = obj.network.simple_request(
+                                'FM_AU_FLESHED_RETRIEVE_VIA_ID',
+                                [ ses(), obj.id ]
+                            );
+                        } else {
+                            throw(patronStrings.getString('staff.patron.summary.retrieve.no_barcode'));
+                        }
+                        if (robj) {
+
+                            if (instanceOf(robj,au)) {
+
+                                obj.patron = robj;
+                                JSAN.use('patron.util');
+                                util.widgets.set_text('patron_name',
+                                    patron.util.format_name( obj.patron )
+                                );
+                                patron.util.set_penalty_css(obj.patron);
+                                JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+                                data.last_patron = obj.patron.id(); data.stash('last_patron');
+
+                            } else {
+
+                                throw(robj);
+
+                            }
+                        } else {
+
+                            throw(robj);
+
+                        }
+
+                    } catch(E) {
+                        throw(E);
+                    }
+                };
+                blah_retrieve();
+
+            /*
+            // Retrieve the survey responses for required surveys
+            chain.push(
+                function() {
+                    try {
+                        var surveys = obj.OpenILS.data.list.my_asv;
+                        var survey_responses = {};
+                        for (var i = 0; i < surveys.length; i++) {
+                            var s = obj.network.request(
+                                api.FM_ASVR_RETRIEVE.app,
+                                api.FM_ASVR_RETRIEVE.method,
+                                [ ses(), surveys[i].id(), obj.patron.id() ]
+                            );
+                            survey_responses[ surveys[i].id() ] = s;
+                        }
+                        obj.patron.survey_responses( survey_responses );
+                    } catch(E) {
+                        var error = ('patron.summary.retrieve : ' + js2JSON(E));
+                        obj.error.sdump('D_ERROR',error);
+                        throw(error);
+                    }
+                }
+            );
+            */
+
+            // Update the screen
+            chain.push( function() {
+                obj.controller.render();
+                if ($('stat_cat_tab')) {
+                    util.widgets.dispatch('command','stat_cat_tab'); 
+                }
+            } );
+
+            // On Complete
+
+            chain.push( function() {
+
+                if (typeof window.xulG == 'object' && typeof window.xulG.on_finished == 'function') {
+                    obj.error.sdump('D_PATRON_SUMMARY',
+                        'patron.summary: Calling external .on_finished()\n');
+                    window.xulG.on_finished(obj.patron);
+                } else {
+                    obj.error.sdump('D_PATRON_SUMMARY','patron.summary: No external .on_finished()\n');
+                }
+
+            } );
+
+            // Do it
+            JSAN.use('util.exec'); obj.exec = new util.exec();
+            obj.exec.on_error = function(E) {
+
+                if (typeof window.xulG == 'object' && typeof window.xulG.on_error == 'function') {
+                    window.xulG.on_error(E);
+                } else {
+                    alert(js2JSON(E));
+                }
+
+            }
+            this.exec.chain( chain );
+
+        } catch(E) {
+            if (typeof window.xulG == 'object' && typeof window.xulG.on_error == 'function') {
+                window.xulG.on_error(E);
+            } else {
+                alert(js2JSON(E));
+            }
+        }
+    },
+
+    'group_frame' : function() {
+        var obj = this;
+        try {
+            obj.group_list.clear();
+
+            var robj = obj.network.simple_request(
+                'FM_AU_LIST_RETRIEVE_VIA_GROUP.authoritative',
+                [ ses(), obj.patron.usrgroup() ]
+            );
+            if ((robj == null) || (typeof robj.ilsevent != 'undefined') ) throw(robj);
+            var ids = util.functional.filter_list( robj, function(o) { return o != obj.patron.id(); });
+            var funcs = [];
+
+                function gen_func(r) {
+                    return function() {
+                        obj.group_list.append( { 'retrieve_id' : r, 'row' : {} } );
+                    }
+                }
+
+            //funcs.push( gen_func(obj.patron.id()) );
+            for (var i = 0; i < ids.length; i++) {
+                funcs.push( gen_func(ids[i]) );
+            }
+            JSAN.use('util.exec'); var exec = new util.exec(4);
+            exec.chain( funcs );
+        } catch(E) {
+            alert('Error in summary.js, group_frame(): ' + E);
+        }
+    }
 }
 
 dump('exiting patron.summary.js\n');
index 0d77dff..db89293 100644 (file)
 <?xml version="1.0"?>
 <!DOCTYPE overlay PUBLIC "" ""[
-       <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
 ]>
 <overlay id="patron_summary_overlay" 
-       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
 <script>dump('loading patron/summary_overlay.xul\n');</script>
 
 <commandset id="patron_summary_cmds" />
 
 <box id="patron_summary_main" flex="1" orient="vertical" class="my_overflow">
-       <vbox id="patron_info_sidebar" />
+    <vbox id="patron_info_sidebar" />
 </box>
 
 <vbox id="patron_info_sidebar" flex="1">
-       <label id="patron_name" hidden="true" class="patronNameLarge"/>
-       <groupbox id="PatronSummaryAlert_groupbox" flex="0" hidden="true" class="alert">
-               <caption id="psagbc" label="&staff.patron.summary_overlay.psagbc.alert.label;" class="shrinkable_groupbox"/>
-               <description id="patron_alert"/>
-       </groupbox>
-       <groupbox id="PatronSummaryStanding_groupbox" flex="0" class="standing">
-               <caption id="pssgbc" label="&staff.patron.summary_overlay.pssgbc.standing.label;" class="shrinkable_groupbox"/>
-        <vbox id="pssgbvb">
-            <grid><columns><column/><column/></columns>
-                <rows id="patron_standing_penalties"/>
-            </grid>
-        </vbox>
-        <spacer/>
-       </groupbox>
-       <groupbox id="PatronSummaryStatus_groupbox" flex="0" class="status"/>
-       <!--
-       <groupbox id="PatronSummarySurvey_groupbox" flex="0">
-               <caption id="pdsgbc" label="Surveys" class="shrinkable_groupbox"/>
-               <vbox id="patron_surveys" />
-       </groupbox>
-       -->
-       <groupbox id="PatronSummaryContact_groupbox" flex="0" class="contact"/>
+    <description id="patron_name" hidden="true" class="copyable patronNameLarge"/>
+    <groupbox id="PatronSummaryAlert_groupbox" flex="0" hidden="true" class="alert">
+        <caption id="psagbc" label="&staff.patron.summary_overlay.psagbc.alert.label;" class="shrinkable_groupbox"/>
+        <description id="patron_alert"/>
+    </groupbox>
+    <groupbox id="PatronSummaryStatus_groupbox" flex="0" class="status"/>
+    <!--
+    <groupbox id="PatronSummarySurvey_groupbox" flex="0">
+        <caption id="pdsgbc" label="Surveys" class="shrinkable_groupbox"/>
+        <vbox id="patron_surveys" />
+    </groupbox>
+    -->
+    <groupbox id="PatronSummaryContact_groupbox" flex="0" class="contact"/>
 </vbox>
 
 <groupbox id="PatronSummaryStatus_groupbox" orient="vertical">
-       <caption label="&staff.patron_display.status.caption;" class="shrinkable_groupbox" />
-       <grid style="border: solid thin"><columns><column/></columns><rows>
-               <row hidden="true">
-                       <label id="patron_standing" />
-               </row>
-               <row id="pdsgr1">
-                       <label id="patron_profile" class="profile value"/>
-               </row>
-               <row id="pdsgr5">
-                       <label id="patron_library" class="homelib value"/>
-               </row>
-               <row id="pdsgr5aa">
-                       <label id="patron_date_of_exp" class="expire_date value"/>
-               </row>
-       </rows></grid>
-       <grid id="PatronSummaryStatus_grid" flex="1"/>
+    <caption label="&staff.patron_display.status.caption;" class="shrinkable_groupbox" />
+    <grid style="border: solid thin"><columns><column/></columns><rows>
+        <row hidden="true">
+            <description id="patron_standing" />
+        </row>
+        <row id="pdsgr1">
+            <description id="patron_profile" class="copyable profile value"/>
+        </row>
+        <row id="pdsgr5">
+            <description id="patron_library" class="copyable homelib value"/>
+        </row>
+        <row id="pdsgr5aa">
+            <description id="patron_date_of_exp" class="copyable expire_date value"/>
+        </row>
+    </rows></grid>
+    <grid id="PatronSummaryStatus_grid" flex="1"/>
 
 </groupbox>
 
 <grid id="PatronSummaryStatus_grid">
-       <columns id="pdsgc">
-               <column id="pdsgc1" />
-               <column id="pdsgc2" />
-               <column id="pdsgc3" />
-               <column id="pdsgc4" />
-       </columns>
-       <rows id="pdsgr" flex="1">
-               <row id="pdsgr4">
-                       <label id="PatronSummaryStatus_holds_label" class="text_left holds label"
-                               value="&staff.patron_display.holds.label;" />
-                       <label id="patron_holds" class="holds value"/>
-               </row><row>
-                       <label id="PatronSummaryStatus_holds_available_label" class="text_right holds_ready label"
-                               value="&staff.patron_display.holds_available.label;"  style="background: grey"/>
-                       <label id="patron_holds_available" class="holds_ready label" style="background: grey"/>
-               </row>
-               <row id="pdsgr2" class="hide_patron_credit" hidden="true">
-                       <label id="PatronSummaryStatus_credit_label" class="text_left credit label"
-                               value="&staff.patron_display.credit.label;" />
-                       <label id="patron_credit" class="credit value"/>
-               </row><row>
-                       <label id="PatronSummaryStatus_bills_label" class="text_left bill label"
-                               value="&staff.patron_display.bills.label;" />
-                       <label id="patron_bill" class="bill value"/>
-               </row>
-               <row id="pdsgr3">
-                       <label id="PatronSummaryStatus_checkouts_label" class="text_left items_out label"
-                               value="&staff.patron_display.checkouts.label;" />
-                       <label id="patron_checkouts" class="items_out value"/>
-               </row>
-               <row>
-                       <label id="PatronSummaryStatus_checkouts_overdue_label" class="text_right items_overdue label"
-                               value="&staff.patron_display.checkouts_overdue.label;" style="background: grey"/>
-                       <label id="patron_overdue" class="items_overdue value" style="background: grey"/>
-               </row>
-               <row id="pdsgr5">
-                       <label id="PatronSummaryStatus_long_overdue_label" value="&staff.patron.summary_overlay.overdue.value;" class="text_right items_long_overdue label" style="background: grey"/>
-                       <label id="patron_long_overdue" class="items_long_overdue value" style="background: grey"/>
-               </row>
-               <row id="pdsgr7">
-                       <label id="PatronSummaryStatus_claimed_returned_label" value="&staff.patron.summary_overlay.claimed_returned.value;" class="text_right items_long_overdue label" style="background: grey"/>
-                       <label id="patron_claimed_returned" class="items_claimed_returned value" style="background: grey"/>
-               </row>
-               <row id="pdsgr6">
-                       <label id="PatronSummaryStatus_lost_label" value="&staff.patron.summary_overlay.lost_label.value;" class="text_left items_lost label"/>
-                       <label id="patron_lost" class="items_lost value"/>
-               </row>
-               <row id="pdsgr6a">
-                       <label id="PatronSummaryStatus_noncat_label" value="&staff.patron.summary_overlay.noncat_label.value;" class="text_left items_noncat label"/>
-                       <label id="patron_noncat" class="items_noncat value"/>
-               </row>
-       </rows>
+    <columns id="pdsgc">
+        <column id="pdsgc1" />
+        <column id="pdsgc2" />
+        <column id="pdsgc3" />
+        <column id="pdsgc4" />
+    </columns>
+    <rows id="pdsgr" flex="1">
+        <row id="pdsgr4">
+            <label id="PatronSummaryStatus_holds_label" class="copyable text_left holds label"
+                value="&staff.patron_display.holds.label;" />
+            <description id="patron_holds" class="copyable holds value"/>
+        </row><row>
+            <label id="PatronSummaryStatus_holds_available_label" class="copyable text_right holds_ready label subgroup"
+                value="&staff.patron_display.holds_available.label;"  />
+            <description id="patron_holds_available" class="copyable holds_ready value subgroup" />
+        </row>
+        <row id="pdsgr2" class="hide_patron_credit" hidden="true">
+            <label id="PatronSummaryStatus_credit_label" class="copyable text_left credit label"
+                value="&staff.patron_display.credit.label;" />
+            <description id="patron_credit" class="copyable credit value"/>
+        </row><row>
+            <label id="PatronSummaryStatus_bills_label" class="copyable text_left bill label"
+                value="&staff.patron_display.bills.label;" />
+            <description id="patron_bill" class="copyable bill value"/>
+        </row>
+        <row id="pdsgr3">
+            <label id="PatronSummaryStatus_checkouts_label" class="copyable text_left items_out label"
+                value="&staff.patron_display.checkouts.label;" />
+            <description id="patron_checkouts" class="copyable items_out value"/>
+        </row>
+        <row>
+            <label id="PatronSummaryStatus_checkouts_overdue_label" class="copyable text_right items_overdue label subgroup"
+                value="&staff.patron_display.checkouts_overdue.label;" />
+            <description id="patron_overdue" class="copyable items_overdue value subgroup" />
+        </row>
+        <row id="pdsgr5">
+            <label id="PatronSummaryStatus_long_overdue_label" value="&staff.patron.summary_overlay.overdue.value;" class="copyable text_right items_long_overdue label subgroup" />
+            <description id="patron_long_overdue" class="copyable items_long_overdue value subgroup" />
+        </row>
+        <row id="pdsgr7">
+            <label id="PatronSummaryStatus_claimed_returned_label" value="&staff.patron.summary_overlay.claimed_returned.value;" class="copyable text_right items_long_overdue label subgroup" />
+            <description id="patron_claimed_returned" class="copyable items_claimed_returned value subgroup" />
+        </row>
+        <row id="pdsgr6">
+            <label id="PatronSummaryStatus_lost_label" value="&staff.patron.summary_overlay.lost_label.value;" class="copyable text_left items_lost label"/>
+            <description id="patron_lost" class="copyable items_lost value"/>
+        </row>
+        <row id="pdsgr6a">
+            <label id="PatronSummaryStatus_noncat_label" value="&staff.patron.summary_overlay.noncat_label.value;" class="copyable text_left items_noncat label"/>
+            <description id="patron_noncat" class="copyable items_noncat value"/>
+        </row>
+    </rows>
 </grid>
 
 <groupbox id="PatronSummaryContact_groupbox" orient="vertical">
-       <!--
-       <caption label="&staff.patron_display.contact.caption;"/>
-       -->
-       <caption id="PatronSummaryContact_caption" label="&staff.patron.summary_overlay.summary_contact.label;" class="shrinkable_groupbox" />
-       <hbox id="pdcgbhb1">
-               <grid id="PatronSummaryContact_grid" />
-               <spacer id="pdcgbhbs1" flex="1"/>
-               <image id="patron_photo_url" />
-       </hbox>
-       <grid id="PatronSummaryContact_grid_phone" />
-       <groupbox id="PatronSummaryContact_mailing_address" class="mailing_address"/>
-       <groupbox id="PatronSummaryContact_physical_address" class="physical_address"/>
+    <!--
+    <caption label="&staff.patron_display.contact.caption;"/>
+    -->
+    <caption id="PatronSummaryContact_caption" label="&staff.patron.summary_overlay.summary_contact.label;" class="shrinkable_groupbox" />
+    <hbox id="pdcgbhb1">
+        <grid id="PatronSummaryContact_grid" />
+        <spacer id="pdcgbhbs1" flex="1"/>
+        <image id="patron_photo_url" />
+    </hbox>
+    <grid id="PatronSummaryContact_grid_phone" />
+    <groupbox id="PatronSummaryContact_mailing_address" class="mailing_address"/>
+    <groupbox id="PatronSummaryContact_physical_address" class="physical_address"/>
 </groupbox>
 
 <grid id="PatronSummaryContact_grid">
-       <columns id="pdsgc">
-               <column id="pdsgc1" />
-               <column id="pdsgc2" />
-       </columns>
-       <rows id="pdsgr" flex="1">
-               <row id="pdsgr0">
-                       <label id="PatronSummaryContact_library_card_label" class="text_left card label"
-                               value="&staff.patron_display.library_card.label;"/>
-                       <label id="patron_card" class="card value click_link" onclick="try { copy_to_clipboard(event); } catch(E) { alert(E); }"/>
-               </row>
-               <row id="pdsgr1">
-                       <label id="PatronSummaryContact_ident_label" class="text_left"
-                               value="&staff.patron_display.ident1.label;"/>
-                       <vbox id="pdsgr0h">
-                               <label id="patron_ident_type_1" class="ident ident_type ident1 value"/>
-                               <label id="patron_ident_value_1" class="ident ident_value ident1 value"/>
-                       </vbox>
-               </row>
-               <row id="pdsgr2">
-                       <label id="PatronSummaryContact_ident_label2" class="text_left"
-                               value="&staff.patron_display.ident2.label;"/>
-                       <vbox id="pdsgr0ah">
-                               <label id="patron_ident_type_2" class="ident ident_type ident2 value"/>
-                               <label id="patron_ident_value_2" class="ident ident_value ident2 value"/>
-                       </vbox>
-               </row>
-               <row id="pdsgr4"><label id="pdsgr4l" value=" "/></row>
-       </rows>
+    <columns id="pdsgc">
+        <column id="pdsgc1" />
+        <column id="pdsgc2" />
+    </columns>
+    <rows id="pdsgr" flex="1">
+        <row id="pdsgr0">
+            <label id="PatronSummaryContact_library_card_label" class="copyable text_left card label"
+                value="&staff.patron_display.library_card.label;"/>
+            <description id="patron_card" class="copyable card value click_link" onclick="try { copy_to_clipboard(event); } catch(E) { alert(E); }"/>
+        </row>
+        <row id="pdsgr1">
+            <label id="PatronSummaryContact_ident_label" class="copyable text_left"
+                value="&staff.patron_display.ident1.label;"/>
+            <vbox id="pdsgr0h">
+                <description id="patron_ident_type_1" class="copyable ident ident_type ident1 value"/>
+                <description id="patron_ident_value_1" class="copyable ident ident_value ident1 value"/>
+            </vbox>
+        </row>
+        <row id="pdsgr2">
+            <label id="PatronSummaryContact_ident_label2" class="copyable text_left"
+                value="&staff.patron_display.ident2.label;"/>
+            <vbox id="pdsgr0ah">
+                <description id="patron_ident_type_2" class="copyable ident ident_type ident2 value"/>
+                <description id="patron_ident_value_2" class="copyable ident ident_value ident2 value"/>
+            </vbox>
+        </row>
+        <row>
+            <label id="PatronSummaryContact_hold_alias_label" class="copyable text_left" value="&staff.patron_display.hold_alias.label;"/>
+            <description id="patron_hold_alias" class="copyable hold_alias value" />
+        </row>
+        <row id="pdsgr4"><label id="pdsgr4l" value=" "/></row>
+    </rows>
 </grid>
 
 <grid id="PatronSummaryContact_grid_phone">
-       <columns id="pdcgpc">
-               <column id="pdcgpc1" />
-               <column id="pdcgpc2" />
-       </columns>
-       <rows id="pdcgpr" flex="1">
-               <row id="pdcgpr1">
-                       <label id="PatronSummaryContact_day_phone_label" class="text_left phone label day_phone"
-                               value="&staff.patron_display.day_phone.label;" />
-                       <label id="patron_day_phone" class="phone value day_phone"/> 
-               </row>
-               <row id="pdcgpr2">
-                       <label id="PatronSummaryContact_evening_phone_label" class="text_left phone label evening_phone"
-                               value="&staff.patron_display.evening_phone.label;" />
-                       <label id="patron_evening_phone" class="phone value evening_phone"/>
-               </row>
-               <row id="pdcgpr3">
-                       <label id="PatronSummaryContact_other_phone_label" class="text_left phone label other_phone"
-                               value="&staff.patron_display.other_phone.label;" />
-                       <label id="patron_other_phone" class="phone value other_phone"/> 
-               </row>
-               <row id="pdsgpr4"><label id="pdsgpr4l" value=" "/></row>
-               <row id="pdsgpr4a">
-                       <label id="PatronSummaryContact_usrname_label" class="text_left usrname label"
-                               value="&staff.patron.summary_overlay.opac_login.value;" />
-                       <label id="patron_usrname" class="usrname value"/>
-               </row>
-               <row id="pdcgpr5">
-                       <label id="PatronSummaryContact_email_label" class="text_left email label"
-                               value="&staff.patron_display.email.label;" />
-                       <label id="patron_email" class="email value" style="text-decoration: underline; color: blue; -moz-user-focus: normal;" onclick="copy_to_clipboard(event)"/>
-               </row>
-               <row id="pdsgpr6"><label id="pdsgpr6l" value=" "/></row>
+    <columns id="pdcgpc">
+        <column id="pdcgpc1" />
+        <column id="pdcgpc2" />
+    </columns>
+    <rows id="pdcgpr" flex="1">
+        <row id="pdcgpr1">
+            <label id="PatronSummaryContact_day_phone_label" class="copyable text_left phone label day_phone"
+                value="&staff.patron_display.day_phone.label;" />
+            <description id="patron_day_phone" class="copyable phone value day_phone"/> 
+        </row>
+        <row id="pdcgpr2">
+            <label id="PatronSummaryContact_evening_phone_label" class="copyable text_left phone label evening_phone"
+                value="&staff.patron_display.evening_phone.label;" />
+            <description id="patron_evening_phone" class="copyable phone value evening_phone"/>
+        </row>
+        <row id="pdcgpr3">
+            <label id="PatronSummaryContact_other_phone_label" class="copyable text_left phone label other_phone"
+                value="&staff.patron_display.other_phone.label;" />
+            <description id="patron_other_phone" class="copyable phone value other_phone"/> 
+        </row>
+        <row id="pdsgpr4"><label id="pdsgpr4l" value=" "/></row>
+        <row id="pdsgpr4a">
+            <label id="PatronSummaryContact_usrname_label" class="copyable text_left usrname label"
+                value="&staff.patron.summary_overlay.opac_login.value;" />
+            <description id="patron_usrname" class="copyable usrname value"/>
+        </row>
+        <row id="pdcgpr5">
+            <label id="PatronSummaryContact_email_label" class="copyable text_left email label"
+                value="&staff.patron_display.email.label;" />
+            <description id="patron_email" class="copyable email value" style="text-decoration: underline; color: blue; -moz-user-focus: normal;" onclick="copy_to_clipboard(event)"/>
+        </row>
+        <row id="pdsgpr6"><label id="pdsgpr6l" value=" "/></row>
 
-       </rows>
+    </rows>
 </grid>
 
+<popupset id="patron_summary_popups">
+    <popup id="addr_export_popup" oncommand="export_address(event);">
+        <menuitem id="addr_export_copy" label="&staff.patron_display.address_export_popup.copy;"/>
+        <menuitem id="addr_export_print" label="&staff.patron_display.address_export_popup.print;"/>
+    </popup>
+</popupset>
+
 <groupbox id="PatronSummaryContact_mailing_address" orient="vertical">
-       <caption id="pdcmac" label="&staff.patron_display.mailing_address;" class="shrinkable_groupbox"/>
-       <label id="patron_mailing_address_street1" tooltiptext="&staff.patron_display.mailing.street1.label;" class="address street street1 mailing"/>
-       <label id="patron_mailing_address_street2" tooltiptext="&staff.patron_display.mailing.street2.label;" class="address street street2 mailing"/>
-       <hbox id="pdcmah">
-               <label id="patron_mailing_address_city" tooltiptext="&staff.patron_display.mailing.city.label;" class="address city mailing"/>
-               <label id="patron_mailing_address_state" tooltiptext="&staff.patron_display.mailing.state.label;" class="address state mailing"/>
-               <label id="patron_mailing_address_post_code" tooltiptext="&staff.patron_display.mailing.post_code.label;" class="address post_code mailing"/>
-       </hbox>
+    <caption id="pdcmac" label="&staff.patron_display.mailing_address;" class="shrinkable_groupbox"/>
+    <description id="patron_mailing_address_street1" tooltiptext="&staff.patron_display.mailing.street1.label;" class="copyable address street street1 mailing value"/>
+    <description id="patron_mailing_address_street2" tooltiptext="&staff.patron_display.mailing.street2.label;" class="copyable address street street2 mailing value"/>
+    <hbox id="pdcmah">
+        <description id="patron_mailing_address_city" tooltiptext="&staff.patron_display.mailing.city.label;" class="copyable address city mailing value"/>
+        <description id="patron_mailing_address_state" tooltiptext="&staff.patron_display.mailing.state.label;" class="copyable address state mailing value"/>
+        <description id="patron_mailing_address_post_code" tooltiptext="&staff.patron_display.mailing.post_code.label;" class="copyable address post_code mailing value"/>
+    </hbox>
+    <hbox>
+        <spacer flex="1" />
+        <label id="addr_export_mailing" value="&staff.patron_display.address_export;" popup="addr_export_popup" class="copyable click_link"/>
+    </hbox>
 </groupbox>
 
 <groupbox id="PatronSummaryContact_physical_address" orient="vertical">
-       <caption id="pdcpac" label="&staff.patron_display.physical_address;" class="shrinkable_groupbox"/>
-       <label id="patron_physical_address_street1" tooltiptext="&staff.patron_display.physical.street1.label;" class="address street street1 physical" />
-       <label id="patron_physical_address_street2" tooltiptext="&staff.patron_display.physical.street2.label;"  class="address street street2 physical"/>
-       <hbox id="pdcpah">
-               <label id="patron_physical_address_city" tooltiptext="&staff.patron_display.physical.city.label;" class="address city physical"/>
-               <label id="patron_physical_address_state" tooltiptext="&staff.patron_display.physical.state.label;" class="address state physical"/>
-               <label id="patron_physical_address_post_code" tooltiptext="&staff.patron_display.physical.post_code.label;" class="address post_code physical"/>
-       </hbox>
+    <caption id="pdcpac" label="&staff.patron_display.physical_address;" class="shrinkable_groupbox"/>
+    <description id="patron_physical_address_street1" tooltiptext="&staff.patron_display.physical.street1.label;" class="copyable address street street1 physical value" />
+    <description id="patron_physical_address_street2" tooltiptext="&staff.patron_display.physical.street2.label;"  class="copyable address street street2 physical value"/>
+    <hbox id="pdcpah">
+        <description id="patron_physical_address_city" tooltiptext="&staff.patron_display.physical.city.label;" class="copyable address city physical value"/>
+        <description id="patron_physical_address_state" tooltiptext="&staff.patron_display.physical.state.label;" class="copyable address state physical value"/>
+        <description id="patron_physical_address_post_code" tooltiptext="&staff.patron_display.physical.post_code.label;" class="copyable address post_code physical value"/>
+    </hbox>
+    <hbox>
+        <spacer flex="1" />
+        <label id="addr_export_physical" value="&staff.patron_display.address_export;" popup="addr_export_popup" class="copyable click_link"/>
+    </hbox>
 </groupbox>
 
 </overlay>
diff --git a/xul/server/patron/ue.xhtml b/xul/server/patron/ue.xhtml
deleted file mode 100644 (file)
index 9cd540b..0000000
+++ /dev/null
@@ -1,923 +0,0 @@
-<?xml version='1.0' encoding="UTF-8"?>
-
-<!DOCTYPE html PUBLIC 
-       "-//W3C//DTD XHTML 1.0 Transitional//EN" 
-       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
-       <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
-       <!ENTITY nbsp " "> <!-- calendar needs this entity -->
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude">
-
-       <head>
-               <title>&ev.staff.patron.ue_xhtml.ev_user_editor.label;</title>
-               <script language='javascript' src='/opac/common/js/utils.js'> </script>
-               <script language='javascript' src='/opac/common/js//config.js'> </script> 
-               <script language='javascript' src='/opac/common/js/CGI.js'> </script>
-       
-               <script language='javascript' src='/opac/common/js/JSON_v1.js'> </script>
-               <script language='javascript' src='/opac/common/js/fmall.js'> </script>
-               <script language='javascript' src='/opac/common/js/fmgen.js'> </script>
-               <script language='javascript' src='/opac/common/js/Cookies.js'> </script>
-               <script language='javascript' src='/opac/common/js/opac_utils.js'> </script>
-               <script language='javascript' src='/opac/common/js/<!--#echo var="locale"-->/OrgTree.js'> </script>
-               <script language='javascript' src='/opac/common/js/org_utils.js'> </script>
-               <script language='javascript' src='/opac/common/js/init.js'> </script>
-               <script language='javascript' src='/opac/common/js/RemoteRequest.js'> </script>
-
-
-
-               <!--
-               <script language='javascript' src='/opac/common/js/date.js'> </script>
-               -->
-               <script language='javascript' src='../admin/adminlib.js'> </script>
-               <script language='javascript' src='ue_config.js'> </script>
-               <script language='javascript' src='ue_ui.js'> </script>
-               <script language='javascript' src='ue.js'> </script>
-               <link type='text/css' rel='stylesheet' href='../admin/admin.css'/>
-  
-               <link rel="stylesheet" type="text/css" media="all" 
-                       href="/opac/common/js/jscalendar/calendar-brown.css" title="win2k-cold-1" />
-               <script type="text/javascript" src="/opac/common/js/jscalendar/calendar.js"></script>
-               <script type="text/javascript" src="/opac/common/js/jscalendar/lang/calendar-en.js"></script>
-               <script type="text/javascript" src="/opac/common/js/jscalendar/calendar-setup.js"></script>
-
-
-               <style type='text/css'>
-                       .messagecatalog { -moz-binding: url( /xul/server/main/bindings.xml#messagecatalog ) }
-                       .main_table { width: 98%; border-collapse: collapse;}
-                       .main_table td { border: 1px solid #E0F0E0; text-align: center; padding: 4px;}
-                       #uedit_nav_bar { border: 2px solid #E0F0E0; padding: 6px;}
-                       .nav_link { padding-left: 90px; padding-right: 90px; }
-                       .main_nav_link { -moz-border-radius: 7px; height: 13%;}
-                       /*
-                       .main_div { height: 480px; padding-left: 15px; 
-                               text-align: center; vertical-align: middle; overflow: auto;}
-                               */
-
-                       .main_div { min-height: 450px; padding-left: 15px; 
-                               text-align: center; vertical-align: middle; }
-
-                       .nav_link_table { height: 480px;}
-                       .label_active { background: #E0F0E0; }
-                       .right { text-align: right; padding-right: 3px;}
-                       .left { text-align: left; padding-left: 3px;}
-                       .wide { width: 98%;}
-                       .pad { padding-left: 3px; padding-right: 3px; }
-                       .no_border td { border: none; }
-                       .uedit_table { width: 80% }
-                       .address_table { -moz-border-radius: 4px; border: 4px solid #E0E0F0; padding: 4px; }
-                       .shared_address { background : #E0F0F0; }
-                       .address_table td { border: none; width: auto; padding: 1px; }
-                       .addr_info_checked { -moz-border-radius: 6px; background: #F0E0E0; }
-                       .button_row { width: 95%; text-align: center; margin-top: 7px; border: 1px solid #E0E0E0; }
-                       /*.required_field { background: #F0E0E0; }*/
-                       .invalid_value { background: red; }
-
-                       /* all text inputs that don't have the .invalid_value 
-                               class applied and are currently focused */
-                       input:focus:not(.invalid_value) { background: #E0F0E0; color: darkblue;}
-
-                       .deleted { background: #FF6666; }
-
-                       .dup_link { padding-left: 5px; color: red; }
-
-
-               </style>
-       </head>
-       
-       <div class="messagecatalog" id="patronStrings" src="/xul/server/locale/<!--#echo var='locale'-->/patron.properties" />
-
-       <body onload='uEditInit();'>
-
-       <center>
-
-               <h2>&ev.staff.patron.ue_xhtml.ev_user_editor.label;</h2>
-
-               <div style='position:absolute; top: 5px; right: 5px;'>
-                       <span>&ev.staff.patron.ue_xhtml.welcome.label;</span><b><span id='uedit_user'/></b>
-               </div>
-
-               <hr/><br/>
-
-               <div id='main_div_container'>
-
-               <table style='margin-bottom: 5px; width:100%;'>
-                       <tbody>
-                               <tr>
-                                       <td align='left' width='80%'>
-                                               <b>
-                                                       <span>&staff.patron.ue.interface_note.label;</span>
-                                               </b>
-                                       </td>
-                                       <td align='right' width='20%'>
-                                               <a class='hide_me' id='ue_errors' href='javascript:void(0);' 
-                                                       style='color: red; font-size: 12pt; font-weight: bold' onclick='uEditAlertErrors();'>
-                                                       &ev.staff.patron.ue_xhtml.view_errors.label;
-                                               </a>
-                                       </td>
-                               </tr>
-                       </tbody>
-               </table>
-
-               <table class='main_table'>
-                       <tbody>
-                               <tr>
-                                       <td width='15%' valign='top'>
-                                               <!-- ************************************************************** -->
-                                               <!--  Top Navigation Links -->
-                                               <!-- ************************************************************** -->
-                                               <table height='100%' class='nav_link_table'>
-                                                       <tbody>
-                                                               <tr>
-                                                                       <td id='uedit_userid_label' class='main_nav_link'>
-                                                                               <a href='javascript:uEditShowPage("uedit_userid");'>&ev.staff.patron.ue_xhtml.user_id.label;</a>
-                                                                       </td>
-                                                               </tr>
-                                                               <tr>
-                                                                       <td id='uedit_contact_info_label' class='main_nav_link'>        
-                                                                               <a href='javascript:uEditShowPage("uedit_contact_info");'>&ev.staff.patron.ue_xhtml.contact_info.label;</a>
-                                                                       </td>
-                                                               </tr>
-                                                               <tr>
-                                                                       <td id='uedit_addresses_label' class='main_nav_link'>           
-                                                                               <a href='javascript:uEditShowPage("uedit_addresses");'>&ev.staff.patron.ue_xhtml.addresses.label;</a>
-                                                                       </td>
-                                                               </tr>
-                                                               <tr>
-                                                                       <td id='uedit_groups_label' class='main_nav_link'>                      
-                                                                               <a href='javascript:uEditShowPage("uedit_groups");'>&ev.staff.patron.ue_xhtml.groups_permissions.label;</a>
-                                                                       </td>
-                                                               </tr>
-                                                               <tr>
-                                                                       <td id='uedit_stat_cats_label' class='main_nav_link'>           
-                                                                               <a href='javascript:uEditShowPage("uedit_stat_cats");'>&ev.staff.patron.ue_xhtml.statistical_categories.label;</a>
-                                                                       </td>
-                                                               </tr>
-                                                               <tr>
-                                                                       <td id='uedit_surveys_label' class='main_nav_link'>                     
-                                                                               <a href='javascript:uEditShowPage("uedit_surveys");'>&ev.staff.patron.ue_xhtml.surveys.label;</a>
-                                                                       </td>
-                                                               </tr>
-                                                               <tr>
-                                                                       <td id='uedit_finalize_label' class='main_nav_link'>                    
-                                                                               <a href='javascript:uEditShowPage("uedit_finalize");'>&ev.staff.patron.ue_xhtml.finish.label;</a>
-                                                                       </td>
-                                                               </tr>
-                                                       </tbody>
-                                               </table>
-                                       </td>
-
-                                       <td width='85%' id='uedit_loading'>
-                                               <div class='main_div has_color' 
-                                                       style='padding: 50px; vertical-align: middle;'>
-                                                       <b>&ev.staff.patron.ue_xhtml.loading_data.label;</b>
-                                               </div>
-                                       </td>
-
-
-                                       <td width='85%' id='ue_maintd' class='hide_me'>
-
-                                               <div id='dup_div_container'>
-                                                       <div id='dup_div' name='dup_div'>
-                                                               <a name='link' class='dup_link hide_me'
-                                                                       href='javascript:void(0);' onclick='uEditShowSearch(this);'>
-                                                                       &ev.staff.patron.ue_xhtml.found_duplicate_patron.label; <b name='count'/>
-                                                                       <b name='data'/>
-                                                               </a>
-                                                       </div>
-                                               </div>
-
-
-                                               <!-- ************************************************************** -->
-                                               <!--  Identification Pane -->
-                                               <!-- ************************************************************** -->
-                                               <div id='uedit_userid' class='main_div'>
-                                                       <table class='uedit_table'>
-                                                               <tbody>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.barcode.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input type='text' id='ue_barcode' />
-                                                                                                       <!--
-                                                                                                       onblur=' 
-                                                                                                               var node = uEditFindFieldByWId("ue_username");
-                                                                                                               if(!node.widget.node.value) {
-                                                                                                                       node.widget.node.value = this.value;
-                                                                                                                       node.widget.node.onchange();
-                                                                                                               }'
-                                                                                                               /> -->
-                                                                                                               <button style='padding-left: 5px;' class='hide_me' id='ue_mark_card_lost'
-                                                                                                       onclick='uEditMarkCardLost();'>&ev.staff.patron.ue_xhtml.mark_lost.label;</button>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.username.label;</div></td>
-                                                                               <td><div class='wide left'><input type='text' id='ue_username'/></div></td>
-                                                                       </tr>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.password.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input type='password' id='ue_password1'/>
-                                                                                               <button class='hide_me' onclick='uEditResetPw();' id='ue_reset_pw'>&ev.staff.patron.ue_xhtml.reset.label;</button>
-                                                                                               <span style='padding-left: 10px;' class='hide_me' id='ue_password_gen'>
-                                                                                                       &ev.staff.patron.ue_xhtml.re_password.label;
-                                                                                                       <span style='text-decoration:underline;' id='ue_password_plain'/>
-                                                                                               </span>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.verify_password.label;</div></td>
-                                                                               <td><div class='wide left'><input type='password' id='ue_password2'/></div></td>
-                                                                       </tr>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.first_name.label;</div></td>
-                                                                               <td><div class='wide left'><input type='text' id='ue_firstname'/></div></td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.middle_name.label;</div></td>
-                                                                               <td><div class='wide left'><input type='text' id='ue_middlename'/></div></td>
-                                                                       </tr>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.last_name.label;</div></td>
-                                                                               <td><div class='wide left'><input type='text' id='ue_lastname'/></div></td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.alias.label;</div></td>
-                                                                               <td><div class='wide left'><input type='text' id='ue_alias'/></div></td>
-                                                                       </tr>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.primary_id_type.label;</div></td>
-                                                                               <td><div class='wide left'>
-                                                                                               <select id='ue_primary_ident_type'>
-                                                                                                       <option value=''>&ev.staff.patron.ue_xhtml.required.label;</option>
-                                                                                               </select>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.primary_id.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input type='text' id='ue_primary_ident'/>
-                                                                                               <span id='primary_ident_ssn_help' 
-                                                                                                       style='padding-left: 2px; font-size: 8pt;' class='hide_me'>
-                                                                                               </span>
-                                                                                               <span id='primary_ident_dl_help' 
-                                                                                                       style='padding-left: 2px; font-size: 8pt;' class='hide_me'>
-                                                                                               </span>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <!--
-                                                                       <tr>
-                                                                               <td><div class='wide right'>Secondary Identification Type</div></td>
-                                                                               <td><div class='wide left'>
-                                                                                               <select id='ue_secondary_ident_type'>
-                                                                                                       <option value=''>  None Selected  </option>
-                                                                                               </select>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       -->
-                                                                       <tr class='hide_me'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.parent_guardian.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input type='text' id='ue_secondary_ident'/>
-                                                                                               <input type='hidden' id='ue_dob' />
-                                                                                               <input type='hidden' id='ue_juvenile' />
-                                                                                               <input type='hidden' id='ue_suffix'/>
-                                                                                               <input type='hidden' id='ue_suffix_selector'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <!--
-                                                                       <tr class='hide_me' id='ue_guardian_row'>
-                                                                               <td><div class='wide right'><b>Parent / Guardian</b></div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <span id='ue_guardian_field'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       -->
-                                                               </tbody>
-                                                       </table>
-                                               </div>
-
-                                               <!-- ************************************************************** -->
-                                               <!-- Contact Info Pane -->
-                                               <!-- ************************************************************** -->
-                                               <div id='uedit_contact_info' class='main_div hide_me'>
-
-                                                       <table class='uedit_table'>
-                                                               <tbody>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.email_address.label;</div></td>
-                                                                               <td><div class='wide left'><input type='text' id='ue_email' size='32'/></div></td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.daytime_phone.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input class='pad' type='text' id='ue_day_phone' size='18'/>
-                                                                                               <span style='font-size: 9pt;'>&ev.staff.patron.ue_xhtml.phone_example;</span>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.evening_phone.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input class='pad' type='text' id='ue_night_phone' size='18'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.other_phone.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input class='pad' type='text' id='ue_other_phone' size='18'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.home_library.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <select style='width: 20em;' id='ue_org_selector'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                               </tbody>
-                                                       </table>
-                                               </div>
-       
-                                               <!-- ************************************************************** -->
-                                               <!-- Addresses Pane -->
-                                               <!-- ************************************************************** -->
-                                               <div id='uedit_addresses' class='main_div hide_me' >
-                                                       <table class='uedit_table' style='width: 98%; padding: 1px;'>
-                                                               <thead>
-                                                                       <tr>
-                                                                               <td>&ev.staff.patron.ue_xhtml.address.label;</td>
-                                                                               <td>&ev.staff.patron.ue_xhtml.in_city_limits.label;</td>
-                                                                               <td>&ev.staff.patron.ue_xhtml.valid.label;</td>
-                                                                               <td>&ev.staff.patron.ue_xhtml.mailing_address.label;</td>
-                                                                               <td>&ev.staff.patron.ue_xhtml.physical_address.label;</td>
-                                                                       </tr>
-                                                               </thead>
-                                                               <tbody id='ue_address_tbody'>
-                                                                       <tr id='ue_address_template'>
-                                                                               <td>
-                                                                                       <table class='address_table'>
-                                                                                               <tbody>
-                                                                                                       <tr name='shared_row' class='hide_me'>
-                                                                                                               <td colspan='6'>
-                                                                                                                       <div style='padding: 8px;'>
-                                                                                                                               <span style='color:red;'>*</span>
-                                                                                                                               &ev.staff.patron.ue_xhtml.address_owned_by.label;
-                                                                                                                               <span name='addr_owner_name'/>
-                                                                                                                               <span name='owner_link_div'>
-                                                                                                                                       (<a name='addr_owner' href='javascript:void(0);'>&ev.staff.patron.ue_xhtml.edit.label;</a>)
-                                                                                                                               </span>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                       </tr>
-                                                                                                       <tr>
-                                                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.label.label;</div></td>
-                                                                                                               <td colspan='3'>
-                                                                                                                       <div class='wide left'>
-                                                                                                                               <input type='text' name='ue_addr_label' id='ue_addr_label'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.zip.label;</div></td>
-                                                                                                               <td>
-                                                                                                                       <div class='wide left'>
-                                                                                                                               <input type='text' name='ue_addr_zip' size='10' maxlength='10'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                       </tr>
-                                                                                                       <tr>
-                                                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.street1.label;</div></td>
-                                                                                                               <td colspan='5'>
-                                                                                                                       <div class='wide left'>
-                                                                                                                               <input type='text' name='ue_addr_street1' size='42'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                       </tr>
-                                                                                                       <tr>
-                                                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.street2.label;</div></td>
-                                                                                                               <td colspan='5'>
-                                                                                                                       <div class='wide left'>
-                                                                                                                               <input type='text' name='ue_addr_street2' size='42'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                       </tr>
-                                                                                                       <tr>
-                                                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.city.label;</div></td>
-                                                                                                               <td colspan='3'>
-                                                                                                                       <div class='wide left'>
-                                                                                                                               <input type='text' name='ue_addr_city' size='17'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.conuty.label;</div></td>
-                                                                                                               <td>
-                                                                                                                       <div class='wide left'>
-                                                                                                                               <input type='text' name='ue_addr_county' size='17'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                       </tr>
-                                                                                                       <tr>
-                                                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.state.label;</div></td>
-                                                                                                               <td colspan='3'>
-                                                                                                                       <div class='wide left'>
-                                                                                                                               <input type='text' name='ue_addr_state' size='3' maxlength='3'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                               <!--
-                                                                                                               <td><div class='wide right'>Zip</div></td>
-                                                                                                               <td>
-                                                                                                                       <div class='wide left'>
-                                                                                                                               <input type='text' name='ue_addr_zip' size='6' maxlength='6'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                               -->
-                                                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.country.label;</div></td>
-                                                                                                               <td>
-                                                                                                                       <div class='wide left'>
-                                                                                                                               <input type='text' name='ue_addr_country' size='6'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                       </tr>
-                                                                                                       <tr>
-                                                                                                               <td colspan='6'>
-                                                                                                                       <div class='button_row'>
-                                                                                                                               <input type='submit' name='ue_addr_delete' 
-                                                                                                                                       value='&ev.staff.patron.ue_xhtml.ue_addr_delete.label;'/>
-                                                                                                                               <span style='padding-left: 10px;'> </span>
-                                                                                                                               <input type='submit' name='ue_addr_detach' 
-                                                                                                                                       value='&ev.staff.patron.ue_xhtml.ue_addr_detach.label;' class='hide_me'/>
-                                                                                                                               <input type='submit' name='ue_addr_approve' 
-                                                                                                                                       value='&ev.staff.patron.ue_xhtml.ue_addr_approve.label;' class='hide_me'/>
-                                                                                                                       </div>
-                                                                                                               </td>
-                                                                                                       </tr>
-                                                                                                       <tr class='hide_me' name='ue_addr_replaced_row'>
-                                                                                                               <td colspan='6'>
-                                                                                                                       <div class='button_row' name='ue_addr_replaced_div'>
-                                                            </div>
-                                                        </td>
-                                                    </tr>
-                                                                                               </tbody>
-                                                                                       </table>
-                                                                               </td>
-                                                                               <td><input type='checkbox' name='ue_addr_inc_yes' checked='checked'/></td>
-                                                                               <td><input type='checkbox' name='ue_addr_valid_yes' checked='checked'/></td>
-                                                                               <td>
-                                                                                       <div style='width: 100%; -moz-border-radius: 8px;'>
-                                                                                               <input type='radio' name='ue_addr_mailing_yes'
-                                                                                                       onchange='uEditAddrTypeClick(this, "mailing");'
-                                                                                                       onclick='uEditAddrTypeClick(this, "mailing");'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                               <td>
-                                                                                       <div style='width: 100%; -moz-border-radius: 8px;'>
-                                                                                               <input type='radio' name='ue_addr_billing_yes'
-                                                                                                       onchange='uEditAddrTypeClick(this, "billing");'
-                                                                                                       onclick='uEditAddrTypeClick(this, "billing");'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                               </tbody>
-                                                       </table>
-
-                                                       <div class='button_row' style='margin-top: 20px;'>
-                                                               <!--
-                                                               <input type='submit' value='Create a New Address' id='ue_address_new'/>
-                                                               -->
-                                                               <input type='submit' value='&staff.patron.ue.create_address.label;' onclick='uEditCreateNewAddr();'/>
-                                                       </div>
-                                               </div>
-       
-                                               <!-- ************************************************************** -->
-                                               <!-- Groups Pane -->
-                                               <!-- ************************************************************** -->
-                                               <div id='uedit_groups' class='main_div hide_me'>
-                                                       <table class='uedit_table'>
-                                                               <tbody>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.profile_group.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <select id='ue_profile' class='select_big'>
-                                                                                                       <option value=''>&ev.staff.patron.ue_xhtml.required.label;</option>
-                                                                                               </select>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr class='required_field'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.account_expiration_date.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input type='text' id='ue_expire' size='10' maxlength='10'/>
-       
-                                                                                               <button style='padding: 0px;' id='ue_expire_trigger'>
-                                                                                                       <img src="/opac/common/js/jscalendar/img.gif" 
-                                                                                                               style="cursor: pointer; border: 1px solid red; padding: 0px; margin: -3px;" 
-                                                                                                               title="&ev.staff.patron.ue_xhtml.date_selector.label;"
-                                                                                                               onmouseover="this.style.background='red';" 
-                                                                                                               onmouseout="this.style.background=''" />
-                                                                                               </button>
-
-                                                                                               <span class='pad' style='font-size: 8pt;'>(YYYY-MM-DD)</span>
-                                                                                               <script type="text/javascript">
-                                                                                                       Calendar.setup({
-                                                                                                               inputField      : "ue_expire",                          // id of the input field
-                                                                                                               ifFormat                : "%Y-%m-%d",                           // format of the input field
-                                                                                                               button          : "ue_expire_trigger",  // trigger for the calendar (button ID)
-                                                                                                               align                   : "Tl",                                         // alignment (defaults to "Bl")
-                                                                                                               singleClick     : true
-                                                                                                       });
-                                                                                               </script>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr class='hide_me'>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.net_access_level.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <select id='ue_net_level'>
-                                                                                               </select>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.active.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input id='ue_active' type='checkbox' checked='checked'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.barred.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input id='ue_barred' type='checkbox'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.set_family_group_lead_account.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input id='ue_group_lead' type='checkbox'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.claims_returned_count.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <input id='ue_claims_returned' type='text' disabled='disabled' size='6'/>
-                                                                                               <script>
-                                                                                                       $('ue_claims_returned').value = 0;
-                                                                                                       $('ue_claims_returned').disabled = true;
-                                                                                               </script>
-                                                                                               <input class='pad' id='ue_claims_returned_reset' type='submit' value='&ev.staff.patron.ue_xhtml.reset.label;' 
-                                                                                                       onclick="
-                                                                                                               if( confirmId('ue_claims_return_confirm') ) {
-                                                                                                                       $('ue_claims_returned').value = 0;
-                                                                                                                       $('ue_claims_returned').onchange();
-                                                                                                               }
-                                                                                                       "/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td><div class='wide right'>&ev.staff.patron.ue_xhtml.alert_message.label;</div></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <textarea wrap='soft' cols='30' rows='4' id='ue_alert_message'/>
-                                                                                               <input class='pad' id='ue_alert_message_reset' 
-                                                                                                       type='submit' value='&ev.staff.patron.ue_xhtml.alert_message_reset.value;' 
-                                                                                                               onclick='
-                                                                                                               var node = $("ue_alert_message");
-                                                                                                               node.value = "";
-                                                                                                               if(node.onchange) node.onchange();'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                               </tbody>
-                                                       </table>
-                                               </div>
-       
-                                               <!-- ************************************************************** -->
-                                               <!-- Stat Cats Pane -->
-                                               <!-- ************************************************************** -->
-                                               <div id='uedit_stat_cats' class='main_div hide_me'>
-                                                       <table class='uedit_table' style='width: 98%'>
-                                                               <thead>
-                                                                       <tr style='font-weight: bold;'>
-                                                                               <td>&ev.staff.patron.ue_xhtml.stat_cat_name.label;</td>
-                                                                               <td>&ev.staff.patron.ue_xhtml.owner.label;</td>
-                                                                               <td>&ev.staff.patron.ue_xhtml.value.label;</td>
-                                                                       </tr>
-                                                               </thead>
-                                                               <tbody id='ue_stat_cat_tbody'>
-                                                                       <tr id='ue_stat_cat_row'>
-                                                                               <td><div class='wide right' name='ue_stat_cat_name'/></td>
-                                                                               <td><div class='wide right' style='font-size: 8pt' name='ue_stat_cat_owner'/></td>
-                                                                               <td>
-                                                                                       <div class='wide left'>
-                                                                                               <select name='ue_stat_cat_selector'>
-                                                                                                       <option value=''>&ev.staff.patron.ue_xhtml.none_selected.label;</option>
-                                                                                               </select>
-                                                                                               <span class='pad'> or </span>
-                                                                                               <input class='pad' type='text' name='ue_stat_cat_newval'/>
-                                                                                       </div>
-                                                                               </td>
-                                                                       </tr>
-                                                               </tbody>
-                                                       </table>
-
-                                               </div>
-       
-                                               <!-- ************************************************************** -->
-                                               <!-- Surveys Pane -->
-                                               <!-- ************************************************************** -->
-                                               <div id='uedit_surveys' class='main_div hide_me'>
-                                                       <div id='uedit_no_surveys' class='hide_me'>
-                                                               <b>&ev.staff.patron.ue_xhtml.no_surveys_for_location.label;</b>
-                                                       </div>
-                                                       <table id='ue_survey_table' 
-                                                               class='uedit_table data_grid' style='width: 95%; margin-top: 17px;'>
-                                                               <thead>
-                                                                       <tr>
-                                                                               <td colspan='2' style='text-align: left; padding-left: 20px;'>
-                                                                                       <span class='pad' name='ue_survey_name' style='font-weight: bold;'/>
-                                                                                       <span class='pad' name='ue_survey_desc'> : </span>
-                                                                               </td>
-                                                                       </tr>
-                                                               </thead>
-                                                               <tbody name='ue_survey_tbody'>
-                                                                       <tr name='ue_survey_row'>
-                                                                               <td name='ue_survey_question' 
-                                                                                       style='width: 60%; text-align: left; padding-left: 40px;'/>
-                                                                               <td>
-                                                                                       <select name='ue_survey_answer'>
-                                                                                               <option value=''>&ev.staff.patron.ue_xhtml.none_selected.label;</option>
-                                                                                       </select>
-                                                                               </td>
-                                                                       </tr>
-                                                               </tbody>
-                                                       </table>
-                                               </div>
-
-                                               <!-- ************************************************************** -->
-                                               <!-- Finish Up -->
-                                               <!-- ************************************************************** -->
-                                               <div id='uedit_finalize' class='main_div hide_me'>
-                                                       <div class='has_color' style='width: 95%; margin-top: 40px; text-align: center'>
-                                                               <div style='padding: 5px;'>
-                                                                       &ev.staff.patron.ue_xhtml.finishing_message.label;
-                                                               </div>
-                                                               <br/>
-                                                               <div style='margin-bottom: 15px;'>
-                                                                       <a style='margin-right: 30px;' id='ue_view_summary' 
-                                                                               href='javascript:uEditShowSummary();'>View Summary</a>
-                                                               </div>
-                                                               <input style='margin-left: 5px; margin-right: 5px;' id='ue_save'
-                                                                       type='submit' value='&ev.staff.patron.ue_xhtml.save_user.value;' onclick='uEditSaveUser();'/>
-                                                               <input style='margin-left: 5px; margin-right: 5px;' id='ue_save_clone'
-                                                                       type='submit' value='&ev.staff.patron.ue_xhtml.save_clone_user.value;' onclick='uEditSaveUser(true);'/>
-                                                               <button style='margin-left: 5px; margin-right: 5px;' 
-                                                                       onclick='if(confirm($("ue_cancel_confirm").innerHTML)) uEditCancel();'>&ev.staff.patron.ue_xhtml.cancel.value;</button>
-                                                       </div>
-                                               </div>
-                                       </td>
-                               </tr>
-
-                               <tr>
-                                       <td colspan='2'>
-                                               <!-- ************************************************************** -->
-                                               <!-- Bottom Navigation Links -->
-                                               <!-- ************************************************************** -->
-                                               <table width='100%' class='no_border'>
-                                                       <tbody>
-                                                               <tr id='uedit_nav_bar'>
-                                                                       <td width='10%'/>
-                                                                       <td width='40%'>
-                                                                               <a id='ue_back' class='nav_link hide_me' 
-                                                                                       href='javascript:uEditPrev()'>&#x2190;&ev.staff.patron.ue_xhtml.back.label;</a>
-                                                                       </td>
-                                                                       <td width='40%'>
-                                                                               <a id='ue_fwd' class='nav_link' 
-                                                                                       href='javascript:uEditNext()'>&ev.staff.patron.ue_xhtml.forward.label;&#x2192;</a>
-                                                                       </td>
-                                                                       <td width='10%'/>
-                                                               </tr>
-                                                       </tbody>
-                                               </table>
-                                       </td>
-                               </tr>
-                       </tbody>
-               </table>
-       </div>
-
-       </center>
-
-       <div id='summary_div_container' class='hide_me'>
-
-       <div id='ue_summary_page'>
-               <table id='ue_summary_table' class='data_grid' width='55%'>
-                       <thead>
-                               <tr>
-                                       <td colspan='2'>
-                                               <span>&staff.patron.ue.user_summary.label;</span>
-                                       </td>
-                               </tr>
-                       </thead>
-                       <tbody name='ue_summary_page_tbody'>
-
-                               <tr>
-
-                                       <td colspan='2' align='center'>
-                                               <input style='margin-right: 15px;' type='submit' value='&ev.staff.patron.ue_xhtml.print_page.label;' onclick='window.print();'/>
-                                               <input style='margin-left: 15px;' type='submit' value='&ev.staff.patron.ue_xhtml.return_to_editor.label;' 
-                                                       onclick=' unHideMe($("main_div_container")); 
-                                                               hideMe($("summary_div_container"));'/>
-                                       </td>
-                               </tr>
-
-                               <tr><td>&ev.staff.patron.ue_xhtml.barcode.label;</td><td id='ue_summary_barcode'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.username.label;</td><td id='ue_summary_usrname'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.first_name.label;</td><td id='ue_summary_first_given_name'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.middle_name.label;</td><td id='ue_summary_second_given_name'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.last_name.label;</td><td id='ue_summary_family_name'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.alias.label;</td><td id='ue_summary_alias'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.suffix.label;</td><td id='ue_summary_suffix'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.dob.label;</td><td id='ue_summary_dob'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.primary_id_type.label;</td><td id='ue_summary_ident_type'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.primary_id.label;</td><td id='ue_summary_ident_value'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.secondary_id_type.label;</td><td id='ue_summary_ident_type2'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.secondary_id.label;</td><td id='ue_summary_ident_value2'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.email_address.label;</td><td id='ue_summary_email'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.daytime_phone.label;</td><td id='ue_summary_day_phone'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.evening_phone.label;</td><td id='ue_summary_evening_phone'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.other_phone.label;</td><td id='ue_summary_other_phone'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.home_library.label;</td><td id='ue_summary_home_ou'/></tr>
-
-                               <tr>
-                                       <td colspan='2'>
-                                               <table width='100%' style='margin-top: 15px; margin-bottom: 15px;'>
-                                                       <thead><tr><td>&ev.staff.patron.ue_xhtml.addresses.label;</td></tr></thead>
-                                                       <tbody name='ue_summary_addr_tbody'>
-                                                               <tr name='ue_summary_addr_row'>
-                                                                       <td>
-                                                                               <table name='ue_summary_addr_table' width='100%'>
-                                                                                       <thead><tr><td colspan='4'/><span> </span></tr></thead>
-                                                                                       <tbody>
-                                                                                               <tr>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.address_label.label;</b></td><td name='label'/>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.zip.label;</b></td><td name='zip'/>
-                                                                                               </tr>
-                                                                                               <tr>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.street1.label;</b></td><td name='street1'/>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.country.label;</b></td><td name='country'/>
-                                                                                               </tr>
-                                                                                               <tr>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.street2.label;</b></td><td name='street2'/>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.mailing.label;</b></td><td name='mailing'/>
-                                                                                               </tr>
-                                                                                               <tr>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.city.label;</b></td><td name='city'/>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.billing.label;</b></td><td name='billing'/>
-                                                                                               </tr>
-                                                                                               <tr>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.county.label;</b></td><td name='county'/>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.valid.label;</b></td><td name='valid'/>
-                                                                                               </tr>
-                                                                                               <tr>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.state.label;</b></td><td name='state'/>
-                                                                                                       <td><b>&ev.staff.patron.ue_xhtml.in_city_limits.label;</b></td><td name='incorporated'/>
-                                                                                               </tr>
-                                                                                       </tbody>
-                                                                               </table>
-                                                                       </td>
-                                                               </tr>
-                                                       </tbody>
-                                               </table>
-                                       </td>
-                               </tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.profile.label;</td><td id='ue_summary_profile'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.active.label;</td><td id='ue_summary_active'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.barred.label;</td><td id='ue_summary_barred'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.expire_date.label;</td><td id='ue_summary_expire_date'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.family_lead_account.label;</td><td id='ue_summary_master_account'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.claims_returned_count.label;</td><td id='ue_summary_claims_returned_count'/></tr>
-                               <tr><td>&ev.staff.patron.ue_xhtml.alert_message.label;</td><td id='ue_summary_alert_message'/></tr>
-                               <tr name='ue_summary_stat_cat_td'>
-                                       <td colspan='2' >
-                                               <table width='100%' style='margin-top: 15px; margin-bottom: 15px;'>
-                                                       <thead><tr><td colspan='2'>&ev.staff.patron.ue_xhtml.stat_categories.label;</td></tr></thead>
-                                                       <tbody name='ue_summary_stats_tbody'>
-                                                               <tr name='ue_summary_stats_row'>
-                                                                       <td name='ue_summary_stat_name'/><td name='ue_summary_stat_value'/>
-                                                               </tr>
-                                                       </tbody>
-                                               </table>
-                                       </td>
-                               </tr>
-                               <tr name='ue_summary_survey_td'>
-                                       <td colspan='2'>
-                                               <table width='100%' style='margin-top: 15px; margin-bottom: 15px;'>
-                                                       <thead>
-                                                               <tr>
-                                                                       <td>&ev.staff.patron.ue_xhtml.survey.label;</td>
-                                                                       <td>&ev.staff.patron.ue_xhtml.question.label;</td>
-                                                                       <td>&ev.staff.patron.ue_xhtml.answer.label;</td>
-                                                               </tr>
-                                                       </thead>
-                                                       <tbody name='ue_summary_survey_tbody'>
-                                                               <tr name='ue_summary_survey_row'>
-                                                                       <td name='ue_summary_survey_name'/>
-                                                                       <td name='ue_summary_survey_question'/>
-                                                                       <td name='ue_summary_survey_answer'/>
-                                                               </tr>
-                                                       </tbody>
-                                               </table>
-                                       </td>
-                               </tr>
-                               <tr>
-                                       <td colspan='2' align='center'>
-                                               <input style='margin-right: 15px;' type='submit' value='&ev.staff.patron.ue_xhtml.print_page.label;' onclick='window.print();'/>
-                                               <input style='margin-left: 15px;' type='submit' value='&ev.staff.patron.ue_xhtml.return_to_editor.label;' 
-                                                       onclick=' unHideMe($("main_div_container")); 
-                                                               hideMe($("summary_div_container"));'/>
-                                       </td>
-                               </tr>
-                       </tbody>
-               </table>
-       </div>
-       </div>
-
-
-       <!-- ************************************************************** -->
-       <!-- This holds all of the strings we may have to alert to the user -->
-       <!-- ************************************************************** -->
-       <div class='hide_me'>
-               <span id='ue_bad_dob'>&staff.patron.ue.bad_dob.label;</span>
-               <span id='ue_bad_username'>&staff.patron.ue.bad_username.label;</span>
-               <span id='ue_bad_password'>&staff.patron.ue.bad_passwords.label;</span>
-               <span id='ue_bad_firstname'>&staff.patron.ue.bad_firstname.label;</span>
-               <span id='ue_bad_middlename'>&staff.patron.ue.bad_middlename.label;</span>
-               <span id='ue_bad_lastname'>&staff.patron.ue.bad_lastname.label;</span>
-               <span id='ue_bad_barcode'>&staff.patron.ue.bad_barcode.label;</span>
-               <span id='ue_duplicate_barcode'>&staff.patron.ue.duplicate_barcode.label;</span>
-               <span id='ue_new_barcode_warn'>&staff.patron.ue.new_barcode_warn.label;</span>
-               <span id='ue_no_ident'>&staff.patron.ue.no_ident.label;</span>
-               <span id='ue_bad_ident_dl'>&staff.patron.ue.bad_ident_dl.label;</span>
-               <span id='ue_bad_ident_ssn'>&staff.patron.ue.bad_ident_ssn.label;</span>
-               <span id='ue_bad_email'>&staff.patron.ue.bad_email.label;</span>
-               <span id='ue_bad_phone'>&staff.patron.ue.bad_phone.label;</span>
-               <span id='ue_no_profile'>&staff.patron.ue.no_profile.label;</span>
-               <span id='ue_bad_expire'>&staff.patron.ue.bad_expire.label;</span>
-               <span id='ue_bad_claims_returned'>&staff.patron.ue.bad_claims_returned.label;</span>
-               <span id='ue_no_profile'>&ev.staff.patron.ue_xhtml.no_profile.label;</span>
-               <span id='ue_unknown_error'>&staff.patron.ue.unknown_error.label;</span>
-               <span id='ue_bad_addr_label'>&staff.patron.ue.bad_addr_label.label;</span>
-               <span id='ue_bad_addr_street'>&staff.patron.ue.bad_addr_street.label;</span>
-               <span id='ue_bad_addr_city'>&staff.patron.ue.bad_addr_city.label;</span>
-               <span id='ue_bad_addr_county'>&staff.patron.ue.bad_addr_county.label;</span>
-               <span id='ue_bad_addr_state'>&staff.patron.ue.bad_addr_state.label;</span>
-               <span id='ue_bad_addr_country'>&staff.patron.ue.bad_addr_country.label;</span>
-               <span id='ue_bad_addr_zip'>&staff.patron.ue.bad_addr_zip.label;</span>
-               <span id='ue_bad_survey'>&staff.patron.ue.bad_survey.label;</span>
-               <span id='ue_delete_addr_warn'>&staff.patron.ue.delete_addr_warn.label;</span>
-               <span id='yes'>&staff.patron.ue.yes.label;</span>
-               <span id='no'>&staff.patron.ue.no.label;</span>
-               <span id='ue_summary_window'>&staff.patron.ue.summary_window.label;</span>
-               <span id='ue_success'>&staff.patron.ue.success.label;</span>
-               <span id='ue_dup_ident1'>&staff.patron.ue.dup_ident1.label;</span>
-               <span id='ue_dup_username'>&staff.patron.ue.dup_username.label;</span>
-               <span id='ue_dup_barcode'>&staff.patron.ue.dup_barcode.label;</span>
-               <span class='hide_me' id='ue_cancel_confirm'>&staff.patron.ue.cancel_confirm.label;</span>
-               <span class='hide_me' id='ue_juv_guardian'>&staff.patron.ue.juv_guardian.label;</span>
-               <span class='hide_me' id='ue_bad_date'>&staff.patron.ue.bad_date.label;</span>
-               <span class='hide_me' id='ue_made_barred'>&staff.patron.ue.made_barred.label;</span>
-               <span class='hide_me' id='ue_claims_return_confirm'>&ev.staff.patron.ue_xhtml.claims_return_confirm.label;</span>
-               <span class='hide_me' id='ue_unsaved_changes'>&ev.staff.patron.ue_xhtml.unsaved_changes.label;</span>
-               <span class='hide_me' id='ue_xact_collision'>&ev.staff.patron.ue_xhtml.xact_collision.label;</span>
-               <span class='hide_me' id='ue_add_approve_confirm'>&ev.staff.patron.ue_xhtml.ue_addr_approve_confirm.label;</span>
-       </div>
-
-       </body>
-</html>
-
diff --git a/xul/server/patron/ue_config.js b/xul/server/patron/ue_config.js
deleted file mode 100644 (file)
index 210e353..0000000
+++ /dev/null
@@ -1,1181 +0,0 @@
-/* -----------------------------------------------------------------------
-       ----------------------------------------------------------------------- */
-const SC_FETCH_ALL             = 'open-ils.circ:open-ils.circ.stat_cat.actor.retrieve.all';
-const SC_CREATE_MAP            = 'open-ils.circ:open-ils.circ.stat_cat.actor.user_map.create';
-const SV_FETCH_ALL             = 'open-ils.circ:open-ils.circ.survey.retrieve.all';
-const FETCH_ID_TYPES           = 'open-ils.actor:open-ils.actor.user.ident_types.retrieve';
-const FETCH_GROUPS             = 'open-ils.actor:open-ils.actor.groups.tree.retrieve';
-const FETCH_NET_LEVELS = 'open-ils.actor:open-ils.actor.net_access_level.retrieve.all';
-const UPDATE_PATRON            = 'open-ils.actor:open-ils.actor.patron.update';
-const PATRON_SEARCH            = 'open-ils.actor:open-ils.actor.patron.search.advanced';
-const ZIP_SEARCH                       = 'open-ils.search:open-ils.search.zip';
-const APPROVE_ADDR             = 'open-ils.actor:open-ils.actor.user.pending_address.approve';
-const FETCH_ADDR_MEMS  = 'open-ils.actor:open-ils.actor.address.members';
-const FETCH_GRP_MEMS           = 'open-ils.actor:open-ils.actor.usergroup.members.retrieve';
-const CREATE_USER_NOTE = 'open-ils.actor:open-ils.actor.note.create';
-const CHECK_BARCODE            = 'open-ils.actor:open-ils.actor.barcode.exists';
-const defaultState             = 'ON';
-const defaultCountry           = 'Canada';
-const defaultNetAccess = 'None';
-const defaultNetLevel   = 1;
-const CSS_INVALID_DATA = 'invalid_value';
-
-// if no org setting exists
-const DEFAULT_ADULT_AGE                        = '18 years';
-
-//const GUARDIAN_NOTE          = 'SYSTEM: Parent/Guardian';
-
-var dataFields;
-const laxRegex         = /\w+/;
-const nameRegex         = /^\S+[\S\s]*$/;
-const numRegex         = /^\d+$/;
-const wordRegex        = /^[\w-]+$/;
-const unameRegex       = /^\w[\.\w\@-]*$/;
-const ssnRegex         = /^\d{3}-\d{2}-\d{4}$/;
-const dlRegex          = /^[a-zA-Z]{2}-\w+/; /* driver's license */
-const phoneRegex       = /^\d{3}-\d{3}-\d{4}(| \S+.*)$/i;
-const nonumRegex       = /^[a-zA-Z]\D*$/; /* no numbers, no beginning whitespace */
-const dateRegex        = /^\d{4}-\d{2}-\d{2}/;
-const zipRegex         = /^\d{5}(-\d{4}|-?$)/; /* 12345 or 12345-6789 */
-
-var barredAlerted = false;
-
-
-function uEditUsrnameBlur(field) {
-       var usrname = uEditNodeVal(field);
-       if (!usrname) { return; }
-       var req = new Request(CHECK_USERNAME, SESSION, usrname);
-       req.callback( 
-               function(r) {
-                       var res = r.getResultObject();
-                       if( res !== null && res != patron.id() ) {
-                               field.widget.onblur = null; /* prevent alert storm */
-                               alertId('ue_dup_username');
-                               field.widget.onblur = uEditUsrnameBlur;
-                               setTimeout( 
-                                       function() {
-                                               field.widget.node.focus();
-                                               field.widget.node.select();
-                                       }, 10 
-                               );
-                       }
-               }
-       );
-       req.send();
-}
-
-
-function uEditBarcodeBlur(field) {
-       var barcode = uEditNodeVal(field);
-       if(!barcode) return;
-       _debug("blurring card with new value " + barcode);
-       var req = new Request(CHECK_BARCODE, SESSION, barcode);
-       req.callback( 
-               function(r) {
-                       var res = r.getResultObject();
-                       if( res == 1 ) {
-                               field.widget.onblur = null; /* prevent alert storm */
-                               alertId('ue_dup_barcode');
-                               field.widget.onblur = uEditBarcodeBlur;
-                               setTimeout( 
-                                       function() {
-                                               field.widget.node.focus();
-                                               field.widget.node.select();
-                                       }, 10 
-                               );
-                       } else {
-                               var node = uEditFindFieldByWId("ue_username");
-                               if(!node.widget.node.value) {
-                                       node.widget.node.value = barcode;
-                                       node.widget.node.onchange();
-                               }
-                       }
-               }
-       );
-       req.send();
-}
-
-
-function uEditDefineData(patron) {
-
-       var fields = [
-               {
-                       required : true,
-                       object  : patron.card(),
-                       key             : 'barcode',
-                       errkey  : 'ue_bad_barcode',
-                       widget  : {
-                               id              : 'ue_barcode',
-                               regex   : wordRegex,
-                               type    : 'input',
-                               onblur : uEditBarcodeBlur
-                       }
-               },
-               {
-                       required : true,
-                       object  : patron,
-                       key             : 'usrname',
-                       errkey  : 'ue_bad_username',
-                       widget  : {
-                               id              : 'ue_username',
-                               regex   : unameRegex,
-                               type    : 'input',
-                               onblur : uEditUsrnameBlur
-                       }
-               },
-               {
-                       required : (patron.isnew()) ? true : false,
-                       object  : patron,
-                       key             : 'passwd',
-                       errkey  : 'ue_bad_password',
-                       widget  : {
-                               id              : 'ue_password1',
-                               type    : 'input',
-                               onpostchange : function(field, newval) {
-                                       var pw2 = uEditFindFieldByWId('ue_password2');
-                                       /* tell the second passsword input to re-validate */
-                                       pw2.widget.node.onchange();
-                               }
-
-                       }
-               },
-               {
-                       required : (patron.isnew()) ? true : false,
-                       object  : patron,
-                       key             : 'passwd',
-                       errkey  : 'ue_bad_password',
-                       widget  : {
-                               id              : 'ue_password2',
-                               type    : 'input',
-                               onpostchange : function(field, newval) {
-                                       var pw1f = uEditFindFieldByWId('ue_password1');
-                                       var pw1 = uEditNodeVal(pw1f);
-                                       field.widget.regex = new RegExp('^'+pw1+'$');
-                                       if( pw1 ) field.required = true;
-                                       else {
-                                               if(!patron.isnew())
-                                                       field.required = false;
-                                       }
-                               }
-                       }
-               },
-               {
-                       required : true,
-                       object  : patron,
-                       key             : 'first_given_name',
-                       errkey  : 'ue_bad_firstname',
-                       widget  : {
-                               id              : 'ue_firstname',
-                               regex   : nameRegex,
-                               type    : 'input',
-                               onblur : function(field) {
-                                       uEditCheckNamesDup('first', field );
-                               }
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'second_given_name',
-                       errkey  : 'ue_bad_middlename',
-                       widget  : {
-                               id              : 'ue_middlename',
-                               regex   : nameRegex,
-                               type    : 'input'
-                       }
-               },
-               {
-                       required : true,
-                       object  : patron,
-                       key             : 'family_name',
-                       errkey  : 'ue_bad_lastname',
-                       widget  : {
-                               id              : 'ue_lastname',
-                               regex   : nameRegex,
-                               type    : 'input',
-                               onblur : function(field) {
-                                       uEditCheckNamesDup('last', field );
-                               }
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'suffix',
-                       widget  : {
-                               id                      : 'ue_suffix',
-                               type            : 'input',
-                               onload  : function(val) {
-                                       setSelector($('ue_suffix_selector'), val);
-                                       $('ue_suffix_selector').onchange = function() {
-                                               uEditFindFieldByKey('suffix').widget.node.onchange();
-                                       }
-                               },
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'alias',
-                       widget  : {
-                               id              : 'ue_alias',
-                               type    : 'input',
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'dob',
-                       errkey  : 'ue_bad_dob',
-                       widget  : {
-                               id                      : 'ue_dob',
-                               regex           : dateRegex,
-                               type            : 'input',
-                               onpostchange    : function(field) { uEditCheckDOB(field); },
-                               onblur  : function(field) { uEditCheckDOB(field); }
-                       }
-               },
-               {
-                       required : true,
-                       object  : patron,
-                       key             : 'ident_type',
-                       errkey  : 'ue_no_ident',
-                       widget  : {
-                               id              : 'ue_primary_ident_type',
-                               regex   : numRegex,
-                               type    : 'select',
-                               onpostchange : function(field, newval) 
-                                       { _uEditIdentPostchange('primary', field, newval); }
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'ident_value',
-                       widget  : {
-                               id                      : 'ue_primary_ident',
-                               type            : 'input',
-                               onblur : function(field) {
-                                       uEditCheckIdentDup(field);
-                               }
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'ident_value2',
-                       widget  : {
-                               id                      : 'ue_secondary_ident',
-                               type            : 'input'
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'email',
-                       errkey  : 'ue_bad_email',
-                       widget  : {
-                               id                      : 'ue_email',
-                               type            : 'input',
-                               regex           :  /.+\@.+\..+/,  /* make me better */
-                               onblur  : function(field) {
-                                       var val = uEditNodeVal(field);
-                                       if( val && val != field.oldemail ) {
-                                               uEditRunDupeSearch('email',
-                                                       { email : { value : val, group : 0 } });
-                                               field.oldemail = val;
-                                       }
-                               }
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'day_phone',
-                       errkey  : 'ue_bad_phone',
-                       widget  : {
-                               id                      : 'ue_day_phone',
-                               type            : 'input',
-                               regex           :  laxRegex,
-                onblur      : function() {
-                    if(uEditUsePhonePw)
-                        uEditMakePhonePw();
-                },
-                onpostchange: function(field, newval) {
-                    /*  if this is a new patron and we are using the phone number for
-                        the password and the staff edits the phone number after entering
-                        it (think typos), update the password too */
-                    if(uEditUsePhonePw && patron.isnew() && patron.passwd() != newval) {
-                        patron.passwd(null);
-                        uEditMakePhonePw();
-                    }
-                }
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'evening_phone',
-                       errkey  : 'ue_bad_phone',
-                       widget  : {
-                               id                      : 'ue_night_phone',
-                               type            : 'input',
-                               regex           :  laxRegex,
-                onblur      : function() {
-                    if(uEditUsePhonePw)
-                        uEditMakePhonePw();
-                }
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'other_phone',
-                       errkey  : 'ue_bad_phone',
-                       widget  : {
-                               id                      : 'ue_other_phone',
-                               type            : 'input',
-                               regex           :  laxRegex,
-                onblur      : function() {
-                    if(uEditUsePhonePw)
-                        uEditMakePhonePw();
-                }
-                       }
-               },
-               {
-                       required : true,
-                       object  : patron,
-                       key             : 'home_ou',
-                       widget  : {
-                               id                      : 'ue_org_selector',
-                               type            : 'select',
-                               regex           :  numRegex,
-                       }
-               },
-               {
-                       required : true,
-                       object  : patron,
-                       key             : 'expire_date',
-                       errkey  : 'ue_bad_expire',
-                       widget  : {
-                               id                      : 'ue_expire',
-                               type            : 'input',
-                               regex           :  dateRegex,
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'active',
-                       widget  : {
-                               id                      : 'ue_active',
-                               type            : 'checkbox',
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'juvenile',
-                       widget  : {
-                               id                      : 'ue_juvenile',
-                               type            : 'checkbox',
-                               onpostchange    : function(field) { uEditCheckDOB(uEditFindFieldByKey('dob')); },
-                               onblur  : function(field) { uEditCheckDOB(uEditFindFieldByKey('dob')); }
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'barred',
-                       widget  : {
-                               id                      : 'ue_barred',
-                               type            : 'checkbox',
-                               onpostchange : function(field, val) {
-                                       var afield = uEditFindFieldByKey('alert_message');
-                                       if( val ) {
-                                               if( !barredAlerted ) {
-                                                       barredAlerted = true;
-                                                       alertId('ue_made_barred');
-                                               }
-                                               afield.required = true; 
-                                       } else {
-                                               afield.required = false;
-                                       }
-                               }
-                       }
-               },
-               {
-                       required : true,
-                       object  : patron,
-                       key             : 'profile',
-                       errkey  : 'ue_no_profile',
-                       widget  : {
-                               id                      : 'ue_profile',
-                               type            : 'select',
-                               regex           : numRegex,
-                               onpostchange : function(field, value) {
-                                       var type                        = groupsCache[value];
-                                       if(!type) return;
-                                       var interval    = type.perm_interval();
-
-                                       /* interval_to_seconds expects 'M' for months, 'm' for minutes */
-                                       interval                        = interval.replace(/mon/, 'Mon'); 
-                                       var intsecs             = parseInt(interval_to_seconds(interval));
-
-                                       var expdate             = new Date();
-                                       var exptime             = expdate.getTime();
-                                       exptime                 += intsecs * 1000;
-                                       expdate.setTime(exptime);
-
-                                       _debug("profile change (interval= '"+interval+"', seconds="+intsecs+")\n\tgenerated a date of " + expdate);
-
-                                       var year                        = expdate.getYear() + 1900;
-                                       var month               = (expdate.getMonth() + 1) + '';
-                                       var day                 = (expdate.getDate()) + '';
-
-                                       if(!month.match(/\d{2}/)) month = '0' + month;
-                                       if(!day.match(/\d{2}/)) day = '0' + day;
-
-
-                                       var node = $('ue_expire');
-                                       node.value = year+'-'+month+'-'+day;
-
-                                       _debug("profile change formatted date to "+ node.value);
-                                       node.onchange();
-                               }
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'net_access_level',
-                       widget  : {
-                               id              : 'ue_net_level',
-                               type    : 'select'
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'master_account',
-                       widget  : {
-                               id                      : 'ue_group_lead',
-                               type            : 'checkbox',
-                       }
-               },
-               {
-                       required : true,
-                       object  : patron,
-                       key             : 'claims_returned_count',
-                       widget  : {
-                               id                      : 'ue_claims_returned',
-                               type            : 'input',
-                               regex           : numRegex,
-                               disabled : true
-                       }
-               },
-               {
-                       required : false,
-                       object  : patron,
-                       key             : 'alert_message',
-                       widget  : {
-                               id                      : 'ue_alert_message',
-                               type            : 'input',
-                       }
-               }
-       ];
-
-       for( var f in fields ) 
-               dataFields.push(fields[f]);
-
-       uEditBuildAddrs(patron);
-       uEditBuildPatronSCM(patron);
-}
-
-var uEditOldFirstName;
-var uEditOldMiddleName; /* future */
-var uEditOldLastName;
-function uEditCheckNamesDup(type, field) {
-       var newval = uEditNodeVal(field);
-       if(!newval) return;
-
-       var dosearch = false;
-
-       if(type =='first') {
-               if( newval != uEditOldFirstName )
-                       dosearch = true;
-               uEditOldFirstName = newval;
-       }
-
-       if(type =='last') {
-               if( newval != uEditOldLastName )
-                       dosearch = true;
-               uEditOldLastName = newval;
-       }
-
-       if( dosearch && uEditOldFirstName && uEditOldLastName ) {
-               var search_hash = {};
-               search_hash['first_given_name'] = { value : uEditOldFirstName, group : 0 };
-               search_hash['family_name'] = { value : uEditOldLastName, group : 0 };
-               uEditRunDupeSearch('names', search_hash);
-       }
-}
-
-var uEditOldIdentValue;
-function uEditCheckIdentDup(field) {
-       var newval = uEditNodeVal(field);
-       if( newval && newval != uEditOldIdentValue ) {
-               /* searches all ident_value fields */
-               var search_hash  = { ident : { value : newval, group : 2 } };
-               uEditRunDupeSearch('ident', search_hash);
-               uEditOldIdentValue = newval;
-       }
-}
-
-
-/* Adds all of the addresses attached to the patron object
-       to the fields array */
-var uEditAddrTemplate;
-function uEditBuildAddrs(patron) {
-       var tbody = $('ue_address_tbody');
-       if(!uEditAddrTemplate)
-               uEditAddrTemplate = tbody.removeChild($('ue_address_template'));
-       for( var a in patron.addresses() ) 
-               uEditBuildAddrFields( patron, patron.addresses()[a]);
-}
-
-
-function uEditDeleteAddr( tbody, row, address, detach ) {
-       if(!confirm($('ue_delete_addr_warn').innerHTML)) return;
-       if(address.isnew()) { 
-               patron.addresses(
-                       grep( patron.addresses(), 
-                               function(i) {
-                                       return (i.id() != address.id());
-                               }
-                       )
-               );
-        if(!patron.addresses())
-            patron.addresses([]);
-
-               /* XXX */
-               for( var f in dataFields ) {
-                       if( dataFields[f].object == address ) {
-                               dataFields[f] = null;
-                       }
-               }
-
-               dataFields = compactArray(dataFields);
-
-       } else {
-
-               if( detach ) { /* remove the offending address from the list */
-                       patron.addresses(
-                               grep( 
-                                       patron.addresses(), 
-                                       function(i) {
-                                               return (i.id() != address.id());
-                                       }
-                               )
-                       );
-            if(!patron.addresses()) {                                      
-                patron.addresses([]);                                      
-                patron.billing_address(null);                              
-                patron.mailing_address(null);
-                patron.ischanged(1);
-            }
-
-
-               } else {
-                       address.isdeleted(1);
-               }
-       }
-
-       tbody.removeChild(row);
-
-       var bid = patron.billing_address();
-    bid = (bid != null && typeof bid == 'object') ? bid.id() : bid;
-
-       var mid = patron.mailing_address();
-    mid = (mid != null && typeof mid == 'object') ? mid.id() : mid;
-
-
-       /* -----------------------------------------------------------------------
-               if we're deleting a billing or mailing address 
-               make sure some other address is automatically
-               assigned as the billing or mailng address 
-               ----------------------------------------------------------------------- */
-
-       if( bid == address.id() ) {
-               for( var a in patron.addresses() ) {
-                       var addr = patron.addresses()[a];
-                       if(!addr.isdeleted() && addr.id() != address.id()) {
-                               var node = uEditFindAddrInput('billing', addr.id());
-                               node.checked = true;
-                               uEditAddrTypeClick(node, 'billing');
-                               break;
-                       }
-               }
-       }
-
-       if( mid == address.id() ) {
-               for( var a in patron.addresses() ) {
-                       var addr = patron.addresses()[a];
-                       if(!addr.isdeleted() && addr.id() != address.id()) {
-                               var node = uEditFindAddrInput('mailing', addr.id());
-                               node.checked = true;
-                               uEditAddrTypeClick(node, 'mailing');
-                               break;
-                       }
-               }
-       }
-
-}
-
-function uEditApproveAddr( tbody, row, address ) {
-    if(!confirm($('ue_add_approve_confirm').innerHTML)) return;
-    var req = new Request(APPROVE_ADDR, SESSION, address);
-    req.callback(
-        function(r) {
-            var oldId = r.getResultObject();
-            if(oldId != null) {
-                // remove the replaced address 
-                       patron.addresses(
-                               grep( patron.addresses(), 
-                                       function(i) { return (i.id() != oldId); }
-                               )
-                       );
-                // update the ID on the new address
-                address.id(oldId);
-                address.replaces(null);
-                address.pending('f');
-                removeChildren($('ue_address_tbody'));
-                   uEditBuildAddrs(patron);
-            }
-        }
-    );
-    req.send();
-}
-
-
-function uEditFindAddrInput(type, id) {
-       var tbody = $('ue_address_tbody');
-       var rows = tbody.getElementsByTagName('tr');
-       for( var r in rows ) {
-               var row = rows[r];
-               if(row.parentNode != tbody) continue;
-               var node = $n(row, 'ue_addr_'+type+'_yes');
-               if( node.getAttribute('address') == id )
-                       return node;
-       }
-}
-
-
-function uEditAddrTypeClick(input, type) {
-       var tbody = $('ue_address_tbody');
-       var rows = tbody.getElementsByTagName('tr');
-       for( var r in rows ) {
-               var row = rows[r];
-               if(row.parentNode != tbody) continue;
-               var node = $n(row, 'ue_addr_'+type+'_yes');
-               removeCSSClass(node.parentNode,'addr_info_checked');
-       }
-
-       addCSSClass(input.parentNode,'addr_info_checked');
-       patron[type+'_address'](input.getAttribute('address'));
-       patron.ischanged(1);
-}
-
-
-
-
-/* Creates the field entries for an address object. */
-function uEditBuildAddrFields(patron, address) {
-
-       var tbody = $('ue_address_tbody');
-
-       var row = tbody.appendChild(
-               uEditAddrTemplate.cloneNode(true));
-
-       uEditCheckSharedAddr(patron, address, tbody, row);
-    
-    // see if this is a pending address
-    if( isTrue(address.pending()) ) {
-        var button = $n(row, 'ue_addr_approve');
-        unHideMe(button);
-        button.onclick = function() { uEditApproveAddr( tbody, row, address ); }
-        var oldaddr = grep(patron.addresses(), function(a){return (a.id() == address.replaces());});
-        if(oldaddr) {
-            oldaddr = oldaddr[0];
-            unHideMe($n(row, 'ue_addr_replaced_row')); 
-            $n(row, 'ue_addr_replaced_div').innerHTML = 
-                $("patronStrings").getFormattedString(
-                    'web.staff.patron.ue.uedit_show_addr_replacement', [
-                    oldaddr.address_type(),
-                    oldaddr.street1(),
-                    oldaddr.street2(),
-                    oldaddr.city(),
-                    oldaddr.state(),
-                    oldaddr.post_code() 
-                ]);
-        }
-    }
-
-       $n(row, 'ue_addr_delete').onclick = 
-               function() { 
-                       uEditDeleteAddr(tbody, row, address); 
-                       uEditCheckErrors();
-               };
-
-       if( patron.billing_address() &&
-                       address.id() == patron.billing_address().id() ) 
-               $n(row, 'ue_addr_billing_yes').checked = true;
-
-       if( patron.mailing_address() &&
-                       address.id() == patron.mailing_address().id() ) 
-               $n(row, 'ue_addr_mailing_yes').checked = true;
-
-       $n(row, 'ue_addr_billing_yes').setAttribute('address', address.id());
-       $n(row, 'ue_addr_mailing_yes').setAttribute('address', address.id());
-
-       /* currently, non-owners cannot edit an address */
-       var disabled = (address.usr() != patron.id())
-
-       var fields = [
-               { 
-                       required : false,
-                       object  : address, 
-                       key             : 'address_type', 
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_label',
-                               type    : 'input',
-                               disabled : disabled,
-                       }
-               },
-               { 
-                       required : true,
-                       object  : address, 
-                       key             : 'street1', 
-                       errkey  : 'ue_bad_addr_street',
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_street1',
-                               type    : 'input',
-                               disabled : disabled,
-                       }
-               },
-               { 
-                       required : false,
-                       object  : address, 
-                       key             : 'street2', 
-                       errkey  : 'ue_bad_addr_street',
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_street2',
-                               type    : 'input',
-                               disabled : disabled,
-                       }
-               },
-               { 
-                       required : true,
-                       object  : address, 
-                       key             : 'city', 
-                       errkey  : 'ue_bad_addr_city',
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_city',
-                               type    : 'input',
-                               disabled : disabled,
-                       }
-               },
-               { 
-                       required : false,
-                       object  : address, 
-                       key             : 'county', 
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_county',
-                               type    : 'input',
-                               disabled : disabled,
-                       }
-               },
-               { 
-                       required : true,
-                       object  : address, 
-                       key             : 'state', 
-                       errkey  : 'ue_bad_addr_state',
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_state',
-                               type    : 'input',
-                               disabled : disabled,
-                       }
-               },
-               { 
-                       required : true,
-                       object  : address, 
-                       key             : 'country', 
-                       errkey  : 'ue_bad_addr_country',
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_country',
-                               type    : 'input',
-                               disabled : disabled,
-                       }
-               },
-               { 
-                       required : true,
-                       object  : address, 
-                       key             : 'post_code',
-                       errkey  : 'ue_bad_addr_zip',
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_zip',
-                               type    : 'input',
-                               disabled : disabled,
-                               regex   : laxRegex,
-                               onblur : function(f) {
-                                       var v = uEditNodeVal(f);
-                                       var req = new Request(ZIP_SEARCH, v);
-                                       req.callback( 
-                                               function(r) {
-                                                       var info = r.getResultObject();
-                                                       if(!info) return;
-                                                       var state = $n(f.widget.base, 'ue_addr_state');
-                                                       var county = $n(f.widget.base, 'ue_addr_county');
-                                                       var city = $n(f.widget.base, 'ue_addr_city');
-                                                       state.value = info.state;
-                                                       state.onchange();
-                                                       county.value = info.county;
-                                                       county.onchange();
-                                                       city.value = info.city;
-                                                       city.onchange();
-                                               }
-                                       );
-                                       req.send();
-                               }
-                       }
-               },
-               { 
-                       required : false,
-                       object  : address, 
-                       key             : 'within_city_limits',
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_inc_yes',
-                               type    : 'checkbox',
-                               disabled : disabled,
-                       }
-               },
-               { 
-                       required : false,
-                       object  : address, 
-                       key             : 'valid',
-                       widget  : {
-                               base    : row,
-                               name    : 'ue_addr_valid_yes',
-                               type    : 'checkbox',
-                               disabled : disabled,
-                       }
-               }
-       ];
-
-       for( var f in fields ) {
-               dataFields.push(fields[f]);
-               uEditActivateField(fields[f]);
-       }
-}
-
-function uEditBuildPatronSCM(patron) {
-       /* get the list of pre-defined maps */
-       var fields = uEditFindFieldsByKey('stat_cat_entry');
-       var map;
-       var newmaps = [];
-
-       /* for each user stat cat, pop it off the list,
-       updated the existing stat map field to match
-       the popped map and shove the existing stat
-       map field onto the user's list of stat maps */
-       while( (map = patron.stat_cat_entries().pop()) ) {
-
-               var field = grep(fields, 
-                       function(item) {
-                               return (item.object.stat_cat() == map.stat_cat());
-                       }
-               );
-
-               if(field) {
-                       var val = map.stat_cat_entry();
-                       field = field[0];
-                       $n(field.widget.base, field.widget.name).value = val;
-                       setSelector($n(field.widget.base, 'ue_stat_cat_selector'), val );
-                       field.object.stat_cat_entry(val);
-                       field.object.id(map.id());
-                       newmaps.push(field.object);
-               }
-       }
-
-       for( var m in newmaps ) 
-               patron.stat_cat_entries().push(newmaps[m]);
-}
-
-
-function uEditBuildSCMField(statcat, row) {
-
-       var map = new actscecm();
-       map.stat_cat(statcat.id());
-       map.target_usr(patron.id());
-
-       var field = {
-               required : false,
-               object  : map,
-               key             : 'stat_cat_entry',
-               widget  : {
-                       base    : row,
-                       name    : 'ue_stat_cat_newval',
-                       type    : 'input',
-
-                       onpostchange : function( field, newval ) {
-
-                               /* see if the current map already resides in 
-                                       the patron entry list */
-                               var exists = grep( patron.stat_cat_entries(),
-                                       function(item) {
-                                               return (item.stat_cat() == statcat.id()); 
-                                       }
-                               );
-
-                               if(newval) {
-                                       map.isdeleted(0);
-                                       setSelector($n(row, 'ue_stat_cat_selector'), newval);
-                               }
-
-                               if(exists) {
-                                       if(!newval) {
-
-                                               /* if the map is new but currently contains no value
-                                                       remove it from the set of new maps */
-                                               if(map.isnew()) {
-                                                       patron.stat_cat_entries(
-                                                               grep( patron.stat_cat_entries(),
-                                                                       function(item) {
-                                                                               return (item.stat_cat() != map.stat_cat());
-                                                                       }
-                                                               )
-                                                       );
-
-                                               } else {
-                                                       map.isdeleted(1);
-                                                       map.ischanged(0);
-                                               }
-                                       } 
-
-                               } else {
-
-                                       /* map does not exist in the map array but now has data */
-                                       if(newval) { 
-                                               map.isnew(1);
-                                               if(!patron.stat_cat_entries())
-                                                       patron.stat_cat_entries([]);
-                                               patron.stat_cat_entries().push(map);
-                                       }
-                               }
-                       }
-               }
-       }
-
-       dataFields.push(field);
-}
-
-
-
-/** Run this after a new ident type is selected */
-function _uEditIdentPostchange(type, field, newval) {
-
-       if(!newval) return;
-
-       /* When the ident type is changed, we change the
-       regex on the ident_value to match the selected type */
-       var vfname = 'ident_value';
-       if(type == 'secondary') vfname = 'ident_value2';
-       var vfield = uEditFindFieldByKey(vfname);
-       var name = identTypesCache[uEditNodeVal(field)].name();
-
-       hideMe($(type+'_ident_ssn_help'));
-       hideMe($(type+'_ident_dl_help'));
-
-       if(name.match(/ssn/i)) {
-               vfield.widget.regex = ssnRegex;
-               vfield.errkey = 'ue_bad_ident_ssn';
-               unHideMe($(type+'_ident_ssn_help'));
-
-       } else {
-
-               if(name.match(/driver/i)) {
-                       vfield.widget.regex = dlRegex;
-                       vfield.errkey = 'ue_bad_ident_dl';
-                       unHideMe($(type+'_ident_dl_help'));
-                       if(!uEditNodeVal(vfield))
-                               vfield.widget.node.value = defaultState + '-';
-
-               } else {
-                       vfield.widget.regex = null;
-                       vfield.errkey = null;
-               }
-       }
-
-       /* focus then valdate the value field */
-       vfield.widget.node.onchange();
-       vfield.widget.node.focus();
-}
-
-
-/* checks to see if the given address is shared by others.
- * if so, the address row is styled and ...
- */
-
-function uEditCheckSharedAddr(patron, address, tbody, row) {
-
-       if( address.isnew() || (patron.isnew() && !clone) ) return;
-
-       var req = new Request(FETCH_ADDR_MEMS, SESSION, address.id());
-       req.callback( 
-               function(r) {
-
-                       var members = r.getResultObject();
-                       var shared = false;
-
-                       for( var m in members ) {
-                               var id = members[m];
-
-                               if( id != patron.id() ) {
-
-                                       addCSSClass(row.getElementsByTagName('table')[0], 'shared_address');
-                                       unHideMe($n(row, 'shared_row'));
-                                       $n(row, 'ue_addr_delete').disabled = true;
-
-                                       if( address.usr() != patron.id() ) {
-                                               var button = $n(row, 'ue_addr_detach');
-                                               unHideMe(button);
-                                               button.onclick = 
-                                                       function() { uEditDeleteAddr( tbody, row, address, true ); }
-                                       }
-
-                                       shared = true;
-                                       break;
-                               }
-                       }
-
-                       if( shared ) {
-
-                               /* if this is a shared address, set the owner field and 
-                                       give the staff a chance to edit the owner if it's not this user */
-
-                               var nnode = $n(row, 'addr_owner_name');
-                               var link = $n(row, 'addr_owner');
-                               var id = address.usr();
-                       
-                               if( id == patron.id() ) {
-                       
-                                       nnode.appendChild(text(
-                                               patron.first_given_name() + ' ' + patron.family_name()));
-                                       hideMe($n(row, 'owner_link_div'));
-                       
-                               } else {
-                       
-                                       var ses = cgi.param('ses'); 
-                                       if (xulG) if (xulG.ses) ses = xulG.ses;
-                                       if (xulG) if (xulG.params) if (xulG.params.ses) ses = xulG.params.ses;
-                                       link.onclick = 
-                                               function() { window.xulG.spawn_editor({ses:ses,usr:id}) };
-                               
-                                       if( userCache[id] ) {
-                        var usr = userCache[id];
-                                               nnode.appendChild(text(
-                                                       usr.first_given_name() + ' ' +  usr.family_name()));
-                               
-                                       } else {
-                               
-                                               fetchFleshedUser( id, 
-                                                       function(usr) {
-                                                               userCache[usr.id()] = usr;
-                                                               nnode.appendChild(text(
-                                                                       usr.first_given_name() + ' ' + usr.family_name()));
-                                                       }
-                                               );
-                                       }
-                               }
-                       }
-               }
-       );
-
-       req.send();
-}
-
-
-
-
-var __lastdob;
-function uEditCheckDOB(field) {
-
-       var dob = uEditNodeVal(field);
-    var ident_field = uEditFindFieldByKey('ident_value2');
-
-    if(dob) {
-
-        /* don't bother if the data isn't valid */
-        if(!dob.match(field.widget.regex)) 
-            return;
-
-        if( dob == __lastdob ) return;
-
-        __lastdob = dob;
-
-        var parts = dob.split(/-/);
-        parts[2] = parts[2].replace(/[T ].*/,'');
-        dob = buildDate( parts[0], parts[1], parts[2] );
-
-        var today = new Date();
-
-        if(!dob || dob > today) {
-            addCSSClass(field.widget.node, CSS_INVALID_DATA);
-            alertId('ue_bad_date');
-            return;
-        }
-
-        var base = new Date();
-        var age;
-        if(orgSettings['global.juvenile_age_threshold'])
-            age = orgSettings['global.juvenile_age_threshold'].value;
-        else age = DEFAULT_ADULT_AGE;
-        base.setTime(base.getTime() - Number(interval_to_seconds(age) + '000'));
-
-
-        unHideMe(ident_field.widget.node.parentNode.parentNode.parentNode);
-        if( dob < base ) { /* patron is of age */
-            ident_field.required = false;
-               uEditFindFieldByKey('juvenile').widget.node.checked = false;
-            if(!uEditNodeVal(ident_field))
-                hideMe(ident_field.widget.node.parentNode.parentNode.parentNode);
-            return;
-        }
-
-    } else {
-        // no DOB and we are not flagged as a juvenile
-        if(uEditFindFieldByKey('juvenile').widget.node.checked == false) {
-            if(!uEditNodeVal(ident_field))
-                hideMe(ident_field.widget.node.parentNode.parentNode.parentNode);
-            return;
-        }
-    }
-
-    unHideMe(ident_field.widget.node.parentNode.parentNode.parentNode);
-    if(!uEditFindFieldByKey('juvenile').widget.node.checked)
-           uEditFindFieldByKey('juvenile').widget.node.checked = true;
-       ident_field.required = true;
-       uEditCheckErrors();
-}
-
-
-
index c6ec82b..625dc75 100644 (file)
@@ -3,703 +3,726 @@ dump('entering patron/util.js\n');
 if (typeof patron == 'undefined') var patron = {};
 patron.util = {};
 
-patron.util.EXPORT_OK  = [ 
-       'columns', 'mbts_columns', 'mb_columns', 'mp_columns', /*'std_map_row_to_column',*/ 'std_map_row_to_columns',
-       'retrieve_au_via_id', 'retrieve_fleshed_au_via_id', 'retrieve_fleshed_au_via_barcode', 'set_penalty_css', 'retrieve_name_via_id',
-    'merge', 'ausp_columns'
+patron.util.EXPORT_OK    = [ 
+    'columns', 'mbts_columns', 'mb_columns', 'mp_columns', /*'std_map_row_to_column',*/ 'std_map_row_to_columns',
+    'retrieve_au_via_id', 'retrieve_fleshed_au_via_id', 'retrieve_fleshed_au_via_barcode', 'set_penalty_css', 'retrieve_name_via_id',
+    'merge', 'ausp_columns', 'format_name', 'work_log_patron_edit'
 ];
-patron.util.EXPORT_TAGS        = { ':all' : patron.util.EXPORT_OK };
+patron.util.EXPORT_TAGS    = { ':all' : patron.util.EXPORT_OK };
 
 patron.util.mbts_columns = function(modify,params) {
 
-       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
-       JSAN.use('util.money'); JSAN.use('util.date');
+    JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+    JSAN.use('util.money'); JSAN.use('util.date');
 
     var commonStrings = document.getElementById('commonStrings');
 
-       var c = [
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'id', 'label' : commonStrings.getString('staff.mbts_id_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mbts.id(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'usr', 'label' : commonStrings.getString('staff.mbts_usr_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.usr() ? "Id = " + my.mbts.usr() : ""; }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'xact_type', 'label' : commonStrings.getString('staff.mbts_xact_type_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mbts.xact_type(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'balance_owed', 'label' : commonStrings.getString('staff.mbts_balance_owed_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mbts.balance_owed() ); },
-                       'sort_type' : 'money'
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'total_owed', 'label' : commonStrings.getString('staff.mbts_total_owed_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mbts.total_owed() ); },
-                       'sort_type' : 'money'
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'total_paid', 'label' : commonStrings.getString('staff.mbts_total_paid_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mbts.total_paid() ); },
-                       'sort_type' : 'money'
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'last_billing_note', 'label' : commonStrings.getString('staff.mbts_last_billing_note_label'), 'flex' : 2,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.last_billing_note(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'last_billing_type', 'label' : commonStrings.getString('staff.mbts_last_billing_type_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.last_billing_type(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'last_billing_ts', 'label' : commonStrings.getString('staff.mbts_last_billing_timestamp_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return util.date.formatted_date( my.mbts.last_billing_ts(), "" ); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'last_payment_note', 'label' : commonStrings.getString('staff.mbts_last_payment_note_label'), 'flex' : 2,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.last_payment_note(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'last_payment_type', 'label' : commonStrings.getString('staff.mbts_last_payment_type_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.last_payment_type(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'last_payment_ts', 'label' : commonStrings.getString('staff.mbts_last_payment_timestamp_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return util.date.formatted_date( my.mbts.last_payment_ts(), "" ); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'xact_start', 'label' : commonStrings.getString('staff.mbts_xact_start_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mbts.xact_start() ? my.mbts.xact_start().toString().substr(0,10) : ""; }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'xact_finish', 'label' : commonStrings.getString('staff.mbts_xact_finish_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mbts.xact_finish() ? my.mbts.xact_finish().toString().substr(0,10) : ""; }
-               },
-       ];
-       for (var i = 0; i < c.length; i++) {
-               if (modify[ c[i].id ]) {
-                       for (var j in modify[ c[i].id ]) {
-                               c[i][j] = modify[ c[i].id ][j];
-                       }
-               }
-       }
-       if (params) {
-               if (params.just_these) {
-                       JSAN.use('util.functional');
-                       var new_c = [];
-                       for (var i = 0; i < params.just_these.length; i++) {
-                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
-                               new_c.push( function(y){ return y; }( x ) );
-                       }
-                       c = new_c;
-               }
-               if (params.except_these) {
-                       JSAN.use('util.functional');
-                       var new_c = [];
-                       for (var i = 0; i < c.length; i++) {
-                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
-                               if (!x) new_c.push(c[i]);
-                       }
-                       c = new_c;
-               }
-       }
-       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+    var c = [
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mbts_id', 'label' : commonStrings.getString('staff.mbts_id_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mbts.id(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'usr', 'label' : commonStrings.getString('staff.mbts_usr_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mbts.usr() ? "Id = " + my.mbts.usr() : ""; }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'xact_type', 'label' : commonStrings.getString('staff.mbts_xact_type_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mbts.xact_type(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'balance_owed', 'label' : commonStrings.getString('staff.mbts_balance_owed_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return util.money.sanitize( my.mbts.balance_owed() ); },
+            'sort_type' : 'money'
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'total_owed', 'label' : commonStrings.getString('staff.mbts_total_owed_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return util.money.sanitize( my.mbts.total_owed() ); },
+            'sort_type' : 'money'
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'total_paid', 'label' : commonStrings.getString('staff.mbts_total_paid_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return util.money.sanitize( my.mbts.total_paid() ); },
+            'sort_type' : 'money'
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'last_billing_note', 'label' : commonStrings.getString('staff.mbts_last_billing_note_label'), 'flex' : 2,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mbts.last_billing_note(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'last_billing_type', 'label' : commonStrings.getString('staff.mbts_last_billing_type_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mbts.last_billing_type(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'last_billing_ts', 'label' : commonStrings.getString('staff.mbts_last_billing_timestamp_label'), 'flex' : 1,
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mbts.last_billing_ts(), "%{localized}" ); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'last_payment_note', 'label' : commonStrings.getString('staff.mbts_last_payment_note_label'), 'flex' : 2,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mbts.last_payment_note(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'last_payment_type', 'label' : commonStrings.getString('staff.mbts_last_payment_type_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mbts.last_payment_type(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'last_payment_ts', 'label' : commonStrings.getString('staff.mbts_last_payment_timestamp_label'), 'flex' : 1,
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mbts.last_payment_ts(), "%{localized}" ); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mbts_xact_start', 'label' : commonStrings.getString('staff.mbts_xact_start_label'), 'flex' : 1,
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mbts.xact_start() ? util.date.formatted_date( my.mbts.xact_start(), "%{localized}" ) : ""; }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mbts_xact_finish', 'label' : commonStrings.getString('staff.mbts_xact_finish_label'), 'flex' : 1,
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mbts.xact_finish() ? util.date.formatted_date( my.mbts.xact_finish(), "%{localized}" ) : ""; }
+        },
+    ];
+    for (var i = 0; i < c.length; i++) {
+        if (modify[ c[i].id ]) {
+            for (var j in modify[ c[i].id ]) {
+                c[i][j] = modify[ c[i].id ][j];
+            }
+        }
+    }
+    if (params) {
+        if (params.just_these) {
+            JSAN.use('util.functional');
+            var new_c = [];
+            for (var i = 0; i < params.just_these.length; i++) {
+                var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                new_c.push( function(y){ return y; }( x ) );
+            }
+            c = new_c;
+        }
+        if (params.except_these) {
+            JSAN.use('util.functional');
+            var new_c = [];
+            for (var i = 0; i < c.length; i++) {
+                var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                if (!x) new_c.push(c[i]);
+            }
+            c = new_c;
+        }
+    }
+    return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
 }
 
 patron.util.mb_columns = function(modify,params) {
 
-       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
-       JSAN.use('util.money'); JSAN.use('util.date');
+    JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+    JSAN.use('util.money'); JSAN.use('util.date');
 
     var commonStrings = document.getElementById('commonStrings');
 
-       var c = [
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'id', 'label' : commonStrings.getString('staff.mb_id_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mb.id(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'voided', 'label' : commonStrings.getString('staff.mb_voided_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return get_bool( my.mb.voided() ) ? "Yes" : "No"; }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'voider', 'label' : commonStrings.getString('staff.mb_voider_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mb.voider() ? "Id = " + my.mb.voider() : ""; }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'void_time', 'label' : commonStrings.getString('staff.mb_void_time_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mb.void_time(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'amount', 'label' : commonStrings.getString('staff.mb_amount_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mb.amount() ); },
-                       'sort_type' : 'money'
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'billing_type', 'label' : commonStrings.getString('staff.mb_billing_type_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mb.billing_type(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'billing_ts', 'label' : commonStrings.getString('staff.mb_billing_ts_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.date.formatted_date( my.mb.billing_ts(), "" ); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'note', 'label' : commonStrings.getString('staff.mb_note_label'), 'flex' : 2,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mb.note(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'xact', 'label' : commonStrings.getString('staff.mb_xact_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mb.xact(); }
-               },
-       ];
-       for (var i = 0; i < c.length; i++) {
-               if (modify[ c[i].id ]) {
-                       for (var j in modify[ c[i].id ]) {
-                               c[i][j] = modify[ c[i].id ][j];
-                       }
-               }
-       }
-       if (params) {
-               if (params.just_these) {
-                       JSAN.use('util.functional');
-                       var new_c = [];
-                       for (var i = 0; i < params.just_these.length; i++) {
-                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
-                               new_c.push( function(y){ return y; }( x ) );
-                       }
-                       c = new_c;
-               }
-               if (params.except_these) {
-                       JSAN.use('util.functional');
-                       var new_c = [];
-                       for (var i = 0; i < c.length; i++) {
-                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
-                               if (!x) new_c.push(c[i]);
-                       }
-                       c = new_c;
-               }
-
-       }
-       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+    var c = [
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mb_id', 'label' : commonStrings.getString('staff.mb_id_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mb.id(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'voided', 'label' : commonStrings.getString('staff.mb_voided_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return get_bool( my.mb.voided() ) ? "Yes" : "No"; }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'voider', 'label' : commonStrings.getString('staff.mb_voider_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mb.voider() ? "Id = " + my.mb.voider() : ""; }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'void_time', 'label' : commonStrings.getString('staff.mb_void_time_label'), 'flex' : 1,
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mb.void_time(), "%{localized}" ); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'amount', 'label' : commonStrings.getString('staff.mb_amount_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return util.money.sanitize( my.mb.amount() ); },
+            'sort_type' : 'money'
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'billing_type', 'label' : commonStrings.getString('staff.mb_billing_type_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mb.billing_type(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'billing_ts', 'label' : commonStrings.getString('staff.mb_billing_ts_label'), 'flex' : 1,
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mb.billing_ts(), "%{localized}" ); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'note', 'label' : commonStrings.getString('staff.mb_note_label'), 'flex' : 2,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mb.note(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'xact', 'label' : commonStrings.getString('staff.mb_xact_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mb.xact(); }
+        },
+    ];
+    for (var i = 0; i < c.length; i++) {
+        if (modify[ c[i].id ]) {
+            for (var j in modify[ c[i].id ]) {
+                c[i][j] = modify[ c[i].id ][j];
+            }
+        }
+    }
+    if (params) {
+        if (params.just_these) {
+            JSAN.use('util.functional');
+            var new_c = [];
+            for (var i = 0; i < params.just_these.length; i++) {
+                var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                new_c.push( function(y){ return y; }( x ) );
+            }
+            c = new_c;
+        }
+        if (params.except_these) {
+            JSAN.use('util.functional');
+            var new_c = [];
+            for (var i = 0; i < c.length; i++) {
+                var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                if (!x) new_c.push(c[i]);
+            }
+            c = new_c;
+        }
+
+    }
+    return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
 }
 
 patron.util.mp_columns = function(modify,params) {
 
-       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
-       JSAN.use('util.money'); JSAN.use('util.date'); JSAN.use('patron.util');
+    JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+    JSAN.use('util.money'); JSAN.use('util.date'); JSAN.use('patron.util');
 
     var commonStrings = document.getElementById('commonStrings');
 
-       var c = [
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'mp_id', 'label' : commonStrings.getString('staff.mp_id_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mp.id(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'mp_amount', 'label' : commonStrings.getString('staff.mp_amount_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mp.amount() ); },
-                       'sort_type' : 'money'
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'mp_payment_type', 'label' : commonStrings.getString('staff.mp_payment_type_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mp.payment_type(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'mp_payment_ts', 'label' : commonStrings.getString('staff.mp_payment_timestamp_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.date.formatted_date( my.mp.payment_ts(), "" ); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'mp_note', 'label' : commonStrings.getString('staff.mp_note_label'), 'flex' : 2,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mp.note(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'mp_ws', 'label' : commonStrings.getString('staff.mp_cash_drawer_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mp.cash_drawer().name(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'mp_staff', 'label' : commonStrings.getString('staff.mp_accepting_usr_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { var s = my.mp.accepting_usr(); if (s && typeof s != "object") s = patron.util.retrieve_fleshed_au_via_id(ses(),s); return s.family_name() + " (" + s.card().barcode() + ") @ " + data.hash.aou[ s.home_ou() ].shortname(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'mp_xact', 'label' : commonStrings.getString('staff.mp_xact_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mp.xact(); }
-               },
-       ];
-       for (var i = 0; i < c.length; i++) {
-               if (modify[ c[i].id ]) {
-                       for (var j in modify[ c[i].id ]) {
-                               c[i][j] = modify[ c[i].id ][j];
-                       }
-               }
-       }
-       if (params) {
-               if (params.just_these) {
-                       JSAN.use('util.functional');
-                       var new_c = [];
-                       for (var i = 0; i < params.just_these.length; i++) {
-                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
-                               new_c.push( function(y){ return y; }( x ) );
-                       }
-                       c = new_c;
-               }
-               if (params.except_these) {
-                       JSAN.use('util.functional');
-                       var new_c = [];
-                       for (var i = 0; i < c.length; i++) {
-                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
-                               if (!x) new_c.push(c[i]);
-                       }
-                       c = new_c;
-               }
-
-       }
-       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+    var c = [
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mp_id', 'label' : commonStrings.getString('staff.mp_id_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mp.id(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mp_amount', 'label' : commonStrings.getString('staff.mp_amount_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return util.money.sanitize( my.mp.amount() ); },
+            'sort_type' : 'money'
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mp_payment_type', 'label' : commonStrings.getString('staff.mp_payment_type_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mp.payment_type(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mp_payment_ts', 'label' : commonStrings.getString('staff.mp_payment_timestamp_label'), 'flex' : 1,
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mp.payment_ts(), "%{localized}" ); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mp_note', 'label' : commonStrings.getString('staff.mp_note_label'), 'flex' : 2,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mp.note(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mp_ws', 'label' : commonStrings.getString('staff.mp_cash_drawer_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mp.cash_drawer().name(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mp_staff', 'label' : commonStrings.getString('staff.mp_accepting_usr_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { var s = my.mp.accepting_usr(); if (s && typeof s != "object") s = patron.util.retrieve_fleshed_au_via_id(ses(),s,["card"]); return s.family_name() + " (" + s.card().barcode() + ") @ " + data.hash.aou[ s.home_ou() ].shortname(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'mp_xact', 'label' : commonStrings.getString('staff.mp_xact_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.mp.xact(); }
+        },
+    ];
+    for (var i = 0; i < c.length; i++) {
+        if (modify[ c[i].id ]) {
+            for (var j in modify[ c[i].id ]) {
+                c[i][j] = modify[ c[i].id ][j];
+            }
+        }
+    }
+    if (params) {
+        if (params.just_these) {
+            JSAN.use('util.functional');
+            var new_c = [];
+            for (var i = 0; i < params.just_these.length; i++) {
+                var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                new_c.push( function(y){ return y; }( x ) );
+            }
+            c = new_c;
+        }
+        if (params.except_these) {
+            JSAN.use('util.functional');
+            var new_c = [];
+            for (var i = 0; i < c.length; i++) {
+                var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                if (!x) new_c.push(c[i]);
+            }
+            c = new_c;
+        }
+
+    }
+    return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
 }
 
 patron.util.ausp_columns = function(modify,params) {
 
-       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+    JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
     JSAN.use('util.functional');
 
     var commonStrings = document.getElementById('commonStrings');
 
-       var c = [
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'csp_id', 'label' : commonStrings.getString('staff.csp_id_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.csp.id(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'csp_name', 'label' : commonStrings.getString('staff.csp_name_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.csp.name(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'csp_label', 'label' : commonStrings.getString('staff.csp_label_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.csp.label(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'csp_block_list', 'label' : commonStrings.getString('staff.csp_block_list_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.csp.block_list(); }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'csp_block_circ', 'label' : commonStrings.getString('staff.csp_block_circ_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { 
-                return String( my.csp.block_list() ).match('CIRC') ? commonStrings.getString('staff.csp_block_circ_yes') : commonStrings.getString('staff.csp_block_circ_no'); 
+    var c = [
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'csp_id', 'label' : commonStrings.getString('staff.csp_id_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return typeof my.csp == 'object' ? my.csp.id() : my.csp; }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'csp_name', 'label' : commonStrings.getString('staff.csp_name_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return typeof my.csp == 'object' ? my.csp.name() : data.hash.csp[ my.csp ].name(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'csp_label', 'label' : commonStrings.getString('staff.csp_label_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return typeof my.csp == 'object' ? my.csp.label() : data.hash.csp[ my.csp ].label(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'csp_block_list', 'label' : commonStrings.getString('staff.csp_block_list_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return typeof my.csp == 'object' ? my.csp.block_list() : data.hash.csp[ my.csp ].block_list(); }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'csp_block_circ', 'label' : commonStrings.getString('staff.csp_block_circ_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { 
+                var my_csp = typeof my.csp == 'object' ? my.csp : data.hash.csp[ my.csp ];
+                return String( my_csp.block_list() ).match('CIRC') ? commonStrings.getString('staff.csp_block_circ_yes') : commonStrings.getString('staff.csp_block_circ_no'); 
             }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'csp_block_renew', 'label' : commonStrings.getString('staff.csp_block_renew_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { 
-                return String( my.csp.block_list() ).match('RENEW') ? commonStrings.getString('staff.csp_block_renew_yes') : commonStrings.getString('staff.csp_block_renew_no'); 
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'csp_block_renew', 'label' : commonStrings.getString('staff.csp_block_renew_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { 
+                var my_csp = typeof my.csp == 'object' ? my.csp : data.hash.csp[ my.csp ];
+                return String( my_csp.block_list() ).match('RENEW') ? commonStrings.getString('staff.csp_block_renew_yes') : commonStrings.getString('staff.csp_block_renew_no'); 
 
             }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'csp_block_hold', 'label' : commonStrings.getString('staff.csp_block_hold_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { 
-                return String( my.csp.block_list() ).match('HOLD') ?  commonStrings.getString('staff.csp_block_hold_yes') : commonStrings.getString('staff.csp_block_hold_no'); 
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'csp_block_hold', 'label' : commonStrings.getString('staff.csp_block_hold_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { 
+                var my_csp = typeof my.csp == 'object' ? my.csp : data.hash.csp[ my.csp ];
+                return String( my_csp.block_list() ).match('HOLD') ?  commonStrings.getString('staff.csp_block_hold_yes') : commonStrings.getString('staff.csp_block_hold_no'); 
             }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'ausp_staff', 'label' : commonStrings.getString('staff.ausp_staff_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { 
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'ausp_id', 'label' : commonStrings.getString('staff.ausp_id_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.ausp ? my.ausp.id() : ''; }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'ausp_staff', 'label' : commonStrings.getString('staff.ausp_staff_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { 
                 return my.ausp ? my.ausp.staff() : '';
             }
         },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'ausp_set_date', 'label' : commonStrings.getString('staff.ausp_set_date_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { 
-                return my.ausp ? my.ausp.set_date() : '';
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'ausp_set_date', 'label' : commonStrings.getString('staff.ausp_set_date_label'), 'flex' : 1,
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { 
+                return my.ausp ? util.date.formatted_date( my.ausp.set_date(), "%{localized}" ) : '';
             }
         },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'ausp_note', 'label' : commonStrings.getString('staff.ausp_note_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { 
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'ausp_note', 'label' : commonStrings.getString('staff.ausp_note_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { 
                 return my.ausp ? my.ausp.note() : '';
             }
         },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'ausp_org_unit', 'label' : commonStrings.getString('staff.ausp_org_unit_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : false, 'render' : function(my) { 
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'ausp_org_unit', 'label' : commonStrings.getString('staff.ausp_org_unit_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { 
                 return my.ausp ? data.hash.aou[ my.ausp.org_unit() ].shortname() : '';
             }
         }
-       ];
-       for (var i = 0; i < c.length; i++) {
-               if (modify[ c[i].id ]) {
-                       for (var j in modify[ c[i].id ]) {
-                               c[i][j] = modify[ c[i].id ][j];
-                       }
-               }
-       }
-       if (params) {
-               if (params.just_these) {
-                       var new_c = [];
-                       for (var i = 0; i < params.just_these.length; i++) {
-                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
-                               new_c.push( function(y){ return y; }( x ) );
-                       }
-                       c = new_c;
-               }
-               if (params.except_these) {
-                       var new_c = [];
-                       for (var i = 0; i < c.length; i++) {
-                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
-                               if (!x) new_c.push(c[i]);
-                       }
-                       c = new_c;
-               }
-
-       }
-       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+    ];
+    for (var i = 0; i < c.length; i++) {
+        if (modify[ c[i].id ]) {
+            for (var j in modify[ c[i].id ]) {
+                c[i][j] = modify[ c[i].id ][j];
+            }
+        }
+    }
+    if (params) {
+        if (params.just_these) {
+            var new_c = [];
+            for (var i = 0; i < params.just_these.length; i++) {
+                var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                new_c.push( function(y){ return y; }( x ) );
+            }
+            c = new_c;
+        }
+        if (params.except_these) {
+            var new_c = [];
+            for (var i = 0; i < c.length; i++) {
+                var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                if (!x) new_c.push(c[i]);
+            }
+            c = new_c;
+        }
+
+    }
+    return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
 }
 
 
 patron.util.columns = function(modify,params) {
-       
-       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+    
+    JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
 
     var commonStrings = document.getElementById('commonStrings');
 
-       var c = [
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'barcode', 'label' : commonStrings.getString('staff.card_barcode_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.card().barcode(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'usrname', 'label' : commonStrings.getString('staff.au_usrname_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.usrname(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'profile', 'label' : commonStrings.getString('staff.au_profile_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.pgt[ my.au.profile() ].name(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'active', 'label' : commonStrings.getString('staff.au_active_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return get_bool( my.au.active() ) ? "Yes" : "No"; }
-               },
-               {
-                       'persist' : 'hidden width ordinal', 'id' : 'barred', 'label' : commonStrings.getString('staff.au_barred_label'), 'flex' : 1,
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return get_bool( my.au.barred() ) ? "Yes" : "No"; }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'id', 'label' : document.getElementById('commonStrings').getString('staff.au_id_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.id(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'prefix', 'label' : document.getElementById('commonStrings').getString('staff.au_name_prefix_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.prefix(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'family_name', 'label' : document.getElementById('commonStrings').getString('staff.au_family_name_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.family_name(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'first_given_name', 'label' : document.getElementById('commonStrings').getString('staff.au_first_given_name_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.first_given_name(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'second_given_name', 'label' : document.getElementById('commonStrings').getString('staff.au_second_given_name_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.second_given_name(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'suffix', 'label' : document.getElementById('commonStrings').getString('staff.au_name_suffix_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.suffix(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'alert_message', 'label' : commonStrings.getString('staff.au_alert_message_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.alert_message(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'claims_returned_count', 'label' : commonStrings.getString('staff.au_claims_returned_count_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.claims_returned_count(); },
-                       'sort_type' : 'number'
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'create_date', 'label' : commonStrings.getString('staff.au_create_date_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.create_date(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'expire_date', 'label' : commonStrings.getString('staff.au_expire_date_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.expire_date().substr(0,10); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'home_ou', 'label' : commonStrings.getString('staff.au_home_library_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.aou[ my.au.home_ou() ].shortname(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'home_ou_fullname', 'label' : commonStrings.getString('staff.au_home_library_fullname_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.aou[ my.au.home_ou() ].name(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'credit_forward_balance', 'label' : commonStrings.getString('staff.au_credit_forward_balance_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.credit_forward_balance(); },
-                       'sort_type' : 'money'
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'day_phone', 'label' : commonStrings.getString('staff.au_day_phone_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.day_phone(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'evening_phone', 'label' : commonStrings.getString('staff.au_evening_phone_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.evening_phone(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'other_phone', 'label' : commonStrings.getString('staff.au_other_phone_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.other_phone(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'email', 'label' : commonStrings.getString('staff.au_email_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.email(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'alias', 'label' : commonStrings.getString('staff.au_alias_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.alias(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'dob', 'label' : commonStrings.getString('staff.au_birth_date_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.dob().substr(0,10); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'ident_type', 'label' : commonStrings.getString('staff.au_ident_type_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.cit[ my.au.ident_type() ].name(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'ident_value', 'label' : commonStrings.getString('staff.au_ident_value_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.ident_value(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'ident_type2', 'label' : commonStrings.getString('staff.au_ident_type2_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.cit[ my.au.ident_type2() ].name(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'ident_value2', 'label' : commonStrings.getString('staff.au_ident_value2_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.ident_value2(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'net_access_level', 'label' : commonStrings.getString('staff.au_net_access_level_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.net_access_level(); }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'master_account', 'label' : commonStrings.getString('staff.au_master_account_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return get_bool( my.au.master_account() ) ? "Yes" : "No"; }
-               },
-               { 
-                       'persist' : 'hidden width ordinal', 'id' : 'usrgroup', 'label' : commonStrings.getString('staff.au_group_id_label'), 'flex' : 1, 
-                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.usrgroup(); }
-               },
-       ];
-       for (var i = 0; i < c.length; i++) {
-               if (modify[ c[i].id ]) {
-                       for (var j in modify[ c[i].id ]) {
-                               c[i][j] = modify[ c[i].id ][j];
-                       }
-               }
-       }
-       if (params) {
-               if (params.just_these) {
-                       JSAN.use('util.functional');
-                       var new_c = [];
-                       for (var i = 0; i < params.just_these.length; i++) {
-                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
-                               new_c.push( function(y){ return y; }( x ) );
-                       }
-                       c = new_c;
-               }
-               if (params.except_these) {
-                       JSAN.use('util.functional');
-                       var new_c = [];
-                       for (var i = 0; i < c.length; i++) {
-                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
-                               if (!x) new_c.push(c[i]);
-                       }
-                       c = new_c;
-               }
-
-       }
-       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+    var c = [
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'au_barcode', 'label' : commonStrings.getString('staff.card_barcode_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.card().barcode(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'usrname', 'label' : commonStrings.getString('staff.au_usrname_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.usrname(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'profile', 'label' : commonStrings.getString('staff.au_profile_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return data.hash.pgt[ my.au.profile() ].name(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'active', 'label' : commonStrings.getString('staff.au_active_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return get_bool( my.au.active() ) ? "Yes" : "No"; }
+        },
+        {
+            'persist' : 'hidden width ordinal', 'id' : 'barred', 'label' : commonStrings.getString('staff.au_barred_label'), 'flex' : 1,
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return get_bool( my.au.barred() ) ? "Yes" : "No"; }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'au_id', 'label' : document.getElementById('commonStrings').getString('staff.au_id_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.id(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'prefix', 'label' : document.getElementById('commonStrings').getString('staff.au_name_prefix_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.prefix(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'family_name', 'label' : document.getElementById('commonStrings').getString('staff.au_family_name_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.family_name(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'first_given_name', 'label' : document.getElementById('commonStrings').getString('staff.au_first_given_name_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.first_given_name(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'second_given_name', 'label' : document.getElementById('commonStrings').getString('staff.au_second_given_name_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.second_given_name(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'suffix', 'label' : document.getElementById('commonStrings').getString('staff.au_name_suffix_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.suffix(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'au_alert_message', 'label' : commonStrings.getString('staff.au_alert_message_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.alert_message(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'claims_returned_count', 'label' : commonStrings.getString('staff.au_claims_returned_count_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.claims_returned_count(); },
+            'sort_type' : 'number'
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'au_create_date', 'label' : commonStrings.getString('staff.au_create_date_label'), 'flex' : 1, 
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.au.create_date(), "%{localized}" ); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'expire_date', 'label' : commonStrings.getString('staff.au_expire_date_label'), 'flex' : 1, 
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.au.expire_date(), "%{localized_date}" ); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'home_ou', 'label' : commonStrings.getString('staff.au_home_library_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return data.hash.aou[ my.au.home_ou() ].shortname(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'home_ou_fullname', 'label' : commonStrings.getString('staff.au_home_library_fullname_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return data.hash.aou[ my.au.home_ou() ].name(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'credit_forward_balance', 'label' : commonStrings.getString('staff.au_credit_forward_balance_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.credit_forward_balance(); },
+            'sort_type' : 'money'
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'day_phone', 'label' : commonStrings.getString('staff.au_day_phone_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.day_phone(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'evening_phone', 'label' : commonStrings.getString('staff.au_evening_phone_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.evening_phone(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'other_phone', 'label' : commonStrings.getString('staff.au_other_phone_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.other_phone(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'email', 'label' : commonStrings.getString('staff.au_email_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.email(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'alias', 'label' : commonStrings.getString('staff.au_alias_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.alias(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'dob', 'label' : commonStrings.getString('staff.au_birth_date_label'), 'flex' : 1, 
+            'sort_type' : 'date',
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.au.dob(), "%{localized_date}" ); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'ident_type', 'label' : commonStrings.getString('staff.au_ident_type_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return data.hash.cit[ my.au.ident_type() ].name(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'ident_value', 'label' : commonStrings.getString('staff.au_ident_value_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.ident_value(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'ident_type2', 'label' : commonStrings.getString('staff.au_ident_type2_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return data.hash.cit[ my.au.ident_type2() ].name(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'ident_value2', 'label' : commonStrings.getString('staff.au_ident_value2_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.ident_value2(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'net_access_level', 'label' : commonStrings.getString('staff.au_net_access_level_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.net_access_level(); }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'master_account', 'label' : commonStrings.getString('staff.au_master_account_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return get_bool( my.au.master_account() ) ? "Yes" : "No"; }
+        },
+        { 
+            'persist' : 'hidden width ordinal', 'id' : 'usrgroup', 'label' : commonStrings.getString('staff.au_group_id_label'), 'flex' : 1, 
+            'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return my.au.usrgroup(); }
+        },
+    ];
+    for (var i = 0; i < c.length; i++) {
+        if (modify[ c[i].id ]) {
+            for (var j in modify[ c[i].id ]) {
+                c[i][j] = modify[ c[i].id ][j];
+            }
+        }
+    }
+    if (params) {
+        if (params.just_these) {
+            JSAN.use('util.functional');
+            var new_c = [];
+            for (var i = 0; i < params.just_these.length; i++) {
+                var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                new_c.push( function(y){ return y; }( x ) );
+            }
+            c = new_c;
+        }
+        if (params.except_these) {
+            JSAN.use('util.functional');
+            var new_c = [];
+            for (var i = 0; i < c.length; i++) {
+                var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                if (!x) new_c.push(c[i]);
+            }
+            c = new_c;
+        }
+
+    }
+    return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
 }
 
 patron.util.std_map_row_to_columns = function(error_value) {
-       return function(row,cols) {
-               // row contains { 'my' : { 'au' : {} } }
-               // cols contains all of the objects listed above in columns
-               
-               var obj = {}; obj.OpenILS = {}; 
-               JSAN.use('util.error'); obj.error = new util.error();
-               JSAN.use('OpenILS.data'); obj.OpenILS.data = new OpenILS.data(); obj.OpenILS.data.init({'via':'stash'});
-               JSAN.use('util.date'); JSAN.use('util.money');
-
-               var my = row.my;
-               var values = [];
-               var cmd = '';
-               try { 
-                       for (var i = 0; i < cols.length; i++) {
-                               switch (typeof cols[i].render) {
-                                       case 'function': try { values[i] = cols[i].render(my); } catch(E) { values[i] = error_value; obj.error.sdump('D_COLUMN_RENDER_ERROR',E); } break;
-                                       case 'string' : cmd += 'try { ' + cols[i].render + '; values['+i+'] = v; } catch(E) { values['+i+'] = error_value; }'; break;
-                                       default: cmd += 'values['+i+'] = "??? '+(typeof cols[i].render)+'"; ';
-                               }
-                       }
-                       if (cmd) eval( cmd );
-               } catch(E) {
-                       obj.error.sdump('D_WARN','map_row_to_column: ' + E);
-                       if (error_value) { value = error_value; } else { value = '   ' };
-               }
-               return values;
-       }
+    return function(row,cols) {
+        // row contains { 'my' : { 'au' : {} } }
+        // cols contains all of the objects listed above in columns
+        
+        var obj = {}; obj.OpenILS = {}; 
+        JSAN.use('util.error'); obj.error = new util.error();
+        JSAN.use('OpenILS.data'); obj.OpenILS.data = new OpenILS.data(); obj.OpenILS.data.init({'via':'stash'});
+        JSAN.use('util.date'); JSAN.use('util.money');
+
+        var my = row.my;
+        var values = [];
+        var cmd = '';
+        try { 
+            for (var i = 0; i < cols.length; i++) {
+                switch (typeof cols[i].render) {
+                    case 'function': try { values[i] = cols[i].render(my); } catch(E) { values[i] = error_value; obj.error.sdump('D_COLUMN_RENDER_ERROR',E); } break;
+                    case 'string' : cmd += 'try { ' + cols[i].render + '; values['+i+'] = v; } catch(E) { values['+i+'] = error_value; }'; break;
+                    default: cmd += 'values['+i+'] = "??? '+(typeof cols[i].render)+'"; ';
+                }
+            }
+            if (cmd) eval( cmd );
+        } catch(E) {
+            obj.error.sdump('D_WARN','map_row_to_column: ' + E);
+            if (error_value) { value = error_value; } else { value = '   ' };
+        }
+        return values;
+    }
 }
 
 patron.util.retrieve_au_via_id = function(session, id, f) {
-       JSAN.use('util.network');
-       var network = new util.network();
-       var patron_obj = network.simple_request(
-               'FM_AU_RETRIEVE_VIA_ID',
-               [ session, id ],
-               f
-       );
-       return patron_obj;
+    JSAN.use('util.network');
+    var network = new util.network();
+    var patron_obj = network.simple_request(
+        'FM_AU_RETRIEVE_VIA_ID.authoritative',
+        [ session, id ],
+        f
+    );
+    return patron_obj;
 }
 
 patron.util.retrieve_name_via_id = function(session, id) {
-       JSAN.use('util.network');
-       var network = new util.network();
-       var parts = network.simple_request(
-               'BLOB_AU_PARTS_RETRIEVE',
-               [ session, id, ['family_name', 'first_given_name', 'second_given_name', 'home_ou' ] ]
-       );
-       return parts;
+    JSAN.use('util.network');
+    var network = new util.network();
+    var parts = network.simple_request(
+        'BLOB_AU_PARTS_RETRIEVE',
+        [ session, id, ['family_name', 'first_given_name', 'second_given_name', 'home_ou' ] ]
+    );
+    return parts;
 }
 
-patron.util.retrieve_fleshed_au_via_id = function(session, id) {
-       JSAN.use('util.network');
-       var network = new util.network();
-       var patron_obj = network.simple_request(
-               'FM_AU_FLESHED_RETRIEVE_VIA_ID',
-               [ session, id ]
-       );
-       patron.util.set_penalty_css(patron_obj);
-       return patron_obj;
+patron.util.retrieve_fleshed_au_via_id = function(session, id, fields, func) {
+    JSAN.use('util.network');
+    var network = new util.network();
+    var patron_obj = network.simple_request(
+        'FM_AU_FLESHED_RETRIEVE_VIA_ID.authoritative',
+        [ session, id, fields ],
+        typeof func == 'function' ? func : null
+    );
+    if (typeof func != 'function') {
+        if (!fields) { patron.util.set_penalty_css(patron_obj); }
+        return patron_obj;
+    }
 }
 
 patron.util.retrieve_fleshed_au_via_barcode = function(session, id) {
-       JSAN.use('util.network');
-       var network = new util.network();
-       var patron_obj = network.simple_request(
-               'FM_AU_RETRIEVE_VIA_BARCODE.authoritative',
-               [ session, id ]
-       );
-       patron.util.set_penalty_css(patron_obj);
-       return patron_obj;
+    JSAN.use('util.network');
+    var network = new util.network();
+    var patron_obj = network.simple_request(
+        'FM_AU_RETRIEVE_VIA_BARCODE.authoritative',
+        [ session, id ]
+    );
+    if (typeof patron_obj.ilsevent == 'undefined') patron.util.set_penalty_css(patron_obj);
+    return patron_obj;
 }
 
 var TIME = { minute : 60, hour : 60*60, day : 60*60*24, year : 60*60*24*365 };
 
 patron.util.set_penalty_css = function(patron) {
-       try {
-                                                       removeCSSClass(document.documentElement,'PATRON_HAS_BILLS');
-                                                       removeCSSClass(document.documentElement,'PATRON_HAS_OVERDUES');
-                                                       removeCSSClass(document.documentElement,'PATRON_HAS_NOTES');
-                                                       removeCSSClass(document.documentElement,'PATRON_EXCEEDS_CHECKOUT_COUNT');
-                                                       removeCSSClass(document.documentElement,'PATRON_EXCEEDS_OVERDUE_COUNT');
-                                                       removeCSSClass(document.documentElement,'PATRON_EXCEEDS_FINES');
-                                                       removeCSSClass(document.documentElement,'NO_PENALTIES');
-                                                       removeCSSClass(document.documentElement,'ONE_PENALTY');
-                                                       removeCSSClass(document.documentElement,'MULTIPLE_PENALTIES');
-                                                       removeCSSClass(document.documentElement,'PATRON_HAS_ALERT');
-                                                       removeCSSClass(document.documentElement,'PATRON_BARRED');
-                                                       removeCSSClass(document.documentElement,'PATRON_INACTIVE');
-                                                       removeCSSClass(document.documentElement,'PATRON_EXPIRED');
-                                                       removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_DOB');
-                                                       removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_65');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_65');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_24');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_24');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_21');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_21');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_18');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_18');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_13');
-                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_13');
-                                                       removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_1');
-                                                       removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_2');
-                                                       removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_3');
-
-               JSAN.use('util.network'); var net = new util.network();
-               net.simple_request('FM_MOUS_RETRIEVE.authoritative',[ ses(), patron.id() ], function(req) {
-                       if (req.getResultObject().balance_owed() > 0) addCSSClass(document.documentElement,'PATRON_HAS_BILLS');
-               });
-               net.simple_request('FM_CIRC_COUNT_RETRIEVE_VIA_USER.authoritative',[ ses(), patron.id() ], function(req) {
-                       try {
-                               var co = req.getResultObject();
-                               if (co.overdue > 0 || co.long_overdue > 0) addCSSClass(document.documentElement,'PATRON_HAS_OVERDUES');
-                       } catch(E) {
-                               alert(E);
-                       }
-               });
-               net.simple_request('FM_AUN_RETRIEVE_ALL.authoritative',[ ses(), { 'patronid' : patron.id() } ], function(req) {
-                       var notes = req.getResultObject();
-                       if (notes.length > 0) addCSSClass(document.documentElement,'PATRON_HAS_NOTES');
-               });
-
-               /*
-               JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
-               data.last_patron = patron.id(); data.stash('last_patron');
-               */
-
-               var penalties = patron.standing_penalties();
-               for (var i = 0; i < penalties.length; i++) {
-                       /* this comes from /opac/common/js/utils.js */
-                       addCSSClass(document.documentElement,penalties[i].standing_penalty().name());
-               }
-
-               switch(penalties.length) {
-                       case 0: addCSSClass(document.documentElement,'NO_PENALTIES'); break;
-                       case 1: addCSSClass(document.documentElement,'ONE_PENALTY'); break;
-                       default: addCSSClass(document.documentElement,'MULTIPLE_PENALTIES'); break;
-               }
-
-               if (patron.alert_message()) {
-                       addCSSClass(document.documentElement,'PATRON_HAS_ALERT');
-               }
-
-               if (get_bool( patron.barred() )) {
-                       addCSSClass(document.documentElement,'PATRON_BARRED');
-               }
-
-               if (!get_bool( patron.active() )) {
-                       addCSSClass(document.documentElement,'PATRON_INACTIVE');
-               }
-
-               var now = new Date();
-               now = now.getTime()/1000;
-
-               var expire_parts = patron.expire_date().substr(0,10).split('-');
-               expire_parts[1] = expire_parts[1] - 1;
-
-               var expire = new Date();
-               expire.setFullYear(expire_parts[0], expire_parts[1], expire_parts[2]);
-               expire = expire.getTime()/1000
-
-               if (expire < now) addCSSClass(document.documentElement,'PATRON_EXPIRED');
-
-               if (patron.mailing_address()) {
-                       if (!get_bool(patron.mailing_address().valid())) {
-                               addCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
-                       }
-               }
-               if (patron.billing_address()) {
-                       if (!get_bool(patron.billing_address().valid())) {
-                               addCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
-                       }
-               }
-
-       } catch(E) {
-               dump('patron.util.set_penalty_css: ' + E + '\n');
-               alert('patron.util.set_penalty_css: ' + E + '\n');
-       }
+    try {
+        removeCSSClass(document.documentElement,'PATRON_HAS_BILLS');
+        removeCSSClass(document.documentElement,'PATRON_HAS_OVERDUES');
+        removeCSSClass(document.documentElement,'PATRON_HAS_NOTES');
+        removeCSSClass(document.documentElement,'PATRON_EXCEEDS_CHECKOUT_COUNT');
+        removeCSSClass(document.documentElement,'PATRON_EXCEEDS_OVERDUE_COUNT');
+        removeCSSClass(document.documentElement,'PATRON_EXCEEDS_FINES');
+        removeCSSClass(document.documentElement,'NO_PENALTIES');
+        removeCSSClass(document.documentElement,'ONE_PENALTY');
+        removeCSSClass(document.documentElement,'MULTIPLE_PENALTIES');
+        removeCSSClass(document.documentElement,'PATRON_HAS_ALERT');
+        removeCSSClass(document.documentElement,'PATRON_BARRED');
+        removeCSSClass(document.documentElement,'PATRON_INACTIVE');
+        removeCSSClass(document.documentElement,'PATRON_EXPIRED');
+        removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_DOB');
+        removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_65');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_65');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_24');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_24');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_21');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_21');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_18');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_18');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_13');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_13');
+        removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_1');
+        removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_2');
+        removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_3');
+
+        JSAN.use('util.network'); var net = new util.network();
+        net.simple_request('FM_MOUS_RETRIEVE.authoritative',[ ses(), patron.id() ], function(req) {
+            var summary = req.getResultObject();
+            if (summary && summary.balance_owed() > 0) addCSSClass(document.documentElement,'PATRON_HAS_BILLS');
+        });
+        net.simple_request('FM_CIRC_COUNT_RETRIEVE_VIA_USER.authoritative',[ ses(), patron.id() ], function(req) {
+            try {
+                var co = req.getResultObject();
+                if (co.overdue > 0 || co.long_overdue > 0) addCSSClass(document.documentElement,'PATRON_HAS_OVERDUES');
+            } catch(E) {
+                alert(E);
+            }
+        });
+        net.simple_request('FM_AUN_RETRIEVE_ALL.authoritative',[ ses(), { 'patronid' : patron.id() } ], function(req) {
+            var notes = req.getResultObject();
+            if (notes.length > 0) addCSSClass(document.documentElement,'PATRON_HAS_NOTES');
+        });
+
+        /*
+        JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+        data.last_patron = patron.id(); data.stash('last_patron');
+        */
+
+        var penalties = patron.standing_penalties();
+        if (!penalties) { penalties = []; }
+        for (var i = 0; i < penalties.length; i++) {
+            /* this comes from /opac/common/js/utils.js */
+            addCSSClass(document.documentElement,penalties[i].standing_penalty().name());
+        }
+
+        switch(penalties.length) {
+            case 0: addCSSClass(document.documentElement,'NO_PENALTIES'); break;
+            case 1: addCSSClass(document.documentElement,'ONE_PENALTY'); break;
+            default: addCSSClass(document.documentElement,'MULTIPLE_PENALTIES'); break;
+        }
+
+        if (patron.alert_message()) {
+            addCSSClass(document.documentElement,'PATRON_HAS_ALERT');
+        }
+
+        if (get_bool( patron.barred() )) {
+            addCSSClass(document.documentElement,'PATRON_BARRED');
+        }
+
+        if (!get_bool( patron.active() )) {
+            addCSSClass(document.documentElement,'PATRON_INACTIVE');
+        }
+
+        var now = new Date();
+        now = now.getTime()/1000;
+
+        var expire_parts = patron.expire_date().substr(0,10).split('-');
+        expire_parts[1] = expire_parts[1] - 1;
+
+        var expire = new Date();
+        expire.setFullYear(expire_parts[0], expire_parts[1], expire_parts[2]);
+        expire = expire.getTime()/1000
+
+        if (expire < now) addCSSClass(document.documentElement,'PATRON_EXPIRED');
+
+        if (patron.mailing_address() && typeof patron.mailing_address() == 'object') {
+            if (!get_bool(patron.mailing_address().valid())) {
+                addCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
+            }
+        }
+        if (patron.billing_address() && typeof patron.billing_address() == 'object') {
+            if (!get_bool(patron.billing_address().valid())) {
+                addCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
+            }
+        }
+
+    } catch(E) {
+        dump('patron.util.set_penalty_css: ' + E + '\n');
+        alert('patron.util.set_penalty_css: ' + E + '\n');
+    }
 }
 
 patron.util.merge = function(record_ids) {
@@ -707,6 +730,8 @@ patron.util.merge = function(record_ids) {
     try {
         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
         JSAN.use('util.error'); error = new util.error();
+        JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
+        var horizontal_interface = String( data.hash.aous['ui.circ.patron_summary.horizontal'] ) == 'true';
         var top_xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" >';
         top_xml += '<description>' + $("patronStrings").getString('staff.patron.usr_buckets.merge_records.merge_lead') + '</description>';
         top_xml += '<hbox>';
@@ -716,24 +741,47 @@ patron.util.merge = function(record_ids) {
                 + $("patronStrings").getString('staff.patron.usr_buckets.merge_records.cancel_button.accesskey') +'" name="fancy_cancel"/></hbox></vbox>';
 
         var xml = '<form xmlns="http://www.w3.org/1999/xhtml">';
-        xml += '<table><tr valign="top">';
-        for (var i = 0; i < record_ids.length; i++) {
+        xml += '<table>';
+
+        function table_cell_with_lead_button(id) {
+            var xml = '';
             xml += '<td><input value="' + $("patronStrings").getString('staff.patron.usr_buckets.merge_records.lead')
-            xml += '" id="record_' + record_ids[i] + '" type="radio" name="lead"';
+            xml += '" id="record_' + id + '" type="radio" name="lead"';
             xml += ' onclick="' + "try { var x = $('lead'); x.setAttribute('value',";
-            xml += record_ids[i] + '); x.disabled = false; } catch(E) { alert(E); }">';
-            xml += '</input>' + $("patronStrings").getFormattedString('staff.patron.usr_buckets.merge_records.lead_record_number',[record_ids[i]]) + '</td>';
+            xml += id + '); x.disabled = false; } catch(E) { alert(E); }">';
+            xml += '</input>' + $("patronStrings").getFormattedString('staff.patron.usr_buckets.merge_records.lead_record_number',[id]) + '</td>';
+            return xml;
+        }
+
+        var iframe_css;
+        if (!horizontal_interface) {
+            xml += '<tr valign="top">';
+            for (var i = 0; i < record_ids.length; i++) {
+                xml += table_cell_with_lead_button( record_ids[i] );
+            }
+            xml += '</tr><tr valign="top">';
+            iframe_css = 'min-height: 1000px; min-width: 300px;';
+        } else {
+            iframe_css = 'min-height: 200px; min-width: 1000px;';
         }
-        xml += '</tr><tr valign="top">';
         for (var i = 0; i < record_ids.length; i++) {
-            xml += '<td nowrap="nowrap"><iframe style="min-height: 1000px; min-width: 300px" flex="1" src="' + urls.XUL_PATRON_SUMMARY; 
+            if (horizontal_interface) {
+                xml += '<tr valign="top">' + table_cell_with_lead_button( record_ids[i] );
+            }
+            xml += '<td nowrap="nowrap"><iframe style="' + iframe_css + '" flex="1" src="' + urls.XUL_PATRON_SUMMARY; 
             xml += '?id=' + record_ids[i] + '&amp;show_name=1"/></td>';
+            if (horizontal_interface) {
+                xml += '</tr>';
+            }
+        }
+        if (!horizontal_interface) {
+            xml += '</tr>';
         }
-        xml += '</tr></table></form>';
+        xml += '</table></form>';
         JSAN.use('util.window'); var win = new util.window();
         var fancy_prompt_data = win.open(
             urls.XUL_FANCY_PROMPT,
-            'fancy_prompt', 'chrome,resizable,modal,width=750,height=500',
+            'fancy_prompt', 'chrome,resizable,modal,width=1000,height=700',
             {
                 'top_xml' : top_xml, 'xml' : xml, 'title' : $("patronStrings").getString('staff.patron.usr_buckets.merge_records.fancy_prompt_title')
             }
@@ -759,10 +807,44 @@ patron.util.merge = function(record_ids) {
         if (Number(robj) != 1) { throw(robj); }
         return fancy_prompt_data.lead;
     } catch(E) {
-               dump('patron.util.merge: ' + js2JSON(E) + '\n');
+        dump('patron.util.merge: ' + js2JSON(E) + '\n');
         try { error.standard_unexpected_error_alert('Error in patron.util.merge',E); } catch(F) { alert('patron.util.merge: ' + E + '\n'); }
         return false;
     }
 }
 
+patron.util.format_name = function(patron_obj) {
+    var patron_name = ( patron_obj.prefix() ? patron_obj.prefix() + ' ' : '') +
+        patron_obj.family_name() + ', ' +
+        patron_obj.first_given_name() + ' ' +
+        ( patron_obj.second_given_name() ? patron_obj.second_given_name() + ' ' : '' ) +
+        ( patron_obj.suffix() ? patron_obj.suffix() : ''); 
+    return patron_name;
+}
+
+patron.util.work_log_patron_edit = function(p) {
+    var error;
+    try {
+        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
+        JSAN.use('util.error'); error = new util.error();
+        error.work_log(
+            document.getElementById('patronStrings').getFormattedString(
+                'staff.circ.work_log_patron_edit.message',
+                [
+                    ses('staff_usrname'),
+                    p.family_name(),
+                    p.card().barcode()
+                ]
+            ), {
+                'au_id' : p.id(),
+                'au_family_name' : p.family_name(),
+                'au_barcode' : p.card().barcode()
+            }
+        );
+    } catch(E) {
+        error.sdump('D_ERROR','Error with work_logging in menu.js, cmd_patron_register:' + E);
+    }
+}
+
+
 dump('exiting patron/util.js\n');