/*  jan 27/ 10:10 am
  Er_Ext_Wrapper.js is a wrapper library around Ext.js    version 2.2
    issues:
    - validation only works if forms have the datasource set, for windows  it doesn't work
    - auto load on addContainer may not work !
    - auto completion      
*/

Ext.namespace('Er');

// the common config for all fields
Er.FieldConfig = {
        labelWidth: 120,             // default lableWidth
        width:      210,             // the default width of all fields 
        allowBlank: true,
        fieldLabel: '',
        msgTarget: 'side'
};

// the common config for all containers
Er.ContainerConfig = {
    buttonAlign: 'center'
};

Er.DEBUG = true;

Er.COUNTRIES        = 1;
Er.STATES           = 2;
Er.STATES_PROVINCES = 3;
Er.PROVINCES        = 4;
Er.GOV_BRANCHES     = 5;
Er.JOB_FUNCTIONS    = 6;
Er.AGENCY_FUNCTION  = 7;
Er.AREA_TECH        = 8;
Er.AUDIT            = 9;
Er.MONTH            = 10;
Er.HOW_HEAR         = 11;

Er.CountriesArray = ['USA','Afghanistan','Argentina','Australia','Austria','Bahrain','Bangladesh','Belgium','Benin','Bermuda',
'Bolivia','Brazil','Cambodia','Canada','Chile','China','Costa Rica','Denmark','Ecuador','El Salvador','Estonia','Ethiopia',
'European Union','Finland','France','Germany','Ghana','Greece','Haiti','Holland','India','Indonesia','Inter-Regional','Iraq',
'Ireland','Italy','Jamaica','Japan','Jordan','Kenya','Korea','Latvia','Lebanon','Liberia','Malaysia','Mali','Marshall Islands',
'Mexico','Morocco','Netherlands','New Zealand','Norway','Oman','Oman','Pakistan','Philippines','Portugal','Romania','Russia',
'Rwanda','Saint Maarten','Sierra Leone','Singapore','South Africa','Spain','Sweden','Switzerland','Taiwan','Tanzania',
'Thailand','Tunisia','Uganda','United Arab Emirates','United Kingdom','United Nations','USA',
'Venezuela','Vietnam','Virgin Islands','Zambia','Zimbabwe','Other'];

Er.StatesArray = [ 
['AL', 'Alabama'],          ['AK', 'Alaska'],           ['AZ', 'Arizona'],      ['AR', 'Arkansas'], 
['CA', 'California'],       ['CO', 'Colorado'],         ['CT', 'Connecticut'],  ['DE', 'Delaware'],
['DC','District of Columbia'],['FL', 'Florida'],        ['GA', 'Georgia'],      ['GU', ' Guam'],     ['HI','Hawaii'],
['ID', 'Idaho'],            ['IL', 'Illinois'],         ['IN', 'Indiana'],      ['IA', 'Iowa'],
['KS', 'Kansas'],           ['KY', 'Kentucky'],         ['LA', 'Louisiana'],    ['ME', 'Maine'],
['MD', 'Maryland'],         ['MA', 'Massachusetts'],    ['MI', 'Michigan'],     ['MN', 'Minnesota'],
['MS', 'Mississippi'],      ['MO', 'Missouri'],         ['MT', 'Montana'],      ['NE', 'Nebraska'],
['NV', 'Nevada'],           ['NH', 'New Hampshire'],    ['NJ', 'New Jersey'],   ['NM', 'New Mexico'], 
['NY', 'New York'],         ['NC', 'North Carolina'],   ['ND', 'North Dakota'], ['OH', 'Ohio'], 
['OK', 'Oklahoma' ],        ['OR', 'Oregon'],           ['PA', 'Pennsylvania'], ['PR', 'Puerto Rico'],
['RI', 'Rhode Island'],
['SC', 'South Carolina'],   ['SD', 'South Dakota'],     ['TN', 'Tennessee'],    ['TX', 'Texas'], 
['UT', 'Utah'],             ['VT', 'Vermont'],          ['VA', 'Virginia'],     ['WA', 'Washington'], 
['WV', 'West Virginia'],    ['WI', 'Wisconsin'],        ['WY', 'Wyoming'],      ['ZZ', 'Other']  ];

Er.ProvincesArray = [ 
['AB', 'Alberta'],                                 
['BC', 'British Columbia'],                                               
['MB', 'Manitoba'],                                                       
['NB', 'New Brunswick'],                                              
['NL', 'Newfoundland and Labrador'],                                      
['NT', 'Northwest Territories'],                                          
['NS', 'Nova Scotia'],                                                    
['NU', 'Nunavut'],                                                        
['ON', 'Ontario'],                                                        
['PE', 'Prince Edward Island'],                                           
['QC', 'Quebec'],                                                         
['SK', 'Saskatchewan'],                                                   
['YT', 'Yukon'] ];                                                          
                                                    
                                                           
 
 
Er.GovBranchArray= [ 
'A - State Government', 
'B - County Government', 
'C - Municipal Government',
'D - Federal Government', 
'E - Special District, Public Utility', 
'F - Government Association',
'W - Other Government',
'Y - Private Sector - Systems/Software/Network Integrator', 
'Z - Private Sector - Suppliers to Government',
'X - Other'];

Er.JobFunctionArray= [ 
'A - Administrative/Policy Management or Supervision', 
'B - Elected Official',
'C - Financial/Procurement Management or Supervision', 
'D - Information Systems/Technical Management or Supervision',
'E - Operations/Project Management or Supervisions', 
'F - Professional Management or Supervision',
'G - Consultant Management or Supervision', 
'H - Marketing/Sales Management or Supervision',
'J - Law Enforcement', 
'Z - Other' ];

Er.AgencyFunctionArray = [ 
'01 - Administrative/Business and Consumer Affairs',
'02 - Records Mgmt/Archives',
'03 - Justice-Judicial/Courts/Prosecution/Defense/Corrections', 
'04 - Law Enforcement/Public Safety/Fire/Emergency Services/911',
'05 - DP/Telecom or Information Services',
'06 - Education (K-12)',
'07 - Education (Higher Ed)',
'08 - Elected Official - Legislative/Admin/Staff',
'09 - Finance/Revenue/Accounting/Audit',
'10 - Forestry/Land Mgmt/Parks and Recreation/Agriculture',
'11 - Health, Welfare and Social Services, Housing and Community Dev.',
'12 - Library',
'13 - Personnel/Human Resources/Training',
'14 - Public Works/Engineering/Public Utility/Transportation',
'15 - Purchasing/General Services',
'16 - Regulatory/Licensing',
'17 - Wastewater/Sanitation/Environment',
'18 - Zoning/Land Use/Planning',
'19 - Printing/Publishing',
'20 - Consulting/Marketing/Research',
'99 - Other' ];

Er.AreaTechArray = [
"01 - Application Development",
"02 - Web Development / Web Portal / Internet",
"03 - Cyber Security / Physical Security",
"04 - Telecommunications / Network Management",
"05 - Mainframe Operations / Support",
"06 - Desktop / Laptop / Server Support or Operations",
"07 - IT Procurement",
"99 - Other" ];

Er.HowHearArray = [
'A - Postcard',
'B - Brochure',
'C - Email',
'M - Phone Call from Government Technology',
//'EVENT WEB PAGE',
'E - Memo from Management',
'F - Staff Meeting',
'G - User Group / Association',
'I - Training Office',
'Z - Other'   ];

Er.MonthArray = [
'01 - January',
'02 - February',
'03 - March',
'04 - April',
'05 - May',
'06 - June',
'07 - July',
'08 - August',
'09 - September',
'10 - October',
'11 - November',
'12 - December' ];

// change Ext sort order to case-insensitive
Ext.data.Store.prototype.sortData = function(f, direction){
    direction = direction || 'ASC';
    var st = this.fields.get(f).sortType;
    var fn = function(r1, r2) 
    {
        var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
        if( v1 == null)
            return -1;
        if( v2 == null)
            return 1;
                
        // ADDED THIS FOR CASE INSENSITIVE SORT
        if (v1.toLowerCase) {
            v1 = v1.toLowerCase();
            v2 = v2.toLowerCase();
        }
        return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
    };

    this.data.sort(direction, fn);
    if (this.snapshot && this.snapshot != this.data) {
        this.snapshot.sort(direction, fn);
    }
}

//===============================================================================================================
//                       Utility functions
//===============================================================================================================
//  tried to use Ext.urlEncode but didn't work 
Er.urlEncode = function(clearString) {
    var output = '';
    var x      = 0;
    clearString  = clearString.toString();
    var regex    = /(^[a-zA-Z0-9_.]*)/;
    while (x < clearString.length) {
        var match = regex.exec(clearString.substr(x));
        if (match != null && match.length > 1 && match[1] != '') {
            output += match[1];
            x += match[1].length;
        } 
        else 
        {
            if (clearString[x] == ' ')
                output += '+';
            else 
            {
                var charCode = clearString.charCodeAt(x);
                var hexVal = charCode.toString(16);
                output += '%' + ( hexVal.length < 2 ? '0' : '' ) + hexVal.toUpperCase();
            }
            x++;
        }
    }
    return output;
}

Er.urlDecode = function(encodedString) 
{
    var output = encodedString;
    var binVal, thisString;
    var myregexp = /(%[^%]{2})/;
    while ((match = myregexp.exec(output)) != null   && match.length > 1    && match[1] != '') {
        binVal     = parseInt(match[1].substr(1),16);
        thisString = String.fromCharCode(binVal);
        output     = output.replace(match[1], thisString);
    }
    var pattern = /\+/g ;
    output     = output.replace(pattern , " ");
    return output;
}

Er.utf8_encode = function( string ) 
{
    // http://kevin.vanzonneveld.net
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: sowberry
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // +   improved by: Yves Sucaet
    // +   bugfixed by: Onno Marsman
    // *     example 1: utf8_encode('Kevin van Zonneveld');
    // *     returns 1: 'Kevin van Zonneveld'
 
    string = (string+'').replace(/\r\n/g, "\n").replace(/\r/g, "\n");
 
    var utftext = "";
    var start, end;
    var stringl = 0;
 
    start = end = 0;
    stringl = string.length;
    for (var n = 0; n < stringl; n++) {
        var c1 = string.charCodeAt(n);
        var enc = null;
 
        if (c1 < 128) {
            end++;
        } else if((c1 > 127) && (c1 < 2048)) {
            enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
        } else {
            enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
        }
        if (enc != null) {
            if (end > start) {
                utftext += string.substring(start, end);
            }
            utftext += enc;
            start = end = n+1;
        }
    }
 
    if (end > start) {
        utftext += string.substring(start, string.length);
    }
 
    return utftext;
}

Er.md5 = function( str ) 
{
    // http://kevin.vanzonneveld.net
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // + namespaced by: Michael White (http://getsprink.com)
    // +    tweaked by: Jack
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // -    depends on: utf8_encode
    // *     example 1: md5('Kevin van Zonneveld');
    // *     returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
 
    var RotateLeft = function(lValue, iShiftBits) {
        return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
    };
 
    var AddUnsigned = function(lX,lY) {
        var lX4,lY4,lX8,lY8,lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
        if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        }
        if (lX4 | lY4) {
            if (lResult & 0x40000000) {
                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    };
 
    var F = function(x,y,z) { return (x & y) | ((~x) & z); };
    var G = function(x,y,z) { return (x & z) | (y & (~z)); };
    var H = function(x,y,z) { return (x ^ y ^ z); };
    var I = function(x,y,z) { return (y ^ (x | (~z))); };
 
    var FF = function(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
 
    var GG = function(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
 
    var HH = function(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
 
    var II = function(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
 
    var ConvertToWordArray = function(str) {
        var lWordCount;
        var lMessageLength = str.length;
        var lNumberOfWords_temp1=lMessageLength + 8;
        var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
        var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
        var lWordArray=Array(lNumberOfWords-1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while ( lByteCount < lMessageLength ) {
            lWordCount = (lByteCount-(lByteCount % 4))/4;
            lBytePosition = (lByteCount % 4)*8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount)<<lBytePosition));
            lByteCount++;
        }
        lWordCount = (lByteCount-(lByteCount % 4))/4;
        lBytePosition = (lByteCount % 4)*8;
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
        lWordArray[lNumberOfWords-2] = lMessageLength<<3;
        lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
        return lWordArray;
    };
 
    var WordToHex = function(lValue) {
        var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
        for (lCount = 0;lCount<=3;lCount++) {
            lByte = (lValue>>>(lCount*8)) & 255;
            WordToHexValue_temp = "0" + lByte.toString(16);
            WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
        }
        return WordToHexValue;
    };
 
    var x=Array();
    var k,AA,BB,CC,DD,a,b,c,d;
    var S11=7, S12=12, S13=17, S14=22;
    var S21=5, S22=9 , S23=14, S24=20;
    var S31=4, S32=11, S33=16, S34=23;
    var S41=6, S42=10, S43=15, S44=21;
 
    str = Er.utf8_encode(str);
    x = ConvertToWordArray(str);
    a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
    
    xl = x.length;
    for (k=0;k<xl;k+=16) {
        AA=a; BB=b; CC=c; DD=d;
        a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
        d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
        c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
        b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
        a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
        d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
        c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
        b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
        a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
        d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
        c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
        b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
        a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
        d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
        c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
        b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
        a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
        d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
        c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
        b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
        a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
        d=GG(d,a,b,c,x[k+10],S22,0x2441453);
        c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
        b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
        a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
        d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
        c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
        b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
        a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
        d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
        c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
        b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
        a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
        d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
        c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
        b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
        a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
        d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
        c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
        b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
        a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
        d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
        c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
        b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
        a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
        d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
        c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
        b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
        a=II(a,b,c,d,x[k+0], S41,0xF4292244);
        d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
        c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
        b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
        a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
        d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
        c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
        b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
        a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
        d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
        c=II(c,d,a,b,x[k+6], S43,0xA3014314);
        b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
        a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
        d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
        c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
        b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
        a=AddUnsigned(a,AA);
        b=AddUnsigned(b,BB);
        c=AddUnsigned(c,CC);
        d=AddUnsigned(d,DD);
    }
 
    var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
 
    return temp.toLowerCase();
}

// usage of on: {click: function(do we get any vars ?){ dump(var); } }

// Simple Debug, written by Chris Klimas 
// licensed under the GNU LGPL. 
// http://www.gnu.org/licenses/lgpl.txt 
// 
// There are three functions defined here: 
// 
// log (message) // Logs a message. Every second, all logged messages are displayed 
// in an alert box. This saves you from having to hit Return a ton 
// of times as your script executes. // 
// inspect (object) 
// Logs the interesting properties an object possesses. Skips functions 
// and anything in CAPS_AND_UNDERSCORES. 
// 
// dump (object) 
// Like inspect(), but displays values for the properties. The output 
// for this can get very large -- for example, if you are inspecting 
// a DOM element. 
Er.log= function(message)
{ 
    if (!  Er._log_timeout) 
        Er._log_timeout = window.setTimeout(dump_log, 1000); 
    Er._log_messages.push(message); 
    
    function dump_log() 
    { 
        var message = ''; 
        for (var i = 0; i < Er._log_messages.length; i++) 
            message += Er._log_messages[i] + '\n'; alert(message); 
        Er._log_timeout = null; 
        delete Er._log_messages; 
        Er._log_messages = new Array(); 
    } 
} 
//==============================================
 Er.inspect = function(obj) 
{ 
    var message = 'Object possesses these properties: \n'; 
    if (obj) 
    { 
        for (var i in obj) 
        { 
            if ((obj[i] instanceof Function) || (obj[i] == null) || (i.toUpperCase() == i)) 
                continue; 
            message += i + ', '; 
        } 
        message = message.substr(0, message.length - 2); 
    } 
    else 
        message = 'Object is null'; 
    Er.log(message); 
} 
//==============================================
Er.dump = function(obj) 
{ 
    var message = ''; 
    if (obj) for (var i in obj) 
    { 
        if ( (obj[i] == null) || (i.toUpperCase() == i)) 
            continue; 
        if(obj[i] instanceof Function)
        { 
            //message += i + ' -function-' + '\n'; 
            continue;
        }
        else
        {
            message += i + ': ' + obj[i] + '\n'; 
        }
    } 
    else 
        message = 'Object is null'; 
    Er.log(message); 
}
Er._log_timeout; 
Er._log_messages = new Array(); 

//==============================================
// a deep copy
Er.cloneObject= function(what) {
    for (i in what) {
        if (typeof what[i] == 'object') {
            this[i] = new Er.cloneObject(what[i]);
        }
        else
            this[i] = what[i];
    }
}   

//==============================================
Er.concat = function(v1, v2)
{
    v = new Array();
    for (p in v1)
        v[p] = v1[p];
    for (p in v2)
        v[p] = v2[p]; 
    return v;
}

//==============================================
Er.isDefined = function(parm)
{
     return (typeof parm == "undefined")?  false: true;
}

//==============================================
Er.getEnvironment = function()
{
    var environment = document.location.href.substr(7,3);
    if(environment == 'pro')
        return 'proof';
    return environment;     
}


//==============================================
// returns false if one or more fields are invalid
Er.validate = function(frm)
{    
    var form            = frm.getForm();
    var invalid         = false;
    var counter         = 0;
    var formFieldValues = form.getValues();
    for (var obj in formFieldValues)
    {
        var currField = form.findField(obj);
        if (!currField.isValid() )
        {
          
            counter++;
            if (1 == counter)
            {
                currField.getEl().dom.focus();
            }
            currField.getEl().frame("FF0000", 1, {duration: 1});
            invalid = true;
        }
    }
    
    if(Er.validation == false)  // this is a debug switch
        return true;
        
    return(!invalid);
}

// =====================================================

Er.loginWindow = null;
Er.loginCallback = function(dta)
{   
    if(dta.success == "true")
    {
        Er.loginWindow.destroy();
        Er.loginWindow = null;
    }
    else
    {
        if(dta.message != "")
            Ext.Msg.alert('Login', dta.message);
    }
}

Er.login = function()
{ 
    ds = new Er.DataSource({ saveAction:{callback: Er.loginCallback, method: 'YaasAccount.login'}});
    Er.loginWindow = new Er.Window({
        title: 'Login',
        modal: true,
        items: [ new Er.FormPanel({
                    dataSource:  ds,
                    height:      110,
                    width:       300,
                    labelWidth:  80,
                    addBodyStyle:'padding:20px;',
                    items:[
                        new Er.TextField({width: 150, name:'email',    fieldLabel:'Email',    allowBlank:false}),
                        new Er.TextField({width: 150, name:'password', fieldLabel:'Password', allowBlank:false, inputType:'password'}),
                        new Er.CheckBoxField({     name:'remember_me', boxLabel:'Remember Me'})
                    ] 
                 })
        ],
        buttons: [new Er.Button({text: 'Login', handler: ds.saveData, scope:ds})   ]         
    });
    Er.loginWindow.ds = ds;
    Er.loginWindow.show();
}

Er.logout = function()
{
    ds = new Er.DataSource({ loadAction:{method: 'YaasAccount.logout'}});
    ds.loadData();
}

/*    not ready yet, have to figure out the backend paart first
//=======================================================
Er.runScript(scriptName)
{
   ds = new Er.DataSource();
   ds.doAction({callback: Er.runScriptCallback, method: 'Yaasgeneric.LoadScript', params:{script:scriptName}}) 
}
Er.runScriptCallback(dta)
{
    if(dta.success == 'true')
    {
        eval(dta[0]);
    }
    else
    {
        if(Er.isDefined(dta.message))
        {
            Ext.Msg.show({modal: false, title: 'Error Message', msg: dta.message });
        }
    }
}
*/

//=======================================================
Er.initialize = function(debug_switch){
    Ext.QuickTips.init();
    if(debug_switch)
    {
        Er.validation = false;   // turns off data validation
    }
}

//================================================================================================================
//                                     D A TA S O U R C E
//================================================================================================================
Er.ConnectionHandler = function() {}

Er.ConnectionHandler.prototype.request = function(dsid, req)
{ 
    req.dsid   = dsid;            // add the dsid  to the request   
    var reqs   = new Array(req);  // we send an array of requests to the other side  so wrap it
  
    for(var par in req.params)
    {
        if(req.params[par] instanceof Function)
        {
           continue;
        }
        var s = ""+ req.params[par] ;
        req.params[par] = s.replace(/&/g,"%26");     
    } 
 
    var params = Ext.util.JSON.encode(reqs);  
    
    Ext.Msg.show({modal: false, title: 'Processing...', msg: 'Please wait.', width: 240, closable: false});
    
    Ext.Ajax.request(
    {
        url: '/yaas/yaas.php', 
        params: 'data='+params,
        success: function(response)
        {
            Ext.MessageBox.hide();
            
            var results = Ext.decode(response.responseText);
            for(var result in results)
            {
                if (results[result].dsid)
                {    
                    var ds = Er.TheDataSources.get(results[result].dsid);
                    ds.replyFromServer(results[result]);
                }
            }
        },
        failure: function(response)
        {
            Ext.Msg.hide();
            Ext.Msg.alert('Connectionhandler', 'Ajax request failed');
        }
    });
}


//================================================================================================================
Er.DataSource = function(customConfig)
{    
    this.ID= Math.random().toString().substr(2);
    Er.TheDataSources.add(this.ID, this);   // register myself in the list of datasources
     
    this.containers = new  Array();  // the list of containers that this datasource is connected to
    
    this.loaded = false;     // we don't have any data yet
    
    this.config = {     
        autoLoad: false
    };
    Ext.apply(this.config, customConfig);
    
    if(this.config.autoLoad == true)
    {
        this.loadData();
    }
}  // end of DataSource constructor

//================================================================================================================
// called by connection handler
Er.DataSource.prototype.replyFromServer = function(dta)
{
    if(dta.debug)
    {
        alert(dta.debug);
    }    
    if(dta.callback &&  !this.forceCallback) 
    {
        eval(dta.callback);
        return;  
    }
    // if there is a callback, it is responsible for errorchecking (it can call defaultHandler to deal with the errors)
    if (this.callback)
    {  
        this.callback(dta);
        return;
    }
    
    this.defaultResultHandler(dta);   
}

//================================================================================================================
Er.DataSource.prototype.defaultResultHandler = function(dta)
{
    if (dta.callback)
    {
        eval(dta.callback);
        return;
    }
    
    if(Er.isDefined(dta.message))
    {
        Ext.Msg.show({modal: false, title: 'Message', msg: dta.message });
    }
 
    if(dta.success != 'true')
    {
        return;
    }
 
    if(Er.isDefined(this.pager))
    {
        this.pager.update(dta.totalRecords);
    }
    
    this.data = dta;
    var theData = new Ext.util.MixedCollection();
    
    //  use only the first data record this is for single value fields!!!!!!!!!!!!!!!!
    theData.addAll(dta.data[0]);   
    
     // go through our list of containers and load them
    for(var t = 0;   t < this.containers.length; t++)    // loop through all items in this container
    {
        this.containers[t].setData(theData, dta); 
    }
}

//================================================================================================================
// called by a button or container  the params contain a complete action object
Er.DataSource.prototype.doAction = function(action)
{
    this.callback      = action.callback;
    this.forceCallback = action.forceCallback;
    
    if(this.pager)
    {
        Ext.apply(action.params, this.pager.resetPagingParameters());
    }    
    Er.TheConnectionHandler.request(this.ID, action);
} 

//================================================================================================================
// called by a button or container the params contain additional params for the loadaction
Er.DataSource.prototype.loadData = function(params)
{
    if(! this.config.loadAction.params)
    {
        this.config.loadAction.params= {};
    }
    //when we call this function from a button we get the button as a parameter, so we have to ignore this
    if(params && ! Er.isDefined(params.xtype))  // add params to the existing params
    {     
        //this.config.loadAction.params = Ext.apply(this.config.loadAction.params, params); 
        this.config.loadAction.params = params;
        if(this.pager) // check if pager parameters are included
        {
            this.pager.resetPagingParameters();
        }
    }
   
    if(this.pager) // check if pager parameters are included
    {
        Ext.apply(this.config.loadAction.params, this.pager.getPagingParameters());
    } 
    
    this.callback      = this.config.loadAction.callback;
    this.forceCallback = this.config.loadAction.forceCallback;
    Er.TheConnectionHandler.request(this.ID, this.config.loadAction);
} 

//================================================================================================================
// called by a button or container the params contain additional params for the saveAction
Er.DataSource.prototype.saveData = function(newParams)
{
    var params = {};
    // go through our list of containers and save them
    for(var t = 0;   t < this.containers.length; t++)    // loop through all items in this container
    {
        if(this.containers[t].ertype == 'Er.FormPanel')
        {
            if(!Er.validate(this.containers[t]))        // make sure the data validates
                return;
                
            // find the radiofieldsets inside this form and validate those    
            var radiogroups = this.containers[t].find('xtype','fieldset');
            for( var t2 = 0; t2 <  radiogroups.length; t2++)
            {
                if(radiogroups[t2].config.ertype == 'radiofieldset')
                {
                    if( !radiogroups[t2].validate())    // radio fieldsets have their own validate()
                        return;
                }
            }  
        }
           
        params= Ext.apply(params, this.containers[t].getData());      
           
    }
  
    //when we call this function from a button we get the button as a parameter, so we have to ignore this
    if(newParams && ! Er.isDefined(newParams.xtype)) 
    {    
       //alert('new paramn');  
       params = Ext.apply(params, newParams);
    }
    else if(Er.isDefined(this.config.saveAction.params))
    {
        params = Ext.apply(params, this.config.saveAction.params);
    }        
    
   
    this.callback = this.config.saveAction.callback;
    this.forceCallback = this.config.saveAction.forceCallback;
    
    //this.config.saveAction.params = params;
    //Er.TheConnectionHandler.request(this.ID, this.config.saveAction);
    var theAction = new Er.cloneObject(this.config.saveAction);
    theAction.params = params;
    Er.TheConnectionHandler.request(this.ID, theAction);
} 

//================================================================================================================
Er.DataSource.prototype.setLoadAction = function(newAction)
{
    this.config.loadAction = newAction;
    if(this.pager) // check if pager parameters are included
    {
        this.pager.resetPagingParameters();
    }
}
//================================================================================================================
Er.DataSource.prototype.setSaveAction = function(newAction)
{
    this.config.saveAction = newAction;
}
//================================================================================================================
// called by a container
Er.DataSource.prototype.addContainerExtra = function(frm, getLoadedData)
{
    this.containers.push(frm);
    if(Er.isDefined(this.data) && getLoadedData == true)
    {
        // if we are loaded already then give our form the data
        
        //  use only the first data record this is for single value fields!!!!!!!!!!!!!!!!
        var theData = new Ext.util.MixedCollection();
        theData.addAll(this.data.data[0]);   
        frm.setData(theData, this.data);   
    }
}

// called by a container
Er.DataSource.prototype.addContainer = function(frm)
{
    this.addContainerExtra(frm, true)
}

Er.DataSource.prototype.setPager = function(pager)
{
    this.pager = pager;
}


//===========================================================================================================
//                                                    C O N T A I N E R S
//===========================================================================================================

// these are new methods that we add to all fields
Er.Container = new Object ({
       
    // called before the superclass constructor is called
    mergeConfigs : function(typeConfig, customConfig)
    {
        var cf = new Er.cloneObject(Er.ContainerConfig);
        cf = Ext.apply(cf, typeConfig);
        
        // merge the bodyStyles, of the defaults, but a custom bodyStyle will override all the defaults 
        cf.bodyStyle = Er.ContainerConfig.bodyStyle +" "+ typeConfig.bodyStyle; 
        if(Er.isDefined(customConfig.addBodyStyle))
        {
             cf.bodyStyle += (" "+ customConfig.addBodyStyle);
        }
        cf = Ext.apply(cf, customConfig); 
        return cf;
    },
    
    // called after the superclass constructor is called
    initialize : function()
    {
        if(this.config.dataSource)
        {
           this.config.dataSource.addContainer(this);
        } 
    } ,
    
    getData : function() 
    {  
        var dta = {};       
        for(var t= 0;   t < this.items.getCount(); t++)    // loop through all items in this container
        { 
            var i = this.items.itemAt(t); 
           
            // ignore objects which name starts with an _  (underscore)
            if( !Er.isDefined(i.name) || i.name.substring(0,1) != "_")
            { 
                dta = Ext.apply(dta, i.getData());                
            }
        }  
        return dta;
    },  // end of getData()
    
    // ----------------------- loads the fields with data   dta is an Ext.util.MixedCollection
    setData : function(dta, ar)
    { 
        
        for(var t= 0;   t < this.items.getCount(); t++)    // loop through all items in this container
        {
            var i = this.items.itemAt(t);
            if ( i instanceof Ext.Panel )
            {
                i.setData(dta,ar);
            }
            else 
            {   
                var name = i.hiddenName == null ? i.name : i.hiddenName;
                if(dta.containsKey(name))
                {
                    i.setValue(dta.get(name));
                }       
            }
        }
    } // end of setData    
});  // end of Er.Container

 
//===========================================================================================================
Er.Window = function (customConfig)
{
   this.ertype = 'Er.Window';
   this.config = {
        buttonAlign: 'center',
        autoScroll: true,
        autoSize: true,
        width:  500,
        height: 300
    };
   
    this.config = this.mergeConfigs(this.config, customConfig);
    Er.Window.superclass.constructor.call(this, this.config);
    this.initialize();
    
    if(this.config.autoSize == true)
    {
        this.on('show' , Er.autoSize);
    }
    
}
Ext.extend(Er.Window, Ext.Window, Er.Container);

Er.autoSize = function(dlg) 
{

    var el  = Ext.get(dlg.body);
    var dialog = dlg;
    
    dialog.setSize(el.first().dom.scrollWidth  + dlg.getFrameWidth()+10, el.first().dom.scrollHeight + dlg.getFrameHeight() + 10);
    
    if (dialog.getPosition()[1] < 30)
    {
        dialog.setPagePosition(dialog.getPosition()[0], 30);
    }
   
}

//===========================================================================================================
Er.Panel  = function(customConfig)
{
    this.ertype = 'Er.Panel';
    this.config = {
      border: false,
      bodyStyle:'padding:5px'
    };
   
    this.config = this.mergeConfigs(this.config, customConfig);
    Er.Panel.superclass.constructor.call(this, this.config);
    this.initialize();
}
Ext.extend(Er.Panel, Ext.Panel, Er.Container);

//===========================================================================================================
Er.TabPanel = function(customConfig)
{
    this.ertype = 'Er.TabPanel';
    this.config = {
        renderTo: Ext.getBody(),
        activeTab: 0,
        defaults:{bodyStyle:'padding:10px; '}
     
    };
    
    this.config = this.mergeConfigs(this.config, customConfig);   
    Er.TabPanel.superclass.constructor.call(this, this.config);
    this.initialize();
}
Ext.extend(Er.TabPanel, Ext.TabPanel, Er.Container);


//===========================================================================================================
Er.Pager = function(customConfig)
{
    this.config = {pageSize: 200
    };
    // x-item-disabled
    Ext.apply(this.config, customConfig);
       
    this.label = null;
    var buttons = new Array(
        new Er.Button({iconCls: 'x-tbar-page-first', minWidth:20, tooltip:'First Page',    handler: this.firstPage, scope: this }),
        new Er.Button({iconCls: 'x-tbar-page-prev' , minWidth:15, tooltip:'Previous Page', handler: this.previousPage, scope: this }),
        this.label = new Ext.form.Label({name:'_pager', text: '0 - 0 of 0'}),
        new Er.Button({iconCls: 'x-tbar-page-next', minWidth:15, tooltip:'Next Page', handler: this.nextPage, scope: this }),
        new Er.Button({iconCls: 'x-tbar-page-last', minWidth:20, tooltip:'Last Page', handler: this.lastPage, scope: this })
    );
    
    Er.Pager.superclass.constructor.call(this, buttons);
    
    this.config.buttons    = buttons;
    this.page       = 1;
    this.pageSize   = this.config.pageSize;
    this.numRecords = 0;

    if(Er.isDefined(customConfig.dataSource))
    {
        customConfig.dataSource.setPager(this);
    }   
    this.displayButtons();
}
Ext.extend(Er.Pager, Ext.Toolbar);

Er.Pager.prototype.displayButtons = function()
{  
    this.config.buttons[0].disable();
    this.config.buttons[1].disable();
    this.config.buttons[3].disable();
    this.config.buttons[4].disable();

    if(this.page > 1)  // not first page
    {
        this.config.buttons[0].enable();
        this.config.buttons[1].enable();
    }
    if( this.page*this.pageSize < this.numRecords) // not last page
    {
        this.config.buttons[3].enable();
        this.config.buttons[4].enable();
    } 
}

Er.Pager.prototype.setSortInfo = function(sortinfo)
{
    this.sortinfo = sortinfo;
    
    if(this.pageSize < this.numRecords)
    {   
        // we need to refresh,  and display the first page in the new order
        this.page = 1;
        this.config.dataSource.loadData.call(this.config.dataSource);
    }
}

Er.Pager.prototype.getPagingParameters = function()
{
    var params =  {page_start: (this.page-1) * this.pageSize, page_size: this.pageSize};
    if(this.sortinfo)
    {
        params.sort_direction = this.sortinfo.direction;
        params.sort_field     = this.sortinfo.field;
    }
    return params;
}


Er.Pager.prototype.resetPagingParameters = function()
{
    this.page       = 1;
    this.numRecords = 0;
    this.displayButtons();
    return this.getPagingParameters();
}

Er.Pager.prototype.update = function(numRecs)
{
    this.numRecords = numRecs;
    
    var first = ( (this.page-1) * this.pageSize )+1;
    var last  = Math.min( this.page * this.pageSize, this.numRecords);
    this.label.setText( first + ' - ' + last + ' of ' + this.numRecords);
    this.displayButtons();
}

Er.Pager.prototype.previousPage = function()
{
    if(this.page>1)
    {
        this.page = this.page-1;
        this.config.dataSource.loadData.call(this.config.dataSource);
    }
}

Er.Pager.prototype.nextPage = function()
{
    if(this.page * this.pageSize < this.numRecords)
    {         
        this.page = this.page +1;
        this.config.dataSource.loadData.call(this.config.dataSource);
    }
}

Er.Pager.prototype.firstPage = function()
{
    if(this.page>1)
    {
        this.page = 1;
        this.config.dataSource.loadData.call(this.config.dataSource);
    }
}

Er.Pager.prototype.lastPage = function()
{
    if(this.page * this.pageSize < this.numRecords)
    { 
        this.page = Math.floor( this.numRecords / this.pageSize) + 1;
        this.config.dataSource.loadData.call(this.config.dataSource);
    }
}


//===========================================================================================================
Er.GridPanel= function(customConfig)
{
    this.config = {
        height:          300,
        width:           400,
        columnWidth:     80,
        dynamic:         true,      // in case the user does not specify columns, we use the columns of the datasource
        remoteSort:      false,
        defaultSortable: true,
        autoScroll:      true,
        viewConfig:      { forceFit: true  }
    };
    
    if(Er.isDefined(customConfig.pageSize)&& Er.isDefined(customConfig.dataSource))
    {
        // add pager to bottom toolbar
        customConfig.bbar = new Er.Pager({pageSize: customConfig.pageSize, dataSource: customConfig.dataSource});
        this.pager = customConfig.bbar;
    }
        
    if(this.config.store == null)
    {
        this.storeConfig = {};
        this.storeConfig.sortInfo = customConfig.sortInfo;  
        var defaultColumnWidth = (typeof customConfig.columnWidth == 'undefined') ? this.config.columnWidth : customConfig.columnWidth;
        customConfig.dynamic = false;
        // create a data record, to be used by setData
        var dr     = new Array;  
        for(t=0; t<customConfig.columns.length; t++)
        {   
            customConfig.columns[t].sortable = true;    // set sortable by default
            
            var field= new Object();
            Ext.apply(field, customConfig.columns[t]); 
            customConfig.columns[t].width = (typeof field.width == 'undefined') ? defaultColumnWidth : field.width;
            field.name = customConfig.columns[t].dataIndex;
            if(field.type == 'date')
            {
                //field.dateFormat = 'Y-m-d H:i:s';  // with php.ini mssql date convert off
                field.dateFormat = 'M d Y g:iA';   // proof and live  
                //field.dateFormat = 'M j Y g:i:s:uA'; // dev
                if( ! customConfig.columns[t].renderer)
                {
                    var dformat = customConfig.columns[t].format ?  customConfig.columns[t].format : 'm/d/Y'
                    customConfig.columns[t].renderer =  Ext.util.Format.dateRenderer( dformat );   
                }
            }
            dr.push(field);    
        }
        var readerConfig = {
            // id: "pk" ,                       // The property within each row object that provides an ID for the record (optional)
            totalProperty: "totalRecords",      // The property which contains the total dataset size (optional)
            root: "data"                        // The property which contains an Array of row objects         
            }
                            
        this.dataRecord         = Ext.data.Record.create(dr); 
        this.storeConfig.reader = new Ext.data.JsonReader(readerConfig, this.dataRecord);           
        this.config.store       = new Ext.data.Store(this.storeConfig); 
    }
    
    this.config = this.mergeConfigs(this.config, customConfig);   
      
    Er.GridPanel.superclass.constructor.call(this, this.config);
    this.initialize();
    this.on('sortchange' , this.sortOrderChanged);       
}

Ext.extend(Er.GridPanel, Ext.grid.GridPanel, Er.Container);



// override the following methods: setData
Ext.override(Er.GridPanel, { 
    setData : function(dta, ar){    
        this.getStore().loadData(ar);
              
        // if the grid has a field with the id 'NumberOfRecordsInGrid' in the toolbar  set it to the number of records
        /*
        if(Er.isDefined(this.config.NumberOfRecordsField))
        { 
            var txt = ar.totalRecords;
            if(Er.isDefined(this.config.NumberOfRecordsFieldText))
            {
                txt += this.config.NumberOfRecordsFieldText;
            }
            this.config.NumberOfRecordsField.setText(txt) ; 
        }
        */
    }
    // ,getData : function(){ }
});


Er.GridPanel.prototype.sortOrderChanged = function(grid, sortinfo)
{
    if(grid.pager)
    {
        grid.pager.setSortInfo(sortinfo);
    }
}


Er.GridPanel.prototype.loadData = function($params)
{
    this.store.removeAll();
    this.config.dataSource.loadData($params);
}
Er.GridPanel.prototype.loadDataExtraData = function($params)
{
    this.store.removeAll();
    this.config.dataSource.loadDataExtraData($params);
}


// add a new method: getRow()
Er.GridPanel.prototype.getRow =  function(rowIndex)
{
  return this.store.getAt(rowIndex).json;
}

// add a new method: getCell()
Er.GridPanel.prototype.getCell =  function(rowIndex, colIndex)
{
  var record    = this.store().getAt(rowIndex);
  var fieldName = this.getColumnModel().getDataIndex(colIndex); // Get field name
  return record.get(fieldName);
}


//===========================================================================================================
Er.FormPanel = function(customConfig)
{
    this.ertype = 'Er.FormPanel';
    this.config = {
        labelWidth: Er.FieldConfig.labelWidth,
        height: 400,
        border: false,
        bodyStyle:'padding:6px;'
    };
    
    this.config = this.mergeConfigs(this.config, customConfig);   
    Er.FormPanel.superclass.constructor.call(this, this.config);
    this.initialize();
}
Ext.extend(Er.FormPanel, Ext.form.FormPanel, Er.Container);


//===========================================================================================================
/*
Er.FieldSet  = function(customConfig)
{
    this.config = {
        //autoWidth: true,
        autoHeight: true,
        hideBorders: true,
        //defaults:{bodyStyle:'padding:5px; margin:5px'},
        xtype: 'fieldset'
    };
    
    this.config = this.mergeConfigs(this.config, customConfig);   
    Er.FieldSet.superclass.constructor.call(this, this.config);
    this.initialize();      
}
Ext.extend(Er.FieldSet, Ext.form.FieldSet, Er.Container);
*/
//===========================================================================================================
Er.FieldSet  = function(customConfig)
{
    this.config = {
        //autoWidth: true,
        autoHeight: true,
        blankMessage: 'A selection is required',  
        hideBorders: true,
        //defaults:{bodyStyle:'padding:5px; margin:5px'},
        xtype: 'fieldset',
        ertype: 'fieldset'
    };
     
    this.config = this.mergeConfigs(this.config, customConfig);   
    this.allowBlank =  this.config.allowBlank;
    Er.FieldSet.superclass.constructor.call(this, this.config);
    this.initialize();
    if(Er.isDefined(this.items))
    {
	    for(var t= 0;   t < this.items.getCount(); t++)    // loop through all items in this container
	    {
	        var i = this.items.itemAt(t);        
	        if(i.xtype == 'radio')
	        {
	           i.on('check' , this.radioClicked);       
	           this.config.ertype = 'radiofieldset';
	        }
	    }
    }       
}
Ext.extend(Er.FieldSet, Ext.form.FieldSet, Er.Container);

Er.FieldSet.prototype.radioClicked = function(radio, value)
{
    if(value == true)
    {  
        var parent = this.ownerCt;
        if(parent.blocked == true)
            return;
        
        parent.blocked = true;    
        for(var t= 0;   t < parent.items.getCount(); t++)    // loop through all items in this container
        {
            var i = parent.items.itemAt(t); 
            if(i != this && i.xtype == 'radio')
            {
                i.setValue(false);       
            }
        }
        parent.selected = radio.name; 
        parent.blocked  = false;
    }
}

Er.FieldSet.prototype.validate = function()
{
    if(this.allowBlank == false && this. disabled == false)
    {
        if( ! Er.isDefined(this.selected))
        {
            this.getEl().frame("FF0000", 1, {duration: 1});
            this.getEl().highlight("FF0000", {attr: 'color', duration: 20});
            //Ext.Msg.alert('Validation', this.config.blankMessage);
            
            if(Er.validation == true)
                return false;
        }
    }
    return true;
}
//===========================================================================================================
//                                                     F I E L D S
//===========================================================================================================



// these are new methods that we add to all fields
Er.Field = new Object ({

    

    //  called before the superclass constructor is called
    mergeConfigs : function(typeConfig, customConfig)
    {
        cf = new Er.cloneObject(Er.FieldConfig);
        Ext.apply(cf, typeConfig);
        Ext.apply(cf, customConfig); 
        
        if(cf.allowBlank == false)
        {
           cf.fieldLabel = '<font color="red">*</font>&nbsp;' + cf.fieldLabel;
        }
        
        if(cf.fieldLabel == '')
        {
            cf.hideLabel = true;
        }
        return cf;
    },
    
    //  called after the superclass constructor is called
    initialize: function()
    {
        
    },
     
    getData : function() 
    {  
       var nam  = Er.isDefined(this.name) ? this.name : this.hiddenName;   
       var obj  = {};
       obj[nam] = this.getValue();   
       return obj;
    }
 
});

 
//===========================================================================================================
//                                        VALIDATION
Ext.apply(Ext.form.VTypes, {
 //   'phone': function(v){ return true},
 //   'url': function(v){ return true},
 //   'email': function(v){ return true},
  
   
    'zipcode': function(v)
        { 
            var numberRe = /^[0-9]5$/;
            return numberRe.test(v);
        },
    'zipocodeText': '5 digits expected', 
    
    'numeric': function(v)
        { 
            var numberRe = /^[0-9]*$/;
            return numberRe.test(v);
        },
    'numericText': 'Numbers only Please',    
    'phone10' : function(v)
        {
//            Ext.form.VTypes['phone10Text'] = 'Please enter a valid 10-digit phone number.';
//            if('United States' == form_personal_info.getForm().findField('country').getValue() || 'canada' == form_personal_info.getForm().findField('country').getValue())
//            {
//                var phoneRe = /^\(?\d{3}\)?\s*-?\s*\d{3}\s*-?\s*\d{4}$/;
//            }
//            else
//            {
//                if (v.length > 15)
//                {
//                    Ext.form.VTypes['phone10Text'] = 'Phone number must be less then 15 characters.';
//                    return false;
//                }
//                var phoneRe = /^\(?\d{1,}\)?\s*-?\s*\(?\d{1,}\)?\s*-?\s*\(?\d{1,}\)?\s*-?\s*\(?\d{1,}\)?\s*-?\s*\(?\d{1,}\)?\s*-?\s*$/;
//            }
            
            var phoneRe = /^\(?\d{3}\)?\s*-?\s*\d{3}\s*-?\s*\d{4}$/;
            return phoneRe.test(v);
        },
    'phone10Text' : 'Please enter a valid 10-digit phone number.',
    'phone_extension' : function(v)
        {
            var phoneRe = /^[0-9*#-]+$/;
            return phoneRe.test(v);
        },
    'phone_extensionText' : 'Please enter a valid numeric phone extension.'
});


//===========================================================================================================
Er.Label = function(txt)
{
   return new Ext.form.Label({name:'_erlabel',html: '<span class="x-form-item-label x-form-item">'+ txt +'</span>'});
}

/*
//===========================================================================================================
Er.Label = function(customConfig )
{
    this.config = {
      //  xtype: "label",
      //  cls: 'x-form-item-label x-form-item' //apply ext styles
    };
    this.config= this.mergeConfigs(this.config, customConfig);
    Er.form.Label.superclass.constructor.call(this, this.config); 
};
Ext.extend(Er.Label, Ext.form.Label, Er.Field);
*/


//===========================================================================================================
Er.ComboBoxField = function(customConfig)
{ 
    this.config = {}; 
    this.comboConfig = {
        forceSelection: true,  // disallows the user to type in their own value
        mode:'local',       
        xtype: 'combo',
        triggerAction: 'all',
        //valueField: 'pk',
        //listAlign: 'tr-br',  // for a list that sticks out to the left
        //listWidth: 300,     // for a wider list
        emptyText: 'Make a selection...'
    };
    
    this.countriesConfig ={
        store:      Er.CountriesArray,    
        fieldLabel: 'Country',
        hiddenName: 'country',
        otherValue: 'Other',
        emptyText:  'Select a country...'    
    };   
    this.statesConfig ={
        store:      Er.StatesArray,
        fieldLabel: 'State',
        hiddenName: 'state',    
        otherValue: 'ZZ - Other',
        emptyText:  'Select a state...'    
    };  
    this.provincesConfig ={
        store:      Er.ProvincesArray,
        fieldLabel: 'Province',
        hiddenName: 'province',    
        otherValue: 'ZZ - Other',
        emptyText:  'Select a province...'    
    };   
    this.govbranchesConfig ={
        store:      Er.GovBranchArray,
        fieldLabel: 'Branch of Government',
        hiddenName: 'gov_branch', 
        width:      400,
        listWidth:  400,   
        otherValue: 'X - Other',
        emptyText:  'Select a branch of government...'    
    };
    this.jobfunctionConfig ={
        store:      Er.JobFunctionArray,
        fieldLabel: 'Which category BEST describes your JOB FUNCTION/ CLASSIFICATION',
        hiddenName: 'job_function',    
        width:      400,
        listWidth:  400,
        otherValue: 'Z - Other',
        emptyText:  'Select a job function...'    
    };      
    this.agencyfunctionConfig ={
        store:      Er.AgencyFunctionArray,
        fieldLabel: 'What is the primary FUNCTION of your AGENCY/ DEPARTMENT',
        hiddenName: 'agency_function',   
        width:      400,
        listWidth:  400,
        otherValue: '99 - Other',
        emptyText:  'Select an agency/department...'    
    };
    this.areatechConfig ={
        store:      Er.AreaTechArray,
        fieldLabel: 'What area of technology are you most involved with?',
        hiddenName: 'area_of_tech', 
        width:      400,
     //   listWidth:  340,  
        otherValue: '99 - Other',
        emptyText:  'Select an area of technology...'    
    };
    this.auditConfig ={
         fieldLabel: 'To start your Free Annual subscription, <i>Government Technology</i> would normally ask that ' +
                    'you sign the request. For audit purposes and in lieu of a signature, would you note the month  ' +
                    'your were born in? This information is for verification purposes only. It will ' +
                    'not be shared with any outside parties.',
        hiddenName: 'audit', 
        labelSeparator: '&nbsp',
        emptyText:  'Select the month...'    
    };
    this.monthConfig ={
        store:      Er.MonthArray,
        fieldLabel: 'Month',
        hiddenName: 'month', 
        emptyText:  'Select the month...'  
    };
    this.howhearConfig ={
        store:      Er.HowHearArray,
        fieldLabel: 'How did you hear about us?',
        hiddenName: 'how_hear', 
        listWidth:  340,  
        otherValue: 'Z - Other' 
    };
    switch(customConfig.stockDataSource)
    {
    case Er.COUNTRIES:
        this.config = Ext.apply(this.comboConfig,  this.countriesConfig);
        break;
    case Er.STATES:
        this.config = Ext.apply(this.comboConfig,  this.statesConfig);
        break;
    case Er.STATES_PROVINCES:
        this.config = Ext.apply(this.comboConfig,  this.statesConfig);
        this.config.store =  Er.StatesArray.concat(Er.ProvincesArray).sort();
        break;    
    case Er.PROVINCES:
        this.config = Ext.apply(this.comboConfig,  this.provincesConfig);
        break;    
    case Er.GOV_BRANCHES:
        this.config = Ext.apply(this.comboConfig,  this.govbranchesConfig);
        break;
    case Er.JOB_FUNCTIONS:
        this.config = Ext.apply(this.comboConfig,  this.jobfunctionConfig);
        break;
    case Er.AGENCY_FUNCTION:
        this.config = Ext.apply(this.comboConfig,  this.agencyfunctionConfig);
        break;
    case Er.AREA_TECH:
        this.config = Ext.apply(this.comboConfig,  this.areatechConfig);
        break; 
    case Er.AUDIT:
        this.config = Ext.apply(this.comboConfig,  this.auditConfig);
        this.config.store = ['R - Refuse to answer'];
        this.config.store = this.config.store.concat(Er.MonthArray);
        break; 
    case Er.MONTH:
        this.config = Ext.apply(this.comboConfig,  this.monthConfig);
        break;  
    case Er.HOW_HEAR:
        this.config = Ext.apply(this.comboConfig,  this.howhearConfig);
        break;                     
    default:
        this.config = Ext.apply(this.config, this.comboConfig);
        if(! Er.isDefined(customConfig.store))
        {
            var readerConfig = {
                totalProperty: "totalRecords",      
                root: "data"                               
            }
            var dr = new Array(); 
            dr.push( {name: customConfig.displayField});
            if (Er.isDefined(customConfig.valueField) )
            {
                dr.push( {name: customConfig.valueField} );
            }
            else
            {
                customConfig.valueField = customConfig.displayField;
            }
            this.dataRecord    = Ext.data.Record.create(dr);       
            this.config.store  = new Ext.data.Store({ reader: new Ext.data.JsonReader(readerConfig, this.dataRecord) }); 
        }
        break;
    }
    
    this.config= this.mergeConfigs(this.config, customConfig);
    Er.ComboBoxField.superclass.constructor.call(this, this.config); 
    this.initialize();
    
    if(customConfig.stockDataSource == Er.COUNTRIES)
    {
        this.setValue('USA');
    }
    
    if(Er.isDefined(this.config.dataSource))
    {
        this.config.dataSource.addContainer(this);
    }

    if(Er.isDefined(this.config.otherField))
    {
        this.on('select' , this.check4Other);
        this.config.otherField.disable();
    }
    else
    {
        this.on('select' , this.onSelectValue);
    }
} 
Ext.extend(Er.ComboBoxField, Ext.form.ComboBox, Er.Field);

Er.ComboBoxField.prototype.setData = function(firstRecord, ar)
{
    this.config.store.loadData(ar);
}

Er.ComboBoxField.prototype.check4Other = function(field, dataRecord, index) 
{
with (this){
    
    this.onSelectValue(field, dataRecord, index);
    
    if(getValue()== config.otherValue){
        config.otherField.enable();
        // at the end of this call the focus is set to this element, so to set the focus somewhere else
        // we use a timeout
        setTimeout("Ext.get('"+config.otherField.id +"').dom.focus()", 100);
        config.otherField.getEl().frame("4080FF", 1, {duration: 1});    
    }
    else
    {
        config.otherField.setValue('');
        config.otherField.clearInvalid();
        config.otherField.disable();
    }
}
}

Er.ComboBoxField.prototype.onSelectValue = function(field, dataRecord, index) 
{
    
    //this.stored_value = this.getRawValue();
    if(this.config.erValueField)
    {
        this.storedDisplay = this.getRawValue();
        var evalstr = "dataRecord.json."+this.config.erValueField ;
        this.storedValue = eval(evalstr);
    }
}

Ext.override(Er.ComboBoxField, { 
    // getValue should return 1 and  0 instead of true and false
    getValue : function()
    { 
	    if(this.config.erValueField)
	    {    
	        var raw = Er.ComboBoxField.superclass.getRawValue.call(this);
	        return raw == this.storedDisplay ? this.storedValue : raw;
	    }
	    else
	    {
	        return Er.ComboBoxField.superclass.getValue.call(this); 
	    }
    }
});     

//===========================================================================================================
Er.DateField = function(customConfig)
{
    this.dateConfig = {
        format: 'M j Y',
        altFormats: 'M j Y|M j Y g:iA|M d Y g:iA|Y-m-d G:i:s|m/d/y|m/d/Y',
        xtype: 'datefield'
    };
    
    this.config = this.mergeConfigs(this.dateConfig, customConfig);
    Er.DateField.superclass.constructor.call(this, this.config); 
    this.initialize();
}
Ext.extend(Er.DateField, Ext.form.DateField, Er.Field);

//===========================================================================================================
Er.TextField = function(customConfig)
{   
    this.textFieldConfig = {
        xtype: 'textfield',
        autoQueryTrigger: 3,    // number of characters that have to be entered
        queryDelay : 500           // number of milliseconds before we call loadData()
    };
/*    
    if(Er.isDefined(customConfig.autoQueryDS ))
    {
        customConfig.enableKeyEvents = true;
    }
*/    
    this.config = this.mergeConfigs(this.textFieldConfig, customConfig);
    Er.TextField.superclass.constructor.call(this, this.config); 
    this.initialize();
    
/*    
    if(Er.isDefined(customConfig.autoQueryDS ))
    {
        this.on('keypress' , Er.TextFieldOnChange);
        //alert('autoCompleteDS');
    }
*/    
}
Ext.extend(Er.TextField, Ext.form.TextField, Er.Field);

/*
Er.TextFieldOnChange = function(field, event)
{
    //alert(field.getValue());
    if(field.getValue().length >= field.config.autoQueryTrigger)
    {
         //window.setTimeout(field.config.autoQueryDS.loadData.call(field.config.autoQueryDS), field.config.queryDelay);  
         field.config.autoQueryDS.loadData();  
          
    }
}
*/
//===========================================================================================================
Er.UrlField = function(customConfig)
{   
    this.urlFieldConfig = {
        xtype: 'textfield',
        vtype: 'url'
    };
    this.config = this.mergeConfigs(this.urlFieldConfig, customConfig);
    Er.UrlField.superclass.constructor.call(this, this.config); 
    this.initialize();
}
Ext.extend(Er.UrlField, Ext.form.TextField, Er.Field);

//===========================================================================================================
Er.ZipField = function(customConfig)
{   
    this.zipFieldConfig = {
        xtype: 'textfield',
        vtype: 'zipcode'
    };
    this.config = this.mergeConfigs(this.zipFieldConfig, customConfig);
    Er.ZipField.superclass.constructor.call(this, this.config); 
    this.initialize();
}
Ext.extend(Er.ZipField, Ext.form.TextField, Er.Field);

//===========================================================================================================
Er.EmailField = function(customConfig)
{   
    this.emailFieldConfig = {
        vtype: 'email',
        xtype: 'textfield'
    };
    this.config = this.mergeConfigs(this.emailFieldConfig, customConfig);
    Er.EmailField.superclass.constructor.call(this, this.config); 
    this.initialize();
}
Ext.extend(Er.EmailField, Ext.form.TextField, Er.Field);

//===========================================================================================================
Er.PhoneField = function(customConfig)
{   
    this.phoneFieldConfig = {
        xtype: 'textfield',
        vtype: 'phone10'
    };
    this.config = this.mergeConfigs(this.phoneFieldConfig, customConfig);
    Er.PhoneField.superclass.constructor.call(this, this.config); 
    this.initialize();
}
Ext.extend(Er.PhoneField, Ext.form.TextField, Er.Field);

//===========================================================================================================
Er.NumericField = function(customConfig)
{   
    this.numericFieldConfig = {
        autocomplete: 'off'
    };
    this.config = this.mergeConfigs(this.numericFieldConfig, customConfig);
    Er.NumericField.superclass.constructor.call(this, this.config); 
    this.initialize();
}
Ext.extend(Er.NumericField, Ext.form.NumberField, Er.Field);

//===========================================================================================================
Er.TextAreaField = function(customConfig)
{    
    
    this.textAreaConfig = {
        xtype: 'textarea',
        height: 100
    };
    this.config = this.mergeConfigs(this.textAreaConfig, customConfig);
    Er.TextAreaField.superclass.constructor.call(this, this.config); 
    this.initialize();
}
Ext.extend(Er.TextAreaField, Ext.form.TextArea, Er.Field);

//===========================================================================================================
Er.CheckBoxField = function(customConfig)
{        
    this.checkBoxConfig = {
        xtype: 'checkbox'
    }
    
    this.config = this.mergeConfigs(this.checkBoxConfig, customConfig);
    delete this.config.width;  // need this for IE
    Er.CheckBoxField.superclass.constructor.call(this, this.config); 
    this.initialize();
}
Ext.extend(Er.CheckBoxField, Ext.form.Checkbox, Er.Field);
Ext.override(Er.CheckBoxField, { 
    // getValue should return 1 and  0 instead of true and false
    getValue : function(){ 
        return Er.CheckBoxField.superclass.getValue.call(this)== true ? 1: 0; 
    }
});

//===========================================================================================================
Er.RadioButtonField = function(customConfig)
{    
    this.radioConfig = {
        xtype: 'radio'
    };
    this.config = this.mergeConfigs(this.radioConfig, customConfig);
    Er.RadioButtonField.superclass.constructor.call(this, this.config);
    this.initialize(); 
}
Ext.extend(Er.RadioButtonField, Ext.form.Radio, Er.Field);
Ext.override(Er.RadioButtonField, { 
    // getValue should return 1 and  0 instead of true and false
    getValue : function(){ 
        return Er.RadioButtonField.superclass.getValue.call(this)== true ? 1: 0; 
    }
});     

//===========================================================================================================
Er.Button = function(customConfig)
{  
    this.config = {
        xtype: 'button',
        minWidth: 70
        //style:'margin:0px;'  set this to add some room around the buttons
        //bodyStyle:'padding:30px;' //  can this be deleted ?
    };
   
    Ext.apply(this.config, customConfig);
    Er.Button.superclass.constructor.call(this, this.config); 
}
Ext.extend(Er.Button, Ext.Button);


// ------- the system globals -------------
Er.TheConnectionHandler = new Er.ConnectionHandler();
Er.TheDataSources       = new Ext.util.MixedCollection();
Er.validation           = true;  // set to false to disable data validation for debug purposes
