added evergreen branch of user editor
authorerickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Wed, 16 Aug 2006 19:08:26 +0000 (19:08 +0000)
committererickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Wed, 16 Aug 2006 19:08:26 +0000 (19:08 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@5539 dcc99617-32d9-48b4-a31d-7c20da2025e4

Evergreen/xul/staff_client/server/patron/ue.js [new file with mode: 0644]
Evergreen/xul/staff_client/server/patron/ue.xhtml [new file with mode: 0644]
Evergreen/xul/staff_client/server/patron/ue_config.js [new file with mode: 0644]
Evergreen/xul/staff_client/server/patron/ue_ui.js [new file with mode: 0644]

diff --git a/Evergreen/xul/staff_client/server/patron/ue.js b/Evergreen/xul/staff_client/server/patron/ue.js
new file mode 100644 (file)
index 0000000..353a7f1
--- /dev/null
@@ -0,0 +1,623 @@
+var cgi                                                        = null;
+var clone                                              = false;
+var patron                                             = null;
+var counter                                            = 0;
+var identTypesCache                    = {};
+var statCatsCache                              = {};
+var surveysCache                               = {};
+var surveyQuestionsCache       = {};
+var surveyAnswersCache         = {};
+var userCache                                  = {};
+var groupsCache                                = {};
+var netLevelsCache                     = {};
+//var guardianNote                             = null; 
+
+
+/* fetch the necessary data to start off */
+function uEditInit() {
+
+       _debug('uEditInit(): ' + location.search);
+
+       cgi             = new CGI();
+       session = cgi.param('ses');
+       clone           = cgi.param('clone');
+       if(!session) throw "User session is not defined";
+
+       fetchUser(session);
+       $('uedit_user').appendChild(text(USER.usrname()));
+
+       setTimeout( function() { 
+               uEditBuild(); uEditShowPage('uedit_userid'); }, 20 );
+}
+
+/* ------------------------------------------------------------------------------ */
+/* Fetch code
+/* ------------------------------------------------------------------------------ */
+function uEditFetchIdentTypes() {
+       _debug("uEditFetchIdentTypes()");
+       var req = new Request(FETCH_ID_TYPES);
+       req.send(true);
+       return req.result();
+}
+
+function uEditFetchStatCats() {
+       _debug("uEditFetchStatCats()");
+       var req = new Request(SC_FETCH_ALL, SESSION);
+       req.send(true);
+       return req.result();
+}
+
+function uEditFetchSurveys() {
+       _debug("uEditFetchSurveys()");
+       var req = new Request(SV_FETCH_ALL, SESSION);
+       req.send(true);
+       return req.result();
+}
+
+function uEditFetchGroups() {
+       _debug("uEditFetchGroups()");
+       var req = new Request(FETCH_GROUPS);
+       req.send(true);
+       return req.result();
+}
+
+function uEditFetchNetLevels() {
+       _debug("uEditFetchNetLevels()");
+       var req = new Request(FETCH_NET_LEVELS, SESSION);
+       req.send(true);
+       return req.result();
+}
+
+/* ------------------------------------------------------------------------------ */
+
+
+
+/* fetches necessary and builds the UI */
+function uEditBuild() {
+       fetchHighestPermOrgs( SESSION, USER.id(), myPerms );
+
+       uEditBuildLibSelector();
+       patron = fetchFleshedUser(cgi.param('usr'));
+       if(!patron) patron = uEditNewPatron(); 
+       
+       uEditDraw( 
+               uEditFetchIdentTypes(),
+               uEditFetchGroups(),
+               uEditFetchStatCats(),
+               uEditFetchSurveys(),
+               uEditFetchNetLevels()
+               );
+
+       if(patron.isnew()) {
+               if(clone) uEditClone(clone);
+               else uEditCreateNewAddr();
+
+       } else {
+
+               $('ue_barcode').disabled = true;
+               unHideMe($('ue_mark_card_lost'));
+               unHideMe($('ue_reset_pw'));
+               uEditCheckEditPerm();
+       }
+
+       if(PERMS['BAR_PATRON'] == -1) 
+               $('ue_barred').disabled = true;
+}
+
+
+/* if this user does not have permission to put users into
+       the edited users group, they do not have permission to 
+       edit this user */
+function uEditCheckEditPerm() {
+
+       var perm = uEditFindGroupPerm(groupsCache[patron.profile()]);   
+       _debug("editing user with group app perm "+patron.profile()+' : '+
+               groupsCache[patron.profile()].name() +', and perm = ' + perm);
+
+       if(PERMS[perm] != -1) return;
+
+       /* we can edit our own account, but not others in our group */
+       if( patron.id() != USER.id() ){
+               _debug("we are not allowed to edit this user");
+       
+               $('ue_save').disabled = true;
+               $('ue_save_clone').disabled = true;
+       
+               uEditIterateFields(
+                       function(f) {
+                               if( f && f.widget && f.widget.node )
+                                       f.widget.node.disabled = true;
+                       }       
+               );      
+
+       }
+
+       var node = $('ue_profile').parentNode;
+       node.removeChild($('ue_profile'));
+       node.appendChild(elem('span',null,groupsCache[patron.profile()].name()));
+
+       var field = uEditFindFieldByKey('profile');
+       field.required = false;
+       removeCSSClass(field.widget.node, CSS_INVALID_DATA);
+       uEditCheckErrors();
+}
+
+
+/* creates a new patron object with card attached */
+var uEditCardVirtId = -1;
+function uEditNewPatron() {
+       var patron = new au(); 
+       patron.isnew(1);
+       patron.id(-1);
+       card = new ac();
+       card.id(uEditCardVirtId--);
+       card.isnew(1);
+       patron.card(card);
+       patron.cards([card]);
+       patron.stat_cat_entries([]);
+       patron.survey_responses([]);
+       patron.addresses([]);
+       patron.home_ou(USER.ws_ou());
+       uEditMakeRandomPw(patron);
+       return patron;
+}
+
+function uEditMakeRandomPw(patron) {
+       var rand  = Math.random();
+       rand = parseInt(rand * 10000) + '';
+       while(rand.length < 4) rand += '0';
+       appendClear($('ue_password_plain'),text(rand));
+       unHideMe($('ue_password_gen'));
+       patron.passwd(rand);
+       return rand;
+}
+
+function uEditResetPw() { 
+       var pw = uEditMakeRandomPw(patron);     
+       $('ue_password1').value = pw;
+       $('ue_password2').value = pw;
+}
+
+function uEditClone(clone) {
+
+       var cloneUser = fetchFleshedUser(clone);
+       patron.usrgroup(cloneUser.usrgroup());
+
+       if( cloneUser.day_phone() )
+               $('ue_day_phone').value = cloneUser.day_phone();
+       if( cloneUser.evening_phone() )
+               $('ue_night_phone').value = cloneUser.evening_phone();
+       if( cloneUser.other_phone() )
+               $('ue_other_phone').value = cloneUser.other_phone();
+       setSelector($('ue_org_selector'), cloneUser.home_ou());
+
+
+       setSelector($('ue_profile'), cloneUser.profile());
+
+       /* force the expire date to be set */
+       $('ue_profile').onchange();
+
+       for( var a in cloneUser.addresses() ) {
+               var addr = cloneUser.addresses()[a];
+               if( cloneUser.mailing_address && 
+                               addr.id() == cloneUser.mailing_address().id() )
+                       patron.mailing_address(addr);
+               if( cloneUser.billing_address() &&
+                               addr.id() == cloneUser.billing_address().id() )
+                       patron.billing_address(addr);
+               patron.addresses().push(addr);
+       }
+
+       uEditBuildAddrs(patron);
+}
+
+
+/* Creates a new blank address, 
+       adds it to the user and the fields array */
+var uEditVirtualAddrId = -1;
+function uEditCreateNewAddr() {
+       var addr = new aua();
+
+       addr.id(uEditVirtualAddrId--);
+       addr.isnew(1);
+       addr.usr(patron.id());
+       addr.country(defaultCountry);
+
+       if(!patron.addresses()) 
+               patron.addresses([]);
+
+       if(patron.addresses().length == 0) {
+               patron.mailing_address(addr);
+               patron.billing_address(addr);
+       }
+
+       addr.valid(1);
+       addr.within_city_limits(1);
+
+       uEditBuildAddrFields(patron, addr);
+       patron.addresses().push(addr);
+       uEditIterateFields(function(f) { uEditCheckValid(f); });
+       uEditCheckErrors();
+}
+
+
+/* kicks off the UI drawing */
+function uEditDraw(identTypes, groups, statCats, surveys, netLevels ) {
+       hideMe($('uedit_loading'));
+       unHideMe($('ue_maintd'));
+
+       dataFields = [];
+       uEditDrawIDTypes(identTypes);
+       uEditDrawGroups(groups);
+       uEditDrawStatCats(statCats);
+       uEditDrawSurveys(surveys);
+       uEditDrawNetLevels(netLevels);
+       uEditDefineData(patron);
+
+       uEditIterateFields(function(f) { uEditActivateField(f) });
+       uEditIterateFields(function(f) { uEditCheckValid(f); });
+       uEditCheckErrors();
+}
+
+
+/** Applies the event handlers and sets the data for the field */
+function uEditActivateField(field) {
+
+       if( field.widget.id ) {
+               field.widget.node = $(field.widget.id);
+
+       } else {
+               field.widget.node = 
+                       $n(field.widget.base, field.widget.name);
+       }
+
+       uEditSetOnchange(field);
+
+       if(field.widget.onblur) {
+               field.widget.node.onblur = 
+                       function() { field.widget.onblur(field); };
+       }
+
+       field.widget.node.disabled = field.widget.disabled;
+       if(field.object == null) return;
+       var val = field.object[field.key]();
+       if(val == null) return;
+
+       if( field.widget.type == 'input' )
+               field.widget.node.value = val;
+
+       if( field.widget.type == 'select' )
+               setSelector(field.widget.node, val);
+
+       if( field.widget.type == 'checkbox' )
+               field.widget.node.checked = 
+                       (val && val != 'f') ? true : false;
+
+       if( field.widget.onload ) 
+               field.widget.onload(val);
+}
+
+
+/* set up the onchange event for the field */
+function uEditSetOnchange(field) {
+       var func = function() {uEditOnChange( field );}
+       field.widget.node.onchange = func;
+
+       if(field.widget.type != 'select')
+               field.widget.node.onkeyup = func;
+}
+
+/* find the current value of the field object's widget */
+function uEditNodeVal(field) {
+       if(field.widget.type == 'input')
+               return field.widget.node.value;
+
+       if(field.widget.type == 'checkbox')
+               return field.widget.node.checked;
+
+       if(field.widget.type == 'select')
+               return getSelectorVal(field.widget.node);
+}
+
+
+/* update a field value */
+function uEditOnChange(field) {
+
+       var newval = uEditNodeVal(field);
+       field.object[field.key](newval);
+       field.object.ischanged(1);
+
+       if(field.widget.onpostchange)
+               field.widget.onpostchange(field, newval);
+
+
+       uEditIterateFields(function(f) { uEditCheckValid(f); });
+       uEditCheckErrors();
+}
+
+
+function uEditCheckValid(field) {
+       var newval = uEditNodeVal(field);
+
+       if(newval) {
+
+               if(field.widget.regex) { 
+                       if(newval.match(field.widget.regex)) 
+                               removeCSSClass(field.widget.node, CSS_INVALID_DATA);
+                       else
+                               addCSSClass(field.widget.node, CSS_INVALID_DATA);
+
+               } else {
+                       removeCSSClass(field.widget.node, CSS_INVALID_DATA);
+               }
+
+       } else {
+
+               if(field.required) {
+                       addCSSClass(field.widget.node, CSS_INVALID_DATA);
+
+               } else {
+                       removeCSSClass(field.widget.node, CSS_INVALID_DATA);
+               }
+       }
+}
+
+/* find a field object by object key */
+function uEditFindFieldByKey(key) {
+       var fields = grep( dataFields,
+               function(item) { return (item.key == key); });
+       return (fields) ? fields[0] : null;
+}
+
+/* find a list of fields by object key */
+function uEditFindFieldsByKey(key) {
+       return grep( dataFields,
+               function(item) { return (item.key == key); });
+}
+
+/* find a field object by widget id */
+function uEditFindFieldByWId(id) {
+       var fields = grep( dataFields,
+               function(item) { return (item.widget.id == id); });
+       return (fields) ? fields[0] : null;
+}
+
+
+function uEditIterateFields(callback) {
+       for( var f in dataFields ) 
+               callback(dataFields[f]);
+}
+
+
+function uEditGetErrorStrings() {
+       var errors = [];
+       uEditIterateFields(
+               function(field) { 
+                       if(field.errkey) {
+                               if( field.widget.node.className.indexOf(CSS_INVALID_DATA) != -1) {
+                                       var str = $(field.errkey).innerHTML;
+                                       if(str) errors.push(str);
+                               }
+                       }
+               }
+       );
+
+       /* munge up something for all of the required surveys 
+               (which are not registered with the fields) */
+       if( patron.isnew() ) {
+               var sel = $('ue_survey_table');
+
+               if( sel ) {
+                       var rows = sel.getElementsByTagName('tr');
+
+                       for( var r in rows ) {
+               
+                               var row = rows[r];
+                               var sel = $n(row, 'ue_survey_answer');
+                               if(!sel) continue;
+                               var qstn = row.getAttribute('question');
+               
+                               if(qstn) {
+                                       qstn            = surveyQuestionsCache[qstn];
+                                       survey  = surveysCache[qstn.survey()];
+                                       var val = getSelectorVal(sel);
+                                       if(!val && isTrue(survey.required()))
+                                               errors.push($('ue_bad_survey').innerHTML + ' : ' + qstn.question());
+                               }
+                       }
+               }
+       }
+
+       /* ------------------------------------------------------------ */
+
+       if(errors[0]) return errors;
+       return null;
+}
+
+function uEditAlertErrors() {
+       var errors = uEditGetErrorStrings();
+       if(!errors) return false;
+       alert(errors.join("\n"));
+       return true;
+}
+
+
+/* send the user to the database */
+function uEditSaveUser(cloneme) {
+
+       if(uEditGetErrorStrings()) {
+               uEditAlertErrors();
+               return;
+       }
+
+       /* null is unique in the db, but '' is not */
+       if( ! patron.ident_value() ) patron.ident_value(null);
+       //if( ! patron.ident_type2() ) patron.ident_type2(null);
+       if( ! patron.ident_value2() ) patron.ident_value2(null);
+       patron.ident_type2(null);
+
+       if(! patron.dob() ) patron.dob(null);
+
+       var req = new Request(UPDATE_PATRON, SESSION, patron);
+       req.alertEvent = false;
+       req.send(true);
+       var newuser = req.result();
+
+       var evt;
+       if( (evt = checkILSEvent(newuser)) || ! newuser ) {
+               if(evt) alert(js2JSON(newuser));
+               return;
+       } 
+
+       alert($('ue_success').innerHTML);
+
+       if(cloneme) {
+               /* if the user we just created was a clone, and we want to clone it,
+               we really want to clone the original */
+               if( clone ) cloneme = clone;
+               else cloneme = newuser.id();
+       }
+
+       if (window.xulG && typeof window.xulG.on_save == 'function') {
+               _debug("xulG funcs defined...");
+               if( !patron.isnew() && cloneme ) {
+                       _debug("calling spawn_editor to clone user...");
+                       window.xulG.spawn_editor({ses:cgi.param('ses'),clone:cloneme});
+               }
+               window.xulG.on_save(newuser, cloneme); 
+
+       } else {
+
+               _debug("xulG funcs not defined, refreshing page..");
+               var href = location.href;
+
+               href = href.replace(/\&?usr=\d+/, '');
+               href = href.replace(/\&?clone=\d+/, '');
+
+               if( cloneme ) href += '&clone=' + cloneme;
+               location.href = href;
+       }
+}
+
+function uEditCancel() {
+       var href = location.href;
+       href = href.replace(/\&?usr=\d+/, '');
+       href = href.replace(/\&?clone=\d+/, '');
+       var id = cgi.param('usr')
+       /* reload the current user if available */
+       if( id ) href += "&usr=" + id;
+       location.href = href;
+}
+
+
+var uEditDupHashes = {};
+var uEditDupTemplate;
+
+function uEditRunDupeSearch(type, search_hash) {
+
+       if(!patron.isnew()) return;
+
+       _debug('dup search: ' + js2JSON(search_hash));
+
+       var req = new Request(PATRON_SEARCH, SESSION, search_hash);
+
+       var container = $('dup_div_container');
+       if(!uEditDupTemplate)
+               uEditDupTemplate = container.removeChild($('dup_div'));
+
+       /* clear any existing dups for this type */
+       iterate( container.getElementsByTagName('div'),
+               function(d) {
+                       if( d.getAttribute('type') == type ) {
+                               container.removeChild(d)
+                               return;
+                       }
+               }
+       );
+
+       req.callback(
+               function(r) {
+                       uEditHandleDupResults( r.getResultObject(), search_hash, type, container );
+               }
+       );
+       req.send();
+}
+
+
+function uEditHandleDupResults(ids, search_hash, type, container) {
+
+       _debug('dup search results: ' + js2JSON(ids));
+
+       if(!(ids && ids[0]))  /* no results */
+               return uEditDupHashes[type] = null;
+
+       /* add a dup link to the UI and plug in the data */
+       var node = uEditDupTemplate.cloneNode(true);
+       container.appendChild(node);
+       node.setAttribute('type', type);
+
+       var link = $n(node, 'link');
+       link.setAttribute('type', type);
+       unHideMe(link);
+       $n(node,'count').appendChild(text(ids.length));
+
+       for( var o in search_hash ) 
+               $n(node, 'data').appendChild(
+                       text(search_hash[o].value + ' '));
+
+       uEditDupHashes[type] = search_hash;
+
+       switch(type) {
+               case 'ident' :
+                       if(confirm($('ue_dup_ident1').innerHTML)) 
+                               uEditShowSearch(null, type);
+                       break;
+       }
+}
+
+
+function uEditShowSearch(link,type) {
+       if(!type) type = link.getAttribute('type');
+       if(window.xulG)
+               window.xulG.spawn_search(uEditDupHashes[type]); 
+       else alert('Search would be:\n' + js2JSON(uEditDupHashes[type]));
+}
+
+function uEditMarkCardLost() {
+
+       for( var c in patron.cards() ) {
+
+               var card = patron.cards()[c];
+               if( patron.card().id() == card.id() ) {
+
+                       /* de-activite the current card */
+                       card.ischanged(1);
+                       card.active(0);
+
+                       /* create a new card for the patron */
+                       var newcard = new ac();
+                       newcard.id(uEditCardVirtId--);
+                       newcard.isnew(1);
+                       patron.card(newcard);
+                       patron.cards().push(newcard);
+
+
+                       /* reset the widget */
+                       var field = uEditFindFieldByWId('ue_barcode');
+                       field.widget.node.disabled = false;
+                       field.widget.node.value = "";
+                       field.widget.node.onchange();
+                       field.object = newcard;
+               }
+       }
+}
+
+
+function compactArray(arr) {
+       var a = [];
+       for( var i = 0; arr && i < arr.length; i++ ) {
+               if( arr[i] != null )
+                       a.push(arr[i]);
+       }
+       return a;
+}
diff --git a/Evergreen/xul/staff_client/server/patron/ue.xhtml b/Evergreen/xul/staff_client/server/patron/ue.xhtml
new file mode 100644 (file)
index 0000000..552a237
--- /dev/null
@@ -0,0 +1,998 @@
+<?xml version='1.0'?>
+
+<!DOCTYPE html PUBLIC 
+       "-//W3C//DTD XHTML 1.0 Transitional//EN" 
+       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.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>Evergreen: User Editor</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/Cookie.js'> </script>
+       
+               <script language='javascript' src='/opac/common/js/slimtree.js'> </script>
+               <script language='javascript' src='/opac/common/js/JSON.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/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'>
+                       .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>
+
+       <body onload='uEditInit();'>
+
+       <center>
+
+               <h2>Evergreen User Editor</h2>
+
+               <div style='position:absolute; top: 5px; right: 5px;'>
+                       <span>Welcome </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>Note: required or invalid fields are </span>
+                                                       <span style='border-bottom: 2px solid red;'>marked with color</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();'>
+                                                       View Errors
+                                               </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");'>1. User Identification</a>
+                                                                       </td>
+                                                               </tr>
+                                                               <tr>
+                                                                       <td id='uedit_contact_info_label' class='main_nav_link'>        
+                                                                               <a href='javascript:uEditShowPage("uedit_contact_info");'>2. Contact Info</a>
+                                                                       </td>
+                                                               </tr>
+                                                               <tr>
+                                                                       <td id='uedit_addresses_label' class='main_nav_link'>           
+                                                                               <a href='javascript:uEditShowPage("uedit_addresses");'>3. Addresses</a>
+                                                                       </td>
+                                                               </tr>
+                                                               <tr>
+                                                                       <td id='uedit_groups_label' class='main_nav_link'>                      
+                                                                               <a href='javascript:uEditShowPage("uedit_groups");'>4. Groups and Permissions</a>
+                                                                       </td>
+                                                               </tr>
+                                                               <tr>
+                                                                       <td id='uedit_stat_cats_label' class='main_nav_link'>           
+                                                                               <a href='javascript:uEditShowPage("uedit_stat_cats");'>5. Statistical Categories</a>
+                                                                       </td>
+                                                               </tr>
+                                                               <tr>
+                                                                       <td id='uedit_surveys_label' class='main_nav_link'>                     
+                                                                               <a href='javascript:uEditShowPage("uedit_surveys");'>6. Surveys</a>
+                                                                       </td>
+                                                               </tr>
+                                                               <tr>
+                                                                       <td id='uedit_finalize_label' class='main_nav_link'>                    
+                                                                               <a href='javascript:uEditShowPage("uedit_finalize");'>7. Finish</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>Loading data...</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);'>
+                                                                       Found <b name='count'/> possible duplicate patron(s):
+                                                                       <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'>Barcode</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();'>Mark Lost</button>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr class='required_field'>
+                                                                               <td><div class='wide right'>Username</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'>Password</div></td>
+                                                                               <td>
+                                                                                       <div class='wide left'>
+                                                                                               <input type='password' id='ue_password1'/>
+                                                                                               <button class='hide_me' onclick='uEditResetPw();' id='ue_reset_pw'>Reset</button>
+                                                                                               <span style='padding-left: 10px;' class='hide_me' id='ue_password_gen'>
+                                                                                                       Password: 
+                                                                                                       <span style='text-decoration:underline;' id='ue_password_plain'/>
+                                                                                               </span>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr class='required_field'>
+                                                                               <td><div class='wide right'>Verify Password</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'>First Name</div></td>
+                                                                               <td><div class='wide left'><input type='text' id='ue_firstname'/></div></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <td><div class='wide right'>Middle Name</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'>Last Name</div></td>
+                                                                               <td><div class='wide left'><input type='text' id='ue_lastname'/></div></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <td><div class='wide right'>Suffix</div></td>
+                                                                               <td><div class='wide left'>
+                                                                                       <input type='text' id='ue_suffix'/>
+                                                                                       <select id='ue_suffix_selector' style='width: 6em;'
+                                                                                               onclick='$("ue_suffix").value = this.options[this.selectedIndex].value'
+                                                                                               onchange='$("ue_suffix").value = this.options[this.selectedIndex].value'>
+                                                                                               <option value=''>- Pick -</option>
+                                                                                               <option value='Jr'>Jr</option>
+                                                                                               <option value='Sr'>Sr</option>
+                                                                                               <option value='II'>II</option>
+                                                                                               <option value='III'>III</option>
+                                                                                               <option value='AA'>AA</option>
+                                                                                               <option value='AS'>AS</option>
+                                                                                               <option value='AAS'>AAS</option>
+                                                                                               <option value='BA'>BA</option>
+                                                                                               <option value='BS'>BS</option>
+                                                                                               <option value='CFPIM'>CFPIM</option>
+                                                                                               <option value='CPA'>CPA</option>
+                                                                                               <option value='CPIM'>CPIM</option>
+                                                                                               <option value='CPM'>CPM</option>
+                                                                                               <option value='CXE'>CXE</option>
+                                                                                               <option value='DC'>DC</option>
+                                                                                               <option value='DDS'>DDS</option>
+                                                                                               <option value='DO '>DO</option>
+                                                                                               <option value='DPM'>DPM</option>
+                                                                                               <option value='DVM'>DVM</option>
+                                                                                               <option value='Esq'>Esq</option>
+                                                                                               <option value='FACAAI'>FACAAI</option>
+                                                                                               <option value='FACP'>FACP</option>
+                                                                                               <option value='FACS'>FACS</option>
+                                                                                               <option value='FACEP'>FACEP</option>
+                                                                                               <option value='FCP'>FCP</option>
+                                                                                               <option value='FICS'>FICS</option>
+                                                                                               <option value='GYN'>GYN</option>
+                                                                                               <option value='JD'>JD</option>
+                                                                                               <option value='LPN'>LPN</option>
+                                                                                               <option value='MA'>MA</option>
+                                                                                               <option value='MCSE'>MCSE</option>
+                                                                                               <option value='MD'>MD</option>
+                                                                                               <option value='MS'>MS</option>
+                                                                                               <option value='NMD'>NMD</option>
+                                                                                               <option value='OB'>OB</option>
+                                                                                               <option value='PhD'>PhD</option>
+                                                                                               <option value='RN'>RN</option>
+                                                                                       </select>
+                                                                               </div></td>
+                                                                       </tr>
+                                                                       <tr class='required_field'>
+                                                                               <td><div class='wide right'>Date of Birth</div></td>
+                                                                               <td>
+                                                                                       <div class='wide left'>
+       
+                                                                                               <input type='text' id='ue_dob' size='10' maxlength='10' 
+                                                                                                       onfocus='/*$("ue_dob_trigger").onclick(event);*/'>1980-01-01</input>
+       
+                                                                                               <button style='padding: 0px;' id='ue_dob_trigger'>
+                                                                                                       <img src="/opac/common/js/jscalendar/img.gif" 
+                                                                                                               style="cursor: pointer; border: 1px solid red; padding: 0px; margin: -3px;" 
+                                                                                                               title="Date selector"
+                                                                                                               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_dob",                             // id of the input field
+                                                                                                               ifFormat                : "%Y-%m-%d",                   // format of the input field
+                                                                                                               button          : "ue_dob_trigger",  // trigger for the calendar (button ID)
+                                                                                                               align                   : "Tl",                                 // alignment (defaults to "Bl")
+                                                                                                               singleClick     : true
+                                                                                                       });
+                                                                                               </script>
+       
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr class='required_field'>
+                                                                               <td><div class='wide right'>Primary Identification Type</div></td>
+                                                                               <td><div class='wide left'>
+                                                                                               <select id='ue_primary_ident_type'>
+                                                                                                       <option value=''> -- Required -- </option>
+                                                                                               </select>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr class='required_field'>
+                                                                               <td><div class='wide right'>Primary Identification</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'>
+                                                                                                       (XXX-YY-ZZZZ)
+                                                                                               </span>
+                                                                                               <span id='primary_ident_dl_help' 
+                                                                                                       style='padding-left: 2px; font-size: 8pt;' class='hide_me'>
+                                                                                                       (GA-123456789)
+                                                                                               </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'>Parent / Guardian</div></td>
+                                                                               <td>
+                                                                                       <div class='wide left'>
+                                                                                               <input type='text' id='ue_secondary_ident'/>
+                                                                                       </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'>Email Address</div></td>
+                                                                               <td><div class='wide left'><input type='text' id='ue_email' size='32'/></div></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <td><div class='wide right'>Daytime Phone</div></td>
+                                                                               <td>
+                                                                                       <div class='wide left'>
+                                                                                               <input class='pad' type='text' id='ue_day_phone' size='18'/>
+                                                                                               <span style='font-size: 9pt;'> Example: 123-456-7890 or 123-456-7890 ex123</span>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <td><div class='wide right'>Evening Phone</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'>Other/Cell Phone</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'>Home Library</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>Address</td>
+                                                                               <td>Within City Limits</td>
+                                                                               <td>Valid</td>
+                                                                               <td>Mailing Address</td>
+                                                                               <td>Physical Address</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>
+                                                                                                                               Address is owned by
+                                                                                                                               <span name='addr_owner_name'/>
+                                                                                                                               <span name='owner_link_div'>
+                                                                                                                                       (<a name='addr_owner' href='javascript:void(0);'>Edit</a>)
+                                                                                                                               </span>
+                                                                                                                       </div>
+                                                                                                               </td>
+                                                                                                       </tr>
+                                                                                                       <tr>
+                                                                                                               <td><div class='wide right'>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'>Zip</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'>Street 1</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'>Street 2</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'>City</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'>County</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'>State</div></td>
+                                                                                                               <td colspan='3'>
+                                                                                                                       <div class='wide left'>
+                                                                                                                               <input type='text' name='ue_addr_state' size='2' maxlength='2'/>
+                                                                                                                       </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'>Country</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='Delete this Address'/>
+                                                                                                                               <span style='padding-left: 10px;'> </span>
+                                                                                                                               <input type='submit' name='ue_addr_detach' 
+                                                                                                                                       value='Detach this Address' class='hide_me'/>
+                                                                                                                       </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='Create a New Address' 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'>Profile Group</div></td>
+                                                                               <td>
+                                                                                       <div class='wide left'>
+                                                                                               <select id='ue_profile' class='select_big'>
+                                                                                                       <option value=''> -- Required -- </option>
+                                                                                               </select>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr class='required_field'>
+                                                                               <td><div class='wide right'>Account Expiration Date</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="Date selector"
+                                                                                                               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>
+                                                                               <td><div class='wide right'>Internet Access Level</div></td>
+                                                                               <td>
+                                                                                       <div class='wide left'>
+                                                                                               <select id='ue_net_level'>
+                                                                                                       <option value=''> -- None Selected -- </option>
+                                                                                               </select>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <td><div class='wide right'>Active</div></td>
+                                                                               <td>
+                                                                                       <div class='wide left'>
+                                                                                               <input id='ue_active' type='checkbox' checked='checked'/>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <td><div class='wide right'>Barred</div></td>
+                                                                               <td>
+                                                                                       <div class='wide left'>
+                                                                                               <input id='ue_barred' type='checkbox'/>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <td><div class='wide right'>Set as Family/Group Lead Account</div></td>
+                                                                               <td>
+                                                                                       <div class='wide left'>
+                                                                                               <input id='ue_group_lead' type='checkbox'/>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <td><div class='wide right'>Claims Returned Count</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='Reset'/>
+                                                                                       </div>
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <td><div class='wide right'>Alert Message</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='Clear' 
+                                                                                                               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>Stat Cat Name</td>
+                                                                               <td>Owner</td>
+                                                                               <td>Value</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=''> -- None Selected -- </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>No surveys have been created for this location.</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=''> -- None Selected -- </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;'>
+                                                                       You are now ready to save the user to the database.  <br/>
+                                                                       To view or print a summary of the changes, click on the "View Summary" link.  <br/>
+                                                                       To save the user, click on the 'Save User' button.
+                                                               </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='Save User' onclick='uEditSaveUser();'/>
+                                                               <input style='margin-left: 5px; margin-right: 5px;' id='ue_save_clone'
+                                                                       type='submit' value='Save and Clone User' onclick='uEditSaveUser(true);'/>
+                                                               <button style='margin-left: 5px; margin-right: 5px;' 
+                                                                       onclick='if(confirm($("ue_cancel_confirm").innerHTML)) uEditCancel();'>Cancel</button>
+                                                       </div>
+                                               </div>
+                                       </td>
+                               </tr>
+
+                               <tr>
+                                       <td colspan='2'>
+                                               <!-- ************************************************************** -->
+                                               <!-- Bottome 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()'>&lt;&lt;Back</a>
+                                                                       </td>
+                                                                       <td width='40%'>
+                                                                               <a id='ue_fwd' class='nav_link' 
+                                                                                       href='javascript:uEditNext()'>Forward&gt;&gt;</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>User Summary Information (Deleted items are marked in</span>
+                                               <span class='deleted'>color</span><span>)</span>
+                                       </td>
+                               </tr>
+                       </thead>
+                       <tbody name='ue_summary_page_tbody'>
+
+                               <tr>
+
+                                       <td colspan='2' align='center'>
+                                               <input style='margin-right: 15px;' type='submit' value='Print Page' onclick='window.print();'/>
+                                               <input style='margin-left: 15px;' type='submit' value='Return to Editor' 
+                                                       onclick=' unHideMe($("main_div_container")); 
+                                                               hideMe($("summary_div_container"));'/>
+                                       </td>
+                               </tr>
+
+                               <tr><td>Barcode</td><td id='ue_summary_barcode'/></tr>
+                               <tr><td>Username</td><td id='ue_summary_usrname'/></tr>
+                               <tr><td>First Name</td><td id='ue_summary_first_given_name'/></tr>
+                               <tr><td>Middle Name</td><td id='ue_summary_second_given_name'/></tr>
+                               <tr><td>Last Name</td><td id='ue_summary_family_name'/></tr>
+                               <tr><td>Suffix</td><td id='ue_summary_suffix'/></tr>
+                               <tr><td>Date of Birth</td><td id='ue_summary_dob'/></tr>
+                               <tr><td>Primary Identification Type</td><td id='ue_summary_ident_type'/></tr>
+                               <tr><td>Primary Identification</td><td id='ue_summary_ident_value'/></tr>
+                               <tr><td>Secondary Identification Type</td><td id='ue_summary_ident_type2'/></tr>
+                               <tr><td>Secondary Identification</td><td id='ue_summary_ident_value2'/></tr>
+                               <tr><td>Email Address</td><td id='ue_summary_email'/></tr>
+                               <tr><td>Day Phone</td><td id='ue_summary_day_phone'/></tr>
+                               <tr><td>Evening Phone</td><td id='ue_summary_evening_phone'/></tr>
+                               <tr><td>Other Phone</td><td id='ue_summary_other_phone'/></tr>
+                               <tr><td>Home Library</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>Addresses</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>Address Label</b></td><td name='label'/>
+                                                                                                       <td><b>Zip Code</b></td><td name='zip'/>
+                                                                                               </tr>
+                                                                                               <tr>
+                                                                                                       <td><b>Street1</b></td><td name='street1'/>
+                                                                                                       <td><b>Country</b></td><td name='country'/>
+                                                                                               </tr>
+                                                                                               <tr>
+                                                                                                       <td><b>Street2</b></td><td name='street2'/>
+                                                                                                       <td><b>Mailing</b></td><td name='mailing'/>
+                                                                                               </tr>
+                                                                                               <tr>
+                                                                                                       <td><b>City</b></td><td name='city'/>
+                                                                                                       <td><b>Billing</b></td><td name='billing'/>
+                                                                                               </tr>
+                                                                                               <tr>
+                                                                                                       <td><b>County</b></td><td name='county'/>
+                                                                                                       <td><b>Valid</b></td><td name='valid'/>
+                                                                                               </tr>
+                                                                                               <tr>
+                                                                                                       <td><b>State</b></td><td name='state'/>
+                                                                                                       <td><b>Within City Limits</b></td><td name='incorporated'/>
+                                                                                               </tr>
+                                                                                       </tbody>
+                                                                               </table>
+                                                                       </td>
+                                                               </tr>
+                                                       </tbody>
+                                               </table>
+                                       </td>
+                               </tr>
+                               <tr><td>Profile</td><td id='ue_summary_profile'/></tr>
+                               <tr><td>Active</td><td id='ue_summary_active'/></tr>
+                               <tr><td>Barred</td><td id='ue_summary_barred'/></tr>
+                               <tr><td>Expire Date</td><td id='ue_summary_expire_date'/></tr>
+                               <tr><td>Family Lead Account</td><td id='ue_summary_master_account'/></tr>
+                               <tr><td>Claims Returned Count</td><td id='ue_summary_claims_returned_count'/></tr>
+                               <tr><td>Alert Message</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'>Statistical Categories</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>Survey</td><td>Question</td><td>Answer</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='Print Page' onclick='window.print();'/>
+                                               <input style='margin-left: 15px;' type='submit' value='Return to Editor' 
+                                                       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'>The date of birth field is not formatted correctly.  We're expecting YYYY-MM-DD</span>
+               <span id='ue_bad_username'>Username is invalid</span>
+               <span id='ue_bad_password'>Passwords do not match or are invalid</span>
+               <span id='ue_bad_firstname'>First name is invalid</span>
+               <span id='ue_bad_middlename'>Middle name is invalid</span>
+               <span id='ue_bad_lastname'>Last name is invalid</span>
+               <span id='ue_bad_barcode'>Barcode is invalid</span>
+               <span id='ue_duplicate_barcode'>The selected barcode already exists in the database</span>
+               <span id='ue_new_barcode_warn'>
+                       This will de-activate the existing barcode for this user!  If you wish to continue, 
+                       enter the new barcode below.  Otherwise, click the Cancel button.
+               </span>
+               <span id='ue_no_ident'>You must select at least one type of identification</span>
+               <span id='ue_bad_ident_dl'>Invalid drivers license. Should be STATE-NUMBER</span>
+               <span id='ue_bad_ident_ssn'>Invalid social security number.  Format should be 111-22-3333</span>
+               <span id='ue_bad_email'>The email addresses is not valid</span>
+               <span id='ue_bad_phone'>An invalid phone number was entered</span>
+               <span id='ue_no_profile'>A profile group must be selected</span>
+               <span id='ue_bad_expire'>The user expiration date is invalid.  We're expecting YYYY-MM-DD</span>
+               <span id='ue_bad_claims_returned'>The claims returned count is invalid</span>
+               <span id='ue_no_profile'>A profile group must be selected</span>
+               <span id='ue_unknown_error'>An unknown formatting error occurred</span>
+               <span id='ue_bad_addr_label'>Address label is invalid</span>
+               <span id='ue_bad_addr_street'>Address street is invalid</span>
+               <span id='ue_bad_addr_city'>Address city is invalid</span>
+               <span id='ue_bad_addr_county'>Address county is invalid</span>
+               <span id='ue_bad_addr_state'>Address state is invalid</span>
+               <span id='ue_bad_addr_country'>Address country is invalid</span>
+               <span id='ue_bad_addr_zip'>Address zip is invalid</span>
+               <span id='ue_bad_survey'>Required survey is unanswered</span>
+               <span id='ue_delete_addr_warn'>
+                       This will remove this address from the user.  
+                       Are you sure you wish to continue?
+               </span>
+               <span id='yes'>Yes</span>
+               <span id='no'>No</span>
+               <span id='ue_summary_window'>Patron Summary</span>
+               <span id='ue_success'>User update succeeded</span>
+               <span id='ue_dup_ident1'>
+                       A user already exists with the primary identification provided.  
+                       Do you wish to view the duplicate record now?
+               </span>
+               <span id='ue_dup_username'>
+                       The selected username is in use by another user.  
+                       Please choose a different username.
+               </span>
+               <span id='ue_dup_barcode'>
+                       The selected barcode is in use by another user.  
+                       Please choose a different barcode.
+               </span>
+               <span class='hide_me' id='ue_cancel_confirm'>
+                       Are you sure you wish to cancel this editing session?
+                       Canceling will destroy any unsaved changes you have made thus far to the user.
+               </span>
+               <span class='hide_me' id='ue_juv_guardian'>
+                       This patron is under 18 years of age.  Please enter the name 
+                       of the parent or guardian for this patron.
+               </span>
+               <span class='hide_me' id='ue_bad_date'>
+                       The date provided is either in the future or invalid.  We're expecting YYYY-MM-DD
+               </span>
+               <span class='hide_me' id='ue_made_barred'>
+                       Please add a note to the patron's alert message explaining why the patron is barred.
+               </span>
+
+       </div>
+
+       </body>
+</html>
+
diff --git a/Evergreen/xul/staff_client/server/patron/ue_config.js b/Evergreen/xul/staff_client/server/patron/ue_config.js
new file mode 100644 (file)
index 0000000..9c7b54b
--- /dev/null
@@ -0,0 +1,1061 @@
+/* -----------------------------------------------------------------------
+       ----------------------------------------------------------------------- */
+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 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             = 'GA';
+const defaultCountry           = 'USA';
+const defaultNetAccess = 'None';
+const CSS_INVALID_DATA = 'invalid_value';
+const ADULT_AGE                        = 18;
+//const GUARDIAN_NOTE          = 'SYSTEM: Parent/Guardian';
+
+/* if they don't have these perms, they shouldn't be here */
+var myPerms = [ 
+       'BAR_PATRON',
+       'group_application.user',
+       'group_application.user.patron',
+       'group_application.user.staff',
+       'group_application.user.staff.circ',
+       'group_application.user.staff.cat',
+       'group_application.user.staff.admin.global_admin',
+       'group_application.user.staff.admin.local_admin',
+       'group_application.user.staff.admin.lib_manager',
+       'group_application.user.staff.cat.cat1',
+       'group_application.user.staff.supercat',
+       'group_application.user.sip_client',
+       'group_application.user.vendor'
+       ];
+
+var dataFields;
+const numRegex         = /^\d+$/;
+const wordRegex        = /^\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}(| ex\d+)$/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 && 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;
+       var req = new Request(CHECK_BARCODE, SESSION, barcode);
+       req.callback( 
+               function(r) {
+                       var res = r.getResultObject();
+                       if( res && res != patron.id() ) {
+                               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   : wordRegex,
+                               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+'$');
+                               }
+                       }
+               },
+               {
+                       required : true,
+                       object  : patron,
+                       key             : 'first_given_name',
+                       errkey  : 'ue_bad_firstname',
+                       widget  : {
+                               id              : 'ue_firstname',
+                               regex   : nonumRegex,
+                               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   : nonumRegex,
+                               type    : 'input'
+                       }
+               },
+               {
+                       required : true,
+                       object  : patron,
+                       key             : 'family_name',
+                       errkey  : 'ue_bad_lastname',
+                       widget  : {
+                               id              : 'ue_lastname',
+                               regex   : nonumRegex,
+                               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             : '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           :  phoneRegex,
+                       }
+               },
+               {
+                       required : false,
+                       object  : patron,
+                       key             : 'evening_phone',
+                       errkey  : 'ue_bad_phone',
+                       widget  : {
+                               id                      : 'ue_night_phone',
+                               type            : 'input',
+                               regex           :  phoneRegex,
+                       }
+               },
+               {
+                       required : false,
+                       object  : patron,
+                       key             : 'other_phone',
+                       errkey  : 'ue_bad_phone',
+                       widget  : {
+                               id                      : 'ue_other_phone',
+                               type            : 'input',
+                               regex           :  phoneRegex,
+                       }
+               },
+               {
+                       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             : '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);
+
+                                       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;
+                               }
+                       }
+               },
+               {
+                       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,
+                       }
+               },
+               {
+                       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());
+                               }
+                       )
+               );
+
+               /* 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());
+                                       }
+                               )
+                       );
+
+               } else {
+                       address.isdeleted(1);
+               }
+       }
+
+       tbody.removeChild(row);
+
+       var bid = patron.billing_address();
+       bid = (typeof bid == 'object') ? bid.id() : bid;
+
+       var mid = patron.mailing_address();
+       mid = (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 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);
+
+       $n(row, 'ue_addr_delete').onclick = 
+               function() { uEditDeleteAddr(tbody, row, address); }
+
+       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   : zipRegex,
+                               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');
+                                                       if(!state.value) {
+                                                               state.value = info.state;
+                                                               state.onchange();
+                                                       }
+                                                       if(!county.value) {
+                                                               county.value = info.county;
+                                                               county.onchange();
+                                                       }
+                                                       if(!city.value) {
+                                                               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);
+                                               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 {
+                       
+                                       link.onclick = 
+                                               function() { window.xulG.spawn_editor({ses:cgi.param('ses'),usr:id}) };
+                               
+                                       if( 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);
+
+       /* don't bother if the data isn't valid */
+       if(!dob || !dob.match(field.widget.regex)) 
+               return;
+
+       if( dob == __lastdob ) return;
+
+       __lastdob = dob;
+
+       var parts = dob.split(/-/);
+       var d = new Date( parts[0], parts[1] - 1, parts[2] );
+
+       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();
+       base.setYear( today.getYear() + 1900 - ADULT_AGE );
+
+       /* patron is at least 18 */
+
+       var f = uEditFindFieldByKey('ident_value2');
+
+       if( dob < base ) { /* patron is of age */
+               f.required = false;
+               hideMe(f.widget.node.parentNode.parentNode.parentNode);
+               return;
+       }
+
+       unHideMe(f.widget.node.parentNode.parentNode.parentNode);
+       f.required = true;
+       uEditCheckErrors();
+}
+
+
+
diff --git a/Evergreen/xul/staff_client/server/patron/ue_ui.js b/Evergreen/xul/staff_client/server/patron/ue_ui.js
new file mode 100644 (file)
index 0000000..dacdfcf
--- /dev/null
@@ -0,0 +1,463 @@
+/* -----------------------------------------------------------------------
+       UI code for the user editor.  Handles breaking up the components
+       into a wizard-like interface.
+       ----------------------------------------------------------------------- */
+
+
+var pages = [ 
+       'uedit_userid', 
+       'uedit_contact_info', 
+       'uedit_addresses', 
+       'uedit_groups', 
+       'uedit_stat_cats', 
+       'uedit_surveys',
+       'uedit_finalize',
+       ];
+
+/* ID's of objects that should be focused when their page is made visible */
+var pageFocus = [
+       'ue_barcode',
+       'ue_email',
+       'ue_addr_label_1',
+       'ue_profile',
+       'ue_stat_cat_selector_1',
+       'ue_survey_selector_1',
+       'ue_view_summary'
+];
+
+
+function uEditNext() {
+       var i = _findActive();
+       if( i < (pages.length - 1)) uEditShowPage(pages[i+1]);
+}
+
+
+function uEditPrev() {
+       var i = _findActive();
+       if( i > 0 ) uEditShowPage(pages[i-1]);
+}
+
+function uEditCheckErrors() {
+       var errors = uEditGetErrorStrings();
+       if(errors) unHideMe($('ue_errors'));
+       else hideMe($('ue_errors'));
+}
+
+/*
+function uEditFetchError(id) { if($(id)) return $(id).innerHTML + "\n"; return "";}
+*/
+
+function uEditShowPage(id) {
+       if( id == null ) return;
+
+       for( var p in pages ) {
+               var page = pages[p];
+               hideMe($(page));
+               removeCSSClass($(page+'_label'), 'label_active');
+       }
+
+       var idx = _findPageIdx(id);
+
+       unHideMe($(id));
+       addCSSClass($(id+'_label'), 'label_active');
+       var fpage = pageFocus[idx];
+
+       var pnode = $(fpage);
+       if( id == 'uedit_addresses' ) 
+               pnode = $n( $('ue_address_tbody').
+                       getElementsByTagName('tr')[0], 'ue_addr_label');
+
+       if(pnode) { 
+               pnode.focus(); 
+               try{pnode.select()}catch(e){} 
+       }
+
+       unHideMe($('ue_back'));
+       unHideMe($('ue_fwd'));
+
+       if(idx == 0) hideMe($('ue_back'));
+       if(idx == (pages.length-1)) hideMe($('ue_fwd'));
+}
+
+function _findActive() {
+       for( var p in pages ) {
+               if(! $(pages[p]).className.match(/hide_me/) )
+                       return parseInt(p);
+       }
+       return null;
+}
+
+function _findPageIdx(name) {
+       for( var i in pages ) {
+               var page = pages[i];
+               if( page == name ) return i;
+       }
+       return -1;
+}
+
+/* ------------------------------------------------------------------------------ */
+/* Below are the various UI components built from retrieved data */
+/* ------------------------------------------------------------------------------ */
+
+
+/* org selector */
+function uEditBuildLibSelector( node, depth, selector ) {
+       if(!selector) selector = $('ue_org_selector');
+       if(!node) { depth = 0; node = globalOrgTree; }
+       var opt = insertSelectorVal( 
+               selector, -1, node.name(), node.id(), null, depth++ );
+       if(!findOrgType(node.ou_type()).can_have_users()) opt.disabled = true; 
+       if( node.id() == USER.ws_ou() ) 
+               setSelector(selector, node.id());
+
+       for( var c in node.children() ) 
+               uEditBuildLibSelector(node.children()[c], depth, selector);
+}
+
+
+/* group tree selector */
+function uEditDrawGroups(tree, depth, selector) {
+       if(!selector) {
+               selector = $('ue_profile');
+               depth = 0;
+       }
+       groupsCache[tree.id()] = tree;
+
+       /* if the staff does not have perms to access this group, 
+               remove it from the tree and don't add it's children */
+       var perm = uEditFindGroupPerm(tree);
+       var org = PERMS[perm];
+       if( org == -1 ) return;
+
+       var opt = insertSelectorVal( selector, -1, tree.name(), tree.id(), null, depth++ );     
+       if(!isTrue(tree.usergroup())) opt.disabled = true;
+
+       for( var c in tree.children() ) 
+               uEditDrawGroups( tree.children()[c], depth, selector );
+}
+
+
+function uEditFindGroupPerm(group) {
+       if(!group) return null;
+       if( group.application_perm() ) 
+               return group.application_perm();
+       return uEditFindGroupPerm(groupsCache[group.parent()]);
+}
+
+
+/* user identification types */
+function uEditDrawIDTypes(types) {
+       var pri_sel = $('ue_primary_ident_type');
+       //var sec_sel = $('ue_secondary_ident_type');
+       var idx = 1;
+       for( var t in types ) {
+               var type = types[t];
+               if(!type.name()) continue;
+               identTypesCache[type.id()] = type;
+               setSelectorVal( pri_sel, idx, type.name(), type.id() );
+               //setSelectorVal( sec_sel, idx++, type.name(), type.id() );
+               idx++;
+       }
+}
+
+/* user statistical catagories */
+function uEditDrawStatCats(cats) {
+       var tbody = $('ue_stat_cat_tbody');
+       var templ = tbody.removeChild($('ue_stat_cat_row'));
+
+       for( var c in cats ) {
+               var row = templ.cloneNode(true);
+               uEditInsertCat( row, cats[c], c );
+               tbody.appendChild(row);
+       }
+}
+
+
+function uEditInsertCat( row, cat, idx ) {
+
+       cat.entries().sort(  /* sort the entries by value */
+               function( a, b ) { 
+                       if( !a.value() ) return -1;
+                       if( !b.value() ) return 1;
+                       if( (a.value()+'').toLowerCase() > (b.value()+'').toLowerCase()) return 1;
+                       if( (a.value()+'').toLowerCase() < (b.value()+'').toLowerCase()) return -1;
+                       return 0;
+               }
+       );
+
+       statCatsCache[cat.id()] = cat;
+
+       /* register the new map object */
+       uEditBuildSCMField(cat, row);
+
+       var newval = $n(row, 'ue_stat_cat_newval');
+       var selector = $n(row, 'ue_stat_cat_selector');
+
+       selector.onchange = function() { 
+               newval.value = getSelectorVal(selector);
+               if(newval.onchange) newval.onchange();
+       }
+
+       if( idx == 0 ) selector.id = 'ue_stat_cat_selector_1'; 
+
+       $n(row, 'ue_stat_cat_name').appendChild(text(cat.name()));
+       $n(row, 'ue_stat_cat_owner').appendChild(
+               text(fetchOrgUnit(cat.owner()).shortname()));
+
+       for( var e in cat.entries() ) {
+               var entry = cat.entries()[e];
+               setSelectorVal( selector, 
+                       (parseInt(e)+1), entry.value(), entry.value() );
+       }
+}
+
+/* draw the surveys */
+function uEditDrawSurveys(surveys) {
+
+       var div = $('uedit_surveys');
+       var table = div.removeChild($('ue_survey_table'));
+       if( surveys.length == 0 ) unHideMe($('uedit_no_surveys'));
+
+       for( var s in surveys ) {
+               var survey = surveys[s];
+               surveysCache[survey.id()] = survey;
+               var clone = table.cloneNode(true);
+               uEditInsertSurvey( div, clone, survey, s );
+               div.appendChild(clone);
+       }
+}
+
+/* insert the servey then insert each of that surveys questions */
+function uEditInsertSurvey( div, table, survey, sidx ) {
+
+       $n(table, 'ue_survey_name').appendChild(text(survey.name()));
+       $n(table, 'ue_survey_desc').appendChild(text(survey.description()));
+
+       var tbody = $n(table, 'ue_survey_tbody');
+       var templ = tbody.removeChild($n(table, 'ue_survey_row'));
+
+       for( var q in survey.questions() ) {
+               var row = templ.cloneNode(true);
+               var quest = survey.questions()[q];
+               uEditInsertSurveyQuestion( row, survey, quest );
+               tbody.appendChild(row);
+       }
+}
+
+function uEditInsertSurveyQuestion( row, survey, question ) {
+
+       var selector = $n(row, 'ue_survey_answer');
+       row.setAttribute('question', question.id());
+       $n(row, 'ue_survey_question').appendChild(text(question.question()));
+
+       for( var a in question.answers() ) {
+               var answer = question.answers()[a];
+               surveyAnswersCache[answer.id()] = answer;
+               insertSelectorVal(selector, -1, answer.answer(), answer.id() );
+       }
+
+       surveyQuestionsCache[question.id()] = question;
+
+       if( patron.isnew() && isTrue(survey.required()) ) 
+               addCSSClass(selector, 'invalid_value');
+
+       selector.onchange = function() {
+
+               /* remove any existing responses for this survey */
+               patron.survey_responses(
+                       grep( patron.survey_responses(),
+                               function(item) {
+                                       return (item.survey() != survey.id());
+                               }
+                       )
+               );
+
+
+               if(!patron.survey_responses())
+                       patron.survey_responses([]);
+
+               var val = getSelectorVal(selector);
+
+               if( patron.isnew() && isTrue(survey.required()) ) {
+                       if(val)
+                               removeCSSClass(selector, 'invalid_value');
+                       else 
+                               addCSSClass(selector, 'invalid_value');
+                       uEditCheckErrors();
+               }
+
+               if(!val) return;
+
+               var resp        = new asvr();
+               resp.isnew(1);
+               resp.survey(survey.id());
+               resp.usr(patron.id());
+               resp.question(row.getAttribute('question'));
+               resp.answer(val);
+               patron.survey_responses().push( resp );
+       }
+}
+
+
+
+
+
+/* -----------------------------------------------------------------------
+       Spit out the patron info to the summary display tables...
+       ----------------------------------------------------------------------- */
+
+function uEditShowSummary() {
+       hideMe($('main_div_container'));
+       unHideMe($('summary_div_container'));
+
+       for( var f in dataFields ) {
+
+               var field = dataFields[f];
+               if( field.object == patron ) {
+
+                       var val = uEditNodeVal(field);
+
+                       if(     field.key == 'profile'          ||
+                                       field.key == 'home_ou'          ||
+                                       field.key == 'ident_type'       ||
+                                       field.key == 'ident_type2') {
+
+                               val = getSelectorName($(field.widget.id));
+                       }
+
+                       var node = $('ue_summary_'+field.key);
+                       if(node) appendClear(node, text(val));
+               }
+
+               if( field.object == patron.card() )
+                       appendClear($('ue_summary_barcode'), text(uEditNodeVal(field)));
+
+       }
+
+       var table = $('ue_summary_table');
+       uEditFleshSummaryAddresses( table, patron );
+       uEditFleshSummaryStatCats( table, patron );
+       uEditFleshSummarySurveys( table, patron );
+}
+
+
+
+var uEditSummaryAddrRow;
+function uEditFleshSummaryAddresses( table, patron ) {
+
+       var addrtbody = $n(table, 'ue_summary_addr_tbody');
+       if(!uEditSummaryAddrRow)
+               uEditSummaryAddrRow = 
+                       addrtbody.removeChild($n(addrtbody, 'ue_summary_addr_row'));
+       var rowtmpl = uEditSummaryAddrRow;
+       removeChildren(addrtbody);
+
+       for( var a in patron.addresses() ) {
+               var address = patron.addresses()[a];
+               var row = rowtmpl.cloneNode(true);
+               uEditFleshSummaryAddr( address, patron, row );
+               addrtbody.appendChild(row);
+               if(address.isdeleted()) addCSSClass(row, 'deleted');
+       }
+}
+
+
+function uEditFleshSummaryAddr( address, patron, row ) {
+       var yes = $('yes').innerHTML;
+       var no = $('no').innerHTML;
+
+       $n(row, 'label').appendChild(text(address.address_type()));
+       $n(row, 'street1').appendChild(text(address.street1()));
+       $n(row, 'street2').appendChild(text(address.street2()));
+       $n(row, 'city').appendChild(text(address.city()));
+       $n(row, 'county').appendChild(text(address.county()));
+       $n(row, 'state').appendChild(text(address.state()));
+       $n(row, 'country').appendChild(text(address.country()));
+       $n(row, 'zip').appendChild(text(address.post_code()));
+       $n(row, 'valid').appendChild(text( (isTrue(address.valid())) ? yes : no ));
+       $n(row, 'incorporated').appendChild(text( (isTrue(address.within_city_limits())) ? yes : no ));
+
+       var mid = patron.mailing_address();
+       if( typeof patron.mailing_address() == 'object' ) 
+               mid = patron.mailing_address().id();
+       $n(row, 'mailing').appendChild(text((mid == address.id()) ? yes : no ));
+
+       var bid = patron.billing_address();
+       if( typeof patron.billing_address() == 'object' ) 
+               bid = patron.billing_address().id();
+       $n(row, 'billing').appendChild(text((bid == address.id()) ? yes : no ));
+}
+
+
+
+var uEditSummaryStatCatRow;
+function uEditFleshSummaryStatCats( table, patron ) {
+       var tbody = $n(table, 'ue_summary_stats_tbody');
+
+       if(!uEditSummaryStatCatRow)
+               uEditSummaryStatCatRow = 
+                       tbody.removeChild($n(tbody, 'ue_summary_stats_row'));
+       var rowtmpl = uEditSummaryStatCatRow;
+       removeChildren(tbody);
+
+       for( var s in patron.stat_cat_entries() ) {
+               row = rowtmpl.cloneNode(true);
+               var entry = patron.stat_cat_entries()[s];
+               var cat = statCatsCache[entry.stat_cat()];
+               $n(row, 'ue_summary_stat_name').appendChild(text(cat.name()));
+               $n(row, 'ue_summary_stat_value').appendChild(text(entry.stat_cat_entry()));
+               row.setAttribute('statcat', entry.stat_cat());
+               if( entry.isdeleted() ) addCSSClass(row, 'deleted'); 
+               tbody.appendChild(row);
+       }
+
+       if( ! getElementsByTagNameFlat( tbody, 'tr' )[0] )
+               hideMe(tbody.parentNode);
+       else
+               unHideMe(tbody.parentNode);
+}
+
+
+
+var uEditSummarySurveyRow;
+function uEditFleshSummarySurveys( table, patron ) {
+
+       var tbody       = $n(table, 'ue_summary_survey_tbody');
+       if(!uEditSummarySurveyRow)
+               uEditSummarySurveyRow = 
+                       tbody.removeChild($n(tbody, 'ue_summary_survey_row'));
+       var rowtmpl = uEditSummarySurveyRow;
+
+       removeChildren(tbody);
+
+       for( var r in patron.survey_responses() ) {
+               var row         = rowtmpl.cloneNode(true);
+               var resp                = patron.survey_responses()[r];
+               var survey      = surveysCache[resp.survey()];
+               var quest       = surveyQuestionsCache[resp.question()];
+               var answer      = surveyAnswersCache[resp.answer()];
+               $n(row, 'ue_summary_survey_name').appendChild(text(survey.name()));
+               $n(row, 'ue_summary_survey_question').appendChild(text(quest.question()));
+               $n(row, 'ue_summary_survey_answer').appendChild(text(answer.answer()));
+               tbody.appendChild(row);
+       }
+
+       if( ! getElementsByTagNameFlat(tbody, 'tr')[0])
+               hideMe(tbody.parentNode);
+       else
+               unHideMe(tbody.parentNode);
+}
+
+
+function uEditDrawNetLevels(netLevels) {
+       var sel = $('ue_net_level');
+       iterate( netLevels, 
+               function(i) {
+                       insertSelectorVal( sel, -1, i.name(), i.id() );
+               }
+       );
+}
+
+
+
+