//----------------------------------------------------------------------------//
    function GetElement ( ID )
    {
        if ( Browser == 'Internet Explorer' )
        {
            var Element = document.all[ID] ;
        }
        if ( Browser == 'Netscape Navigator' )
        {
            var Element = document.layer[ID] ;
        }
        if ( Browser == 'Mozilla / Mozilla Firefox' || Browser == 'Opera' )
        {
            var Element = document.getElementById(ID) ;
        }
        return Element ;
    }
//----------------------------------------------------------------------------//
    function StartList ( )
    {
        if ( document.all && document.getElementById )
        {
            NavigationRoot = document.getElementById ( 'Navigation' ) ;
            if ( NavigationRoot != null )
            {
                for ( Index = 0 ; Index < NavigationRoot.childNodes.length; Index++ )
                {
                    Node = NavigationRoot.childNodes[Index] ;
                    if ( Node.nodeName == 'LI' )
                    {
                        Node.onmouseover = function ( )
                        {
                            this.className += ' Over' ;
                        }
                        Node.onmouseout=function ( )
                        {
                            this.className=this.className.replace ( ' Over' , '' ) ;
                        }
                    }
                }
            }
        }
    }
//----------------------------------------------------------------------------//
    function UpdateZIndex ( ID , Number )
    {
        var Element = GetElement ( ID ) ;
        if ( Element != null )
        {
            Element.style.zIndex = Number ;
        }
    }
//----------------------------------------------------------------------------//
    function AddColleaguesEMailAddresses ( )
    {
        var Cell = GetElement ( 'ColleaguesEMailAddresses' ) ;
        Cell.innerHTML += '<br/><input type="text" name="ColleaguesEMailAddresses[]" value="" size="50" maxlength="255"/>' ;
    }
//----------------------------------------------------------------------------//
    function PopUp ( URL , Width , Height )
    {
        var Left = ( screen.width - Width ) / 2 ;
        var Top = ( screen.height - Height ) / 2 ;
        Day = new Date();
        ID = Day.getTime();
        eval("Page"+ID+"=window.open('" + URL + "','" + ID + "','height="+Height+",width="+Width+",top='+Top+',left='+Left+',toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0');");
    }
//----------------------------------------------------------------------------//


//----------------------------------------------------------------------------//
    window.onload = function ( )
    {
        var SearchEngineContent = GetElement ( 'SearchEngineContent' ) ;
        var MiddleColumn = GetElement ( 'MiddleColumn' ) ;
        if ( MiddleColumn != null && SearchEngineContent != null )
        {
            MiddleColumn.innerHTML = SearchEngineContent.innerHTML ;
        }
        StartList ( ) ;
    }
//----------------------------------------------------------------------------//



//----------------------------------------------------------------------------//
    function PopUp ( URL , Width , Height )
    {
        var Left = ( screen.width - Width ) / 2 ;
        var Top = ( screen.height - Height ) / 2 ;
        Day = new Date();
        ID = Day.getTime();
        eval("Page"+ID+"=window.open('" + URL + "','" + ID + "','height="+Height+",width="+Width+",top='+Top+',left='+Left+',toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0');");
    }
//----------------------------------------------------------------------------//


//----------------------------------------------------------------------------//
    var Browser ;
//----------------------------------------------------------------------------//
    if ( navigator.userAgent.indexOf ( 'Opera' ) != -1 && document.getElementById )
    {
        Browser = 'Opera' ;
    }
    if ( document.all )
    {
        Browser = 'Internet Explorer' ;
    }
    if ( document.layers )
    {
        Browser = 'Netscape Navigator' ;
    }
    if ( !document.all && document.getElementById )
    {
        Browser = 'Mozilla / Mozilla Firefox' ;
    }
//----------------------------------------------------------------------------//

function fValConfig()
{
    /*  Globals.  Modify these to suit your setup
    ------------------------------------------- */

    //  Attribute used for fValidate Validator codes
    this.code = 'alt';

    //  Attribute used for custom error messages (override built-in error messages)
    this.emsg = 'emsg';

    //  Attribute used for pattern with custom validator type
    this.pattern = 'pattern';

    //  Change this to the classname you want for the error highlighting
    this.errorClass = 'HighlightedError';

    //  If you wish fValidate to use only single classNames for errors
    this.useSingleClassNames = false; // or true

    //  This is the even that triggers the clearing of the errorClass hilighting
    this.clearEvent = 'change'; // 'change' | 'blur' | null

    //  For browsers that don't support attachEvent or addEventListere - override existing events for error reverting?
    this.eventOverride = false;

    //  If the bConfirm flag is set to true, the users will be prompted with CONFIRM box with this message
    //  See your language file for this value
    this.confirmMsg = fvalidate.i18n.config.confirmMsg;

    //  If user cancels CONFIRM, then this message will be alerted.  If you don't want this alert to show, then
    //  empty the variable (  this.confirmAbortMsg = '';  )
    //  See your langauge file for this value
    this.confirmAbortMsg = fvalidate.i18n.config.confirmAbortMsg;

    //  Enter the name/id of your form's submit button here.  Can be a string or array of strings
    this.submitButton = ['Submit'];

    //  Enter the name/id of your form's reset button here
    this.resetButton = 'Reset';

    //  Ender the name or id of the SELECT object here. Make sure you pay attention to the values (CC Types)
    //  used in the case statement for the function validateCC()
    this.ccType = 'CreditCardType';

    //  NOTE: The config value below exists for backwards compatibility with fValidate 3.55b.  If you have a newer
    //  version, use the above this.ccType instead.
    //  Enter the DOM name of the SELECT object here. Make sure you pay attention to the values (CC Types)
    //  used in the case statement for the function validateCC()
    this.ccTypeObj = 'form1.CreditCardType';

    //  Element where box errors will appear
    this.boxError = 'Errors';

    //  Prefix given to all error paragraphs in box error mode
    this.boxErrorPrefix = 'fv_error_';
}
//  EOF


/***************************************************************************************************
*
*-- Form validation script by Peter Bailey, Copyright (c) 2001-2003
*   Version 5.01b
*   Updated on Feb 07, 2004
*   www.peterbailey.net
*   me@peterbailey.net
*
*   IF YOU USE THIS SCRIPT, GIVE ME CREDIT PLEASE =)
*
*   Visit http://www.peterbailey.net/fValidate/ for more info
*
*   Feel free to contact me with any questions, comments, problems, or suggestions
*
*   Note: This document most easily read with tab spacing set to 4
*
*******************************************************************************************************/

/*  Create static fvalidate object
------------------------------------------- */
if ( typeof fvalidate == 'undefined' )
{
    var fvalidate = new Object();
}

/*  Generic event handling
------------------------------------------- */
fvalidate.addEvent = function( obj, evt, fn, useCapture )
{
    if ( typeof obj.attachEvent != 'undefined' )
    {
        obj.attachEvent( "on" + evt, fn );
    }
    else if ( typeof obj.attachEventListener != 'undefined' )
    {
        obj.addEventListener( evt, fn, Boolean( useCapture ) );
    }
}
fvalidate.addEvents = function( obj, evts, fn, useCapture )
{
    var i = 0, evt;
    while( evt = evts[i++] )
    {
        this.addEvent( obj, evt, fn, Boolean( useCapture ) );
    }
}

/*  Main validation routine
------------------------------------------- */
function validateForm( f, bConfirm, bDisable, bDisableR, groupError, errorMode )
{
    //  Set defaults
    bConfirm    = Boolean( bConfirm );
    bDisable    = Boolean( bDisable );
    bDisableR   = Boolean( bDisableR );
    groupError  = Boolean( groupError );
    errorMode   = ( typeof errorMode != 'undefined' ) ? parseInt( errorMode, 10 ) : 0;

    //  Init vars and fValidate object
    var params, fvCode, type;
    if ( typeof f.fv == 'undefined' )
    {
        f.fv = new fValidate( f, errorMode, groupError );
    } else {
        f.fv._reset();
        f.fv.errorMode = errorMode;
    }

    //  Loop through all form elements
    var elem, i = 0, attr = f.fv.config.code;
    while ( elem = f.elements[i++] )
    {
        //  Skip fieldsets
        if ( elem.nodeName == "FIELDSET" ) continue;

        //  Does element have validator attribute? (short-circuit check)
        fvCode          = ( elem[attr] ) ? elem[attr] : elem.getAttribute( attr );
        if ( !( typeof fvCode == 'undefined' || fvCode == null || fvCode == "" ) )
        {
            //  Set params, validation type, and validation state
            params          = fvCode.split( "|" );
            type            = params[0];
            elem.validated  = true;

            //  Valid validator type?
            if ( typeof f.fv[type] == 'undefined' )
            {
                f.fv.devError( [type, elem.name], 'notFound' );
                return false;
            }

            //  Check for modifiers
            switch( params.last() )
            {
                case 'bok'  :   //  bok requested
                    params = params.reduce( 1, 1 );
                    elem.bok = true;
                    break;
                case 'if'   :   //  Conditional validation requested
                    params = params.reduce( 1, 1 );
                    elem._if_ = true;
                    break;
                case 'then' :   //  Conditional validation requested
                    params = params.reduce( 1, 1 );
                    elem._then_ = true;
                    break;
                default     :   //  No modifiers
                    params = params.reduce( 1, 0 );

            }

            //  Is element an array?
            if ( /radio|checkbox/.test( elem.type ) )
            {
                //  Set group property
                elem.group = f.elements[elem.name];
            }

            //  Add events if not already added
            if ( typeof elem.fName == 'undefined' )
            {
                //  If element is an array
                if ( typeof elem.group != 'undefined' )
                {
                    for ( var j = 0; j < elem.group.length; j++ )
                    {
                        //  Apply event-function to each child
                        if ( f.fv.config.clearEvent != null )
                        {
                        //  fvalidate.addEvent( elem.group.item( j ), fv.config.clearEvent, fv.revertError, false );
                            addEvent( elem.group.item( j ), f.fv.config.clearEvent, f.fv, 'revertError', false );
                        }
                    }
                }
                else
                {
                    //  Apply event-function to element
                //  fvalidate.addEvent( elem, fv.config.clearEvent, fv.revertError, false );
                    addEvent( elem, f.fv.config.clearEvent, f.fv, 'revertError', false );
                }
            }

            //  Set formatted name, current element
            elem.fName  = elem.name.format();
            f.fv.elem       = elem;
            f.fv.type       = type;

            //  Create function to call the proper validator method of the fValidate class
            var func = new Function( "obj", "method", "obj[method]( " + params.toArgString() + " );" );
            func( f.fv, type );

            //  If element test failed AND group error is off, return false
            if ( elem.validated == false && groupError == false ) return false;

            //  Clear error if field okay
            if ( elem.validated == true ) f.fv.revertError();
        }
    } //    end of element loop

    //  If group error, show it
    if ( groupError ) f.fv.showGroupError();

    //  Return false if errors found
    if ( f.fv.errors.length > 0 ) return false;

    //  Show pre-submission confirmation
    if ( bConfirm && !confirm( f.fv.config.confirmMsg ) )
    {
        if ( f.fv.config.confirmAbortMsg != '' ) alert( f.fv.config.confirmAbortMsg );
        return false;
    }

    //  Disable reset and/or submit buttons if requested
    if ( bDisable )
    {
        if ( typeof f.fv.config.submitButton == 'object' )
        {
            var sb, j = 0;
            while( sb = f.fv.config.submitButton[j++] )
            {
                if ( f.fv.elementExists( sb ) )
                {
                    f.elements[sb].disabled = true;
                }
            }
        }
        else if ( f.fv.elementExists( f.fv.config.submitButton ) )
        {
            f.elements[f.fv.config.submitButton].disabled = true;
        }
    }
    if ( bDisableR && f.fv.elementExists( f.fv.config.resetButton ) )
    {
        f.elements[f.fv.config.resetButton].disabled = true;
    }

    //  Successful Validation.  Submit form
    return true;

    function addEvent( elem, evt, obj, method, capture )
    {
        var self = elem;
        if ( typeof elem.attachEvent != 'undefined' )
        {
            elem.attachEvent( "on" + evt, function() { obj[method]( self ) } );
        }
        else if ( typeof elem.addEventListener != 'undefined' )
        {
            elem.addEventListener( evt, function() { obj[method]( self ) }, capture );
        }
        else if ( f.fv.config.eventOverride )
        {
            eleme['on' + evt] = function() { obj[method]( self ) };
        }
    }
}

/*  Constructor
------------------------------------------- */
function fValidate( f, errorMode, groupError )
{
    var self        = this;
    this.form       = f;
    this.errorMode  = errorMode;
    this.groupError = groupError;
    this.errors     = new Array();
    this.validated  = true;
    this.config     = new fValConfig();
    this.i18n       = fvalidate.i18n;

    //  Add reset action to clear visual error cues
    f.onreset = function()
    {
        var elem, i = 0;
        while ( elem = this.elements[i++] )
        {
            self.revertError( elem );
        }
    }

    addLabelProperties();

    //  Parses form and adds label properties to elements that have one specified
    function addLabelProperties()
    {
        //  Collect all label elements in form, init vars
        if ( typeof f.getElementsByTagName == 'undefined' ) return;
        var labels = f.getElementsByTagName( "label" );
        var label, i = j = 0;
        var elem;

        //  Loop through labels retrieved
        while ( label = labels[i++] )
        {
            //  For Opera 6
            if ( typeof label.htmlFor == 'undefined' ) return;

            //  Retrieve element
            elem = f.elements[label.htmlFor];
            if ( typeof elem == 'undefined' )
            {   //  No element found for label
                self.devError( [label.htmlFor], 'noLabel' );
            }
            else if ( typeof elem.label != 'undefined' )
            {   //  label property already added
                continue;
            }
            else if ( typeof elem.length != 'undefined' && elem.length > 1 && elem.nodeName != 'SELECT' )
            {   //  For arrayed elements
                for ( j = 0; j < elem.length; j++ )
                {
                    elem.item( j ).label = label;
                }
            }
            //  Regular label
            elem.label = label;
        }
    }
}

/*  Reset for another validation
------------------------------------------- */
fValidate.prototype._reset = function()
{
    this.errors     = new Array();
    this.showErrors = new Array();
}

/*  Checks if element exists in form
------------------------------------------- */
fValidate.prototype.elementExists = function( elemName )
{
    return Boolean( typeof this.form.elements[elemName] != 'undefined' );
}

/*  Receives error message and determines action
------------------------------------------- */
fValidate.prototype.throwError = function( args, which )
{
    var elem  = this.elem;

    //  Arrayed element?
    if ( typeof elem.name == 'undefined' )
    {
        elem = elem[0];
    }

    //  Bok requested AND element blank OR conditional validation?
    if ( elem.bok && this.isBlank() )
    {   //  skip
        elem.validated = true;
        return;
    }

    //  Part of a conditional validation?
    if ( elem.cv )
    {
        return;
    }

    //  Set failsafe to false
    elem.validated = false;

    //  Create error message
    which   = this.setArg( which, 0 );
    args    = this.setArg( args, [] );
    emsgElem = ( typeof this.elem.getAttribute == "undefined" ) ?
            this.elem[0]:
            this.elem;
    if ( emsgElem.getAttribute( this.config.emsg ) )
    {
        var error = emsgElem.getAttribute( this.config.emsg );
    }
    var error = this.translateMessage( args, this.i18n.errors[this.type][which] );

    //  Group error mode?
    if ( this.groupError )
    {
        //  Push error onto stack
        this.errors.push( {'elem':elem, 'msg': error} );
    }
    else
    {
        //  Process error message
        this.showError( error, false, emsgElem );

        var focusElem = ( typeof elem.fields != 'undefined' )?
            elem.fields[0]:
            elem;

        //  Focus and select elements, if possible
        this.selectFocus( focusElem );
    }
}


/*  Shows error message to user
------------------------------------------- */
fValidate.prototype.showError = function( emsg, last, elem )
{
    //  Set variables
    var self        = this,
        elem        = this.setArg( elem, this.elem ),
        isHidden    = Boolean( elem.type == 'hidden' ),
        label       = ( isHidden ) ? null : elem.label || null,
        emsg        = ( elem.getAttribute( this.config.emsg ) ) ? elem.getAttribute( this.config.emsg ).replace( /\\n/g, "\n" ) : emsg,
        errorClass  = this.config.errorClass,
        singleCSS   = this.config.useSingleClassNames;

    if ( typeof this.showErrors == 'undefined' ) this.showErrors = new Array();

    //  Determine which error modes to use
    switch( this.errorMode )
    {   //  This represents all possible combinations
        case 0  : alertError(); break;
        case 1  : inputError(); break;
        case 2  : labelError(); break;
        case 3  : appendError(); break;
        case 4  : boxError(); break;
        case 5  : inputError(); labelError(); break;
        case 6  : inputError(); appendError(); break;
        case 7  : inputError(); boxError(); break;
        case 8  : inputError(); alertError(); break;
        case 9  : labelError(); appendError(); break;
        case 10 : labelError(); boxError(); break;
        case 11 : labelError(); alertError(); break;
        case 12 : appendError(); boxError(); break;
        case 13 : appendError(); alertError(); break;
        case 14 : boxError(); alertError(); break;
        case 15 : inputError(); labelError(); appendError(); break;
        case 16 : inputError(); labelError(); boxError(); break;
        case 17 : inputError(); labelError(); alertError(); break;
        case 18 : inputError(); appendError(); boxError(); break;
        case 19 : inputError(); appendError(); alertError(); break;
        case 20 : inputError(); boxError(); alertError(); break;
        case 21 : labelError(); appendError(); boxError(); break;
        case 22 : labelError(); appendError(); alertError(); break;
        case 23 : appendError(); boxError(); alertError(); break;
        case 24 : inputError(); labelError(); appendError(); boxError(); break;
        case 25 : inputError(); labelError(); appendError(); alertError(); break;
        case 26 : inputError(); appendError(); boxError(); alertError(); break;
        case 27 : labelError(); appendError(); boxError(); alertError(); break;
        case 28 : inputError(); labelError(); appendError(); boxError(); alertError(); break;
    }
    //  Regular alert error
    function alertError()
    {
        if ( self.groupError ) self.showErrors.push( emsg );
        else alert( emsg );
        if ( last ) alert( self.i18n.groupAlert + self.showErrors.join( "\n\n- " ) );
    }
    //  Applies class to form element
    function inputError()
    {
        if ( ( typeof elem.length != 'undefined' && elem.length > 1 && elem.nodeName != 'SELECT' ) || isHidden )
        {
            var subelem, i = 0;
            while( subelem = ( isHidden ) ? elem.fields[i++] : elem.item( i++ ) )
            {
                if ( subelem.className != '' && singleCSS )
                {
                    subelem.revertClass = subelem.className;
                    subelem.className = errorClass;
                } else {
                    self.addCSSClass( subelem, errorClass );
                }
            }
        }
        else
        {
            if ( singleCSS )
            {
                elem.revertClass = elem.className;
                elem.className = errorClass;
            } else {
                self.addCSSClass( elem, errorClass );
            }
        }
    }
    //  Applies class to element's label
    function labelError()
    {
        if ( label == null ) return;
        if ( self.config.useSingleClassNames )
        {
            label.className = errorClass;
        } else {
            self.addCSSClass( label, errorClass );
        }

    }
    //  Appends error message to element's label
    function appendError()
    {
        if ( label == null || typeof label.innerHTML == 'undefined' ) return;
        if ( typeof label.original == 'undefined' )
            label.original = label.innerHTML;
        label.innerHTML = label.original + " - " + emsg.toHTML();
    }
    //  Appends Error message to pre-defined element
    function boxError()
    {
        if ( typeof self.boxError == 'undefined' ) self.boxError = document.getElementById( self.config.boxError );
        if ( self.boxError == null )
        {
            self.devError( [self.config.boxError], 'noBox' );
            return;
        }
        if ( typeof self.elem.name == 'undefined' || self.elem.name == "" )
        {
            self.devError( [self.elem[self.config.code]], 'missingName' );
            return;
        }
        var errorId = self.config.boxErrorPrefix + self.elem.name,
            errorElem;
        if ( errorElem = document.getElementById( errorId ) ) // short-circuit
        {
            errorElem.firstChild.nodeValue = emsg.toHTML();
        }
        else
        {
            errorElem = document.createHTMLElement( 'li', { id: errorId, 'innerHTML': emsg.toHTML(), title: self.i18n.boxToolTip } );
            self.boxError.appendChild( errorElem );
            errorElem.onclick = function()
            {
                var elem = self.form.elements[this.id.replace( self.config.boxErrorPrefix, "" )];
                if ( typeof elem.fields != 'undefined' ) elem = elem.fields[0];
                if ( typeof elem.select != 'undefined' ) elem.select();
                if ( typeof elem.focus != 'undefined' ) elem.focus();
            }
        }
        self.boxError.style.display = "block";
    }
}

/*  Handles element className manipulation
------------------------------------------- */
fValidate.prototype.removeCSSClass = function( elem, className )
{
    elem.className = elem.className.replace( className, "" ).trim();
}
fValidate.prototype.addCSSClass = function( elem, className )
{
    this.removeCSSClass( elem, className );
    elem.className = ( elem.className + " " + className ).trim();
}

/*  Processes errors in stack for group error mode
------------------------------------------- */
fValidate.prototype.showGroupError = function()
{
    for ( var error, firstElem, i = 0; ( error = this.errors[i] ); i++ )
    {
        if ( i == 0 ) firstElem = error.elem;
        this.elem = error.elem;
        this.showError( error.msg, Boolean( i == ( this.errors.length - 1 ) ) );
    }
    // var focusElem = ( typeof firstElem.fields != 'undefined' ) ? firstElem.fields[0] : firstElem ;
    // this.selectFocus( focusElem );
}

/*  Reverts any visible error notification upon event
------------------------------------------- */
fValidate.prototype.revertError = function( elem )
{
    elem = this.setArg( elem, this.elem );
    var isHidden    = Boolean( elem.type == 'hidden' ),
        errorClass  = this.config.errorClass,
        i           = 0,
        errorElem,
        subelem;

    if ( ( typeof elem.length != 'undefined' && elem.length > 1 && elem.nodeName != 'SELECT' ) || isHidden )
    {
        if ( isHidden && typeof elem.fields != 'undefined' )
        {
            while( subelem = ( isHidden ) ? elem.fields[i++] : elem.item( i++ ) )
            {
                if ( typeof subelem.revertClass != 'undefined' )
                {
                    subelem.className = subelem.revertClass;
                }
            }
        }
    } else {
        if ( this.config.useSingleClassNames )
        {
            if ( typeof subElement.revertClass != 'undefined' )
            {
                elem.className = elem.revertClass;
            }
        } else {
            this.removeCSSClass( elem, errorClass );
        }
    }
    if ( typeof elem.label != 'undefined' )
    {
        if ( this.config.useSingleClassNames )
        {
            elem.label.className = '';
        } else {
            this.removeCSSClass( elem.label, errorClass );
        }
        elem.label.innerHTML = ( elem.label.original || elem.label.innerHTML );
    }
    if ( typeof this.boxError != 'undefined' )
    {
        if ( typeof this.boxError.normalize != 'undefined' ) this.boxError.normalize();
        if ( errorElem = document.getElementById( this.config.boxErrorPrefix + elem.name ) )
        {
            this.boxError.removeChild( errorElem );
        }
        if ( this.boxError.childNodes.length == 0 ) this.boxError.style.display = "none";
    }
}

/*  Focus and select elements, if possible
------------------------------------------- */
fValidate.prototype.selectFocus = function( elem )
{
    if ( typeof elem.select != 'undefined' ) elem.select();
    if ( typeof elem.focus != 'undefined' )  elem.focus();
}

/*  Developer assistance method - shows error if validator/element-type mismatch
------------------------------------------- */
fValidate.prototype.typeMismatch = function()
{
    var pats = {
        'text':     'text|password|textarea',
        'ta':       'textarea',
        'hidden':   'hidden',
        's1':       'select-one',
        'sm':       'select-multiple',
        'select':   'select-one|select-multiple',
        'rg':       'radio',
        'radio':    'radio',
        'cb':       'checkbox',
        'file':     'file'
        };
    var fail        = false,
        expected    = new Array(),
        result = key = type = regex = "";
    for ( var i = 0; i < arguments.length; i++ )
    {
        type    = pats[arguments[i]];
        regex   = new RegExp( type );
        result  += ( regex.test( this.elem.type ) ) ? "1" : "0";
        key     += "0";
        expected.push( type );
    }
    if ( key ^ result == 0 )
    {
        this.devError( [this.elem.fName, this.elem.type, expected.join( "|" ).replace( /\|/g, this.i18n.or )], 'mismatch' );
        this.elem.validated = false;
        return true;
    }
    return false;
}

/*  Returns value(s) of reference element passed
------------------------------------------- */
fValidate.prototype.getValue = function( elem )
{
    switch ( elem.type )
    {
        case 'text' :
        case 'password' :
        case 'textarea' :
        case 'hidden' :
        case 'file' :
            return elem.value;
        case 'radio':
        case 'select-single':
            if ( typeof elem.length == 'undefined' )
            {
                return elem.value;
            } else {
                for ( var i = 0; i < elem.length; i++ )
                {
                    choice = ( elem.type == 'radio' ) ? "checked" : "selected";
                    if ( elem[i][choice] )
                    {
                        return elem[i].value;
                    }
                }
            }
        case 'select-multiple' :
        case 'checkbox' :
            if ( typeof elem.length == 'undefined' )
            {
                return elem.value
            } else {
                var returnValues = new Array();
                for ( var i = 0; i < elem.length; i++ )
                {
                    choice = ( elem.type == 'checkbox' ) ? "checked" : "selected";
                    if ( elem[i][choice] )
                    {
                        returnValues.push( elem[i].value );
                    }
                }
                return returnValues;
            }
        default: return null;
    }
}

/*  Generic argument setting method
------------------------------------------- */
fValidate.prototype.setArg = function( arg, def )
{
    return ( typeof arg == 'undefined' || arg == '' || arg == null ) ? def : arg;
}

/*  Blank checker.  Optional string argument for evaluating element other than current
------------------------------------------- */
fValidate.prototype.isBlank = function( el )
{
    var elem = this.form.elements[el] || this.elem;
    return Boolean( /^\s*$/.test( elem.value ) );
}

/*  Translates messages using language file
------------------------------------------- */
fValidate.prototype.translateMessage = function( args, format )
{
    var msg     = ""
    for ( var i = 0; i < format.length; i++ )
    {
            msg += ( typeof format[i] == 'number' ) ? args[format[i]] : format[i];
    }
    return msg;
}

/*  Throws developer errors
------------------------------------------- */
fValidate.prototype.devError = function( args, which )
{
    if ( typeof args == 'string' )
    {
        which = args;
        args = [];
    }
    which = this.setArg( which, this.type );
    var format = this.i18n.devErrors[which];
    var a = [
        this.i18n.devErrors.lines[0],
        '----------------------------------------------------------------------------------------------',
        this.translateMessage( args, format ),
        '----------------------------------------------------------------------------------------------',
        this.i18n.devErrors.lines[1]
        ];
    alert( a.join( "\n" ) );
}

/*  Throws specific developer error
------------------------------------------- */
fValidate.prototype.paramError = function( param, elemName )
{
    elemName = this.setArg( elemName, this.elem.name );
    this.devError( [param, this.type, elemName], 'paramError' );
}
/* Non-fValidate methods *****************************************/

/*  For easy creation of DOM nodes
------------------------------------------- */
document.createHTMLElement = function( elemName, attribs )
{
    if ( typeof document.createElement == 'undefined' ) return;
    var elem = document.createElement( elemName );
    if ( typeof attribs != 'undefined' )
    {
        for ( var i in attribs )
        {
            switch ( true )
            {
                case ( i == 'text' )  : elem.appendChild( document.createTextNode( attribs[i] ) ); break;
                case ( i == 'class' ) : elem.className = attribs[i]; break;
                default : elem.setAttribute( i, '' ); elem[i] = attribs[i];
            }
        }
    }
    return elem;
}

/*  Trims b items from the beginning of the array, e items from the end
------------------------------------------- */
Array.prototype.reduce = function( b, e )
{
    var a = new Array();
    var count = 0;
    for ( var i = b; i < this.length - e; i++ )
    {
        a[count++] = this[i];
    }
    return a;
}

/*  Returns array as argument-compatible string
------------------------------------------- */
Array.prototype.toArgString = function()
{
    var a = new Array();
    for ( var i = 0; i < this.length; i++ )
    {
        a.push( "'" + this[i] + "'" );
    }
    return a.toString();
}

/*  Prototype push if missing
------------------------------------------- */
if ( typeof Array.push == 'undefined' )
Array.prototype.push = function()
{
    var arg, i = 0;
    while( arg = arguments[i++] )
    {
        this[this.length] = arg;
    }
    return this.length;
}

/*  Returns last item of the array
------------------------------------------- */
Array.prototype.last = function()
{
    return this[this.length-1];
}

/*  Removes the follow charaters _[] from an elements name for human-reading
------------------------------------------- */
String.prototype.format = function()
{
    return this.replace( /\_/g, " ").replace( /\[|\]/g, "" );
}

/*  Replaces newline characters with XHTML BR tags
------------------------------------------- */
String.prototype.toHTML = function()
{
    return this.replace( /\n/g, "<br />" ).replace( /\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;" );
}

/*  Trims leading and trailing whitespace from string
------------------------------------------- */
String.prototype.trim = function()
{
    return this.replace( /^\s+|\s+$/, "" );
}

/*  Escapes necessary charactes for string-generated regular expressions
------------------------------------------- */
String.prototype.toPattern = function()
{
    return this.replace( /([\.\*\+\{\}\(\)\<\>\^\$\\])/g, "\\$1" );
}
//  EOF

/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.controls.js

	Included Validators
	-------------------
	select
	selectm
	selecti
	checkbox
	radio
	file

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.select = function()
{
	if ( this.typeMismatch( 's1' ) ) return;
	if ( this.elem.selectedIndex == 0 )
	{
		this.throwError( [this.elem.fName] );
	}
}

fValidate.prototype.selectm = function( minS, maxS )
{
	if ( this.typeMismatch( 'sm' ) ) return;
	if ( typeof minS == 'undefined' )
	{
		this.paramError( 'minS' );
	}
	if ( maxS == 999 || maxS == '*' || typeof maxS == 'undefined' || maxS > this.elem.length ) maxS = this.elem.length;

	var count = 0;	
	for ( var opt, i = 0; ( opt = this.elem.options[i] ); i++ )
	{
		if ( opt.selected ) count++;
	}

	if ( count < minS || count > maxS )
	{
		this.throwError( [minS, maxS, this.elem.fName, count] );
	}
}

fValidate.prototype.selecti = function( indexes )
{
	
	if ( this.typeMismatch( 's1' ) ) return;
	if ( typeof indexes == 'undefined' )
	{
		this.paramError( 'indexes' );
		return;
	}
	indexes = indexes.split( "," );
	var selectOK = true;

	for ( var i = 0; i < indexes.length; i++ )
	{
		if ( this.elem.options[indexes[i]].selected )
		{
			selectOK = false;
			break;
		}
	}
	if ( !selectOK )
	{
		this.throwError( [this.elem.fName] );
	}
}

fValidate.prototype.checkbox = function( minC, maxC )
{
	if ( this.typeMismatch( 'cb' ) ) return;
	if ( typeof minC == 'undefined' )
	{
		this.paramError( 'minC' );
		return;
	}
	if ( this.elem == this.form.elements[this.elem.name] && !this.elem.checked )
	{
		this.throwError( [this.elem.fName] );
	}
	else
	{
		this.elem = this.form.elements[this.elem.name];
		var len   = this.elem.length;
		var count = 0;
		
		if ( maxC == 999 || maxC == '*' || typeof maxC == 'undefined' || maxC > this.elem.length )
		{
			maxC == len;
		}
		var i = len;
		while( i-- > 0 )
		{
			if ( this.elem[i].checked )
			{
				count++;
			}
		}
		if ( count < minC || count > maxC )
		{
			this.throwError( [minC, maxC, this.elem[0].fName, count] );
		}			
	}
}

fValidate.prototype.radio = function()
{
	if ( this.typeMismatch( 'rg' ) ) return;
	if ( this.elem == this.form.elements[this.elem.name] && !this.elem.checked )
	{
		this.throwError( [this.elem.fName] );
	}
	else
	{
		this.elem = this.form.elements[this.elem.name];
		
		for ( var i = 0; i < this.elem.length; i++ )
		{
			if ( this.elem.item( i ).checked )
			{
				return;
			}
		}
		this.throwError( [this.elem[0].fName] );
	}
}

fValidate.prototype.file = function( extensions, cSens )
{
	if ( this.typeMismatch( 'file' ) ) return;
	if ( typeof extensions == 'undefined' )
	{
		this.paramError( 'extensions' );
		return;
	}
	cSens = Boolean( cSens ) ? "" : "i";
	var regex = new RegExp( "^.+\\.(" + extensions.replace( /,/g, "|" ) + ")$", cSens );
	if ( ! regex.test( this.elem.value ) )
	{
		this.throwError( [extensions.replace( /,/g, "\n" )] );
	}
}
//	EOF

/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.datetime.js

	Included Validators
	-------------------
	date

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.date = function( formatStr, delim, code, specDate )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof formatStr == 'undefined' )
	{
		this.paramError( 'formatStr' );
		return;
	}

	delim = this.setArg( delim, "/" );

	var error	= [this.elem.fName, formatStr.replace( /\//g, delim )];
	var format  = formatStr.split( "/" );
	var compare = this.elem.value.split( delim );
	var order   = new Object();
	
	for ( var i = 0; i < format.length; i++ )
	{
		switch( format[i].charAt( 0 ).toLowerCase() )
		{
			case 'm' :
				order.months = i;
				break;
			case 'd' :
				order.days = i;
				break;
			case 'y' :
				order.years = i;
				break;
		}
	}
	var thisDate = new Date( compare[order.years], compare[order.months]-1, compare[order.days] );
	
	if ( isNaN( thisDate ) || thisDate.getDate() != compare[order.days] || thisDate.getMonth() != compare[order.months]-1 || thisDate.getFullYear().toString().length != formatStr.match( /y/g ).length )
	{
		this.throwError( error );
		return;
	}
	
	var compareElem = this.form.elements[specDate];
	if ( typeof compareElem != 'undefined' )
	{
		specDate = compareElem.validDate || compareElem.value;
	}
	var compareDate = ( specDate == 'today' )?
		new Date():
		new Date( specDate );
	compareDate.setHours(0);
	compareDate.setMinutes(0);
	compareDate.setSeconds(0);
	compareDate.setMilliseconds(0);
	
	var timeDiff = compareDate.getTime() - thisDate.getTime();
	var dateOk   = false;
	
	switch ( parseInt( code ) ) {
		case 1 :	// Before specDate
			dateOk	= Boolean( timeDiff > 0 );
			error	= 1;
			break;
		case 2 :	// Before or on specDate
			dateOk	= Boolean( ( timeDiff + 86400000 ) > 0 );
			error	= 2;
			break;
		case 3 :	// After specDate
			dateOk	= Boolean( timeDiff < 0 );
			error	= 3;
			break;
		case 4 :	// After or on specDate
			dateOk	= Boolean( ( timeDiff - 86400000 ) < 0 );
			error	= 4;
			break;
		default : dateOk = true;
		}
	if ( !dateOk )
	{
		this.throwError( [specDate], error );
	}
	this.elem.validDate = thisDate.toString();
}	
//	EOF
/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.controls.js

	Included Validators
	-------------------
	select
	selectm
	selecti
	checkbox
	radio
	file

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.select = function()
{
	if ( this.typeMismatch( 's1' ) ) return;
	if ( this.elem.selectedIndex == 0 )
	{
		this.throwError( [this.elem.fName] );
	}
}

fValidate.prototype.selectm = function( minS, maxS )
{
	if ( this.typeMismatch( 'sm' ) ) return;
	if ( typeof minS == 'undefined' )
	{
		this.paramError( 'minS' );
	}
	if ( maxS == 999 || maxS == '*' || typeof maxS == 'undefined' || maxS > this.elem.length ) maxS = this.elem.length;

	var count = 0;	
	for ( var opt, i = 0; ( opt = this.elem.options[i] ); i++ )
	{
		if ( opt.selected ) count++;
	}

	if ( count < minS || count > maxS )
	{
		this.throwError( [minS, maxS, this.elem.fName, count] );
	}
}

fValidate.prototype.selecti = function( indexes )
{
	
	if ( this.typeMismatch( 's1' ) ) return;
	if ( typeof indexes == 'undefined' )
	{
		this.paramError( 'indexes' );
		return;
	}
	indexes = indexes.split( "," );
	var selectOK = true;

	for ( var i = 0; i < indexes.length; i++ )
	{
		if ( this.elem.options[indexes[i]].selected )
		{
			selectOK = false;
			break;
		}
	}
	if ( !selectOK )
	{
		this.throwError( [this.elem.fName] );
	}
}

fValidate.prototype.checkbox = function( minC, maxC )
{
	if ( this.typeMismatch( 'cb' ) ) return;
	if ( typeof minC == 'undefined' )
	{
		this.paramError( 'minC' );
		return;
	}
	if ( this.elem == this.form.elements[this.elem.name] && !this.elem.checked )
	{
		this.throwError( [this.elem.fName] );
	}
	else
	{
		this.elem = this.form.elements[this.elem.name];
		var len   = this.elem.length;
		var count = 0;
		
		if ( maxC == 999 || maxC == '*' || typeof maxC == 'undefined' || maxC > this.elem.length )
		{
			maxC == len;
		}
		var i = len;
		while( i-- > 0 )
		{
			if ( this.elem[i].checked )
			{
				count++;
			}
		}
		if ( count < minC || count > maxC )
		{
			this.throwError( [minC, maxC, this.elem[0].fName, count] );
		}			
	}
}

fValidate.prototype.radio = function()
{
	if ( this.typeMismatch( 'rg' ) ) return;
	if ( this.elem == this.form.elements[this.elem.name] && !this.elem.checked )
	{
		this.throwError( [this.elem.fName] );
	}
	else
	{
		this.elem = this.form.elements[this.elem.name];
		
		for ( var i = 0; i < this.elem.length; i++ )
		{
			if ( this.elem.item( i ).checked )
			{
				return;
			}
		}
		this.throwError( [this.elem[0].fName] );
	}
}

fValidate.prototype.file = function( extensions, cSens )
{
	if ( this.typeMismatch( 'file' ) ) return;
	if ( typeof extensions == 'undefined' )
	{
		this.paramError( 'extensions' );
		return;
	}
	cSens = Boolean( cSens ) ? "" : "i";
	var regex = new RegExp( "^.+\\.(" + extensions.replace( /,/g, "|" ) + ")$", cSens );
	if ( ! regex.test( this.elem.value ) )
	{
		this.throwError( [extensions.replace( /,/g, "\n" )] );
	}
}
//	EOF
/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.datetime.js

	Included Validators
	-------------------
	date

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.date = function( formatStr, delim, code, specDate )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof formatStr == 'undefined' )
	{
		this.paramError( 'formatStr' );
		return;
	}

	delim = this.setArg( delim, "/" );

	var error	= [this.elem.fName, formatStr.replace( /\//g, delim )];
	var format  = formatStr.split( "/" );
	var compare = this.elem.value.split( delim );
	var order   = new Object();
	
	for ( var i = 0; i < format.length; i++ )
	{
		switch( format[i].charAt( 0 ).toLowerCase() )
		{
			case 'm' :
				order.months = i;
				break;
			case 'd' :
				order.days = i;
				break;
			case 'y' :
				order.years = i;
				break;
		}
	}
	var thisDate = new Date( compare[order.years], compare[order.months]-1, compare[order.days] );
	
	if ( isNaN( thisDate ) || thisDate.getDate() != compare[order.days] || thisDate.getMonth() != compare[order.months]-1 || thisDate.getFullYear().toString().length != formatStr.match( /y/g ).length )
	{
		this.throwError( error );
		return;
	}
	
	var compareElem = this.form.elements[specDate];
	if ( typeof compareElem != 'undefined' )
	{
		specDate = compareElem.validDate || compareElem.value;
	}
	var compareDate = ( specDate == 'today' )?
		new Date():
		new Date( specDate );
	compareDate.setHours(0);
	compareDate.setMinutes(0);
	compareDate.setSeconds(0);
	compareDate.setMilliseconds(0);
	
	var timeDiff = compareDate.getTime() - thisDate.getTime();
	var dateOk   = false;
	
	switch ( parseInt( code ) ) {
		case 1 :	// Before specDate
			dateOk	= Boolean( timeDiff > 0 );
			error	= 1;
			break;
		case 2 :	// Before or on specDate
			dateOk	= Boolean( ( timeDiff + 86400000 ) > 0 );
			error	= 2;
			break;
		case 3 :	// After specDate
			dateOk	= Boolean( timeDiff < 0 );
			error	= 3;
			break;
		case 4 :	// After or on specDate
			dateOk	= Boolean( ( timeDiff - 86400000 ) < 0 );
			error	= 4;
			break;
		default : dateOk = true;
		}
	if ( !dateOk )
	{
		this.throwError( [specDate], error );
	}
	this.elem.validDate = thisDate.toString();
}	
//	EOF


/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.ecommerce.js

	Included Validators
	-------------------
	money
	cc

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.money = function( ds, grp, dml )
{
	if ( this.typeMismatch( 'text' ) ) return;
	
	ds  = ( ds == ' ' )  ? false : ds.toPattern();
	grp = ( grp == ' ' ) ? false : grp.toPattern();
	dml = ( dml == ' ' ) ? false : dml.toPattern();
	
	var moneySyntax, pattern;
	
	switch( true )
	{
		case Boolean( ds && grp && dml ):		// Dollar sign, grouping, and decimal
			pattern		= "^" + ds + "(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})(" + dml + "[0-9]{2})$";
			moneySyntax = ds + "XX" + grp + "XXX" + dml + "XX";
			break;
		case Boolean( ds && grp && !dml ):		// Dollar sign and grouping
			pattern		= "^" + ds + "(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})$";
			moneySyntax = "" + ds + "XX" + grp + "XXX";
			break;
		case Boolean( ds && !grp && dml ):		// Dollar sign and decimal
			pattern		="^" + ds + "[0-9]*(\\.[0-9]{2})$";
			moneySyntax ="" + ds + "XXXXX" + dml + "XX";
			break;
		case Boolean( !ds && grp && dml ):		// Grouping and decimal
			pattern		="^(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})(" + dml + "[0-9]{2})?$";
			moneySyntax ="XX" + grp + "XXX" + dml + "XX";
			break;
		case Boolean( ds && !grp && !dml ):		// Dollar sign only
			pattern		="^" + ds + "[0-9]*$";
			moneySyntax ="" + ds + "XXXXX";
			break;
		case Boolean( !ds && grp && !dml ):		// Grouping only
			pattern		="^(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})$";
			moneySyntax ="XX" + grp + "XXX";
			break;
		case Boolean( !ds && !grp && dml ):		// Decimal only
			pattern		="^[0-9]*(" + dml + "[0-9]{2})$";
			moneySyntax ="XXXXX" + dml + "XX";
			break;
		case Boolean( !ds && !grp && !dml ):	// No params set, all special chars become optional
			pattern		="^.?(?:(?:[0-9]{1,3}.?)(?:[0-9]{3}.?)*[0-9]{3}|[0-9]{1,3})(.[0-9]{2})?$";
			moneySyntax ="[?]XX[?]XXX[?XX]";
	}
			
	var regex = new RegExp( pattern );
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName, moneySyntax.replace( /\\/g, '' )] );
	}
}

fValidate.prototype.cc = function()
{
	if ( this.typeMismatch( 'text' ) ) return;
	var typeElem = this.form.elements[this.config.ccType];
	if ( !typeElem )
	{
		this.devError( 'noCCType' )
		return;
	}
	var ccType   = typeElem.options[typeElem.selectedIndex].value.toUpperCase();
	var types    = {
		'VISA'    : /^4\d{12}(\d{3})?$/,
		'MC'      : /^5[1-5]\d{14}$/,
		'DISC'    : /^6011\d{12}$/,
		'AMEX'    : /^3[4|7]\d{13}$/,        
		'DINERS'  : /^3[0|6|8]\d{12}$/,
		'ENROUTE' : /^2[014|149]\d{11}$/,
		'JCB'     : /^3[088|096|112|158|337|528]\d{12}$/,
		'SWITCH'  : /^(49030[2-9]|49033[5-9]|49110[1-2]|4911(7[4-9]|8[1-2])|4936[0-9]{2}|564182|6333[0-4][0-9]|6759[0-9]{2})\d{10}(\d{2,3})?$/,
		'DELTA'   : /^4(1373[3-7]|462[0-9]{2}|5397[8|9]|54313|5443[2-5]|54742|567(2[5-9]|3[0-9]|4[0-5])|658[3-7][0-9]|659(0[1-9]|[1-4][0-9]|50)|844[09|10]|909[6-7][0-9]|9218[1|2]|98824)\d{10}$/,
		'SOLO'    : /^(6334[5-9][0-9]|6767[0-9]{2})\d{10}(\d{2,3})?$/
		};
	if ( typeElem.validated == false && this.groupError == true ) return;
	if ( typeof types[ccType] == 'undefined' && typeElem.validated == false && this.groupError == false )
	{
		this.devError( [ccType] );
		return;
	}
	this.elem.value = this.elem.value.replace( /[^\d]/g, "" );
	if ( !types[ccType].test( this.elem.value ) || !this.elem.value.luhn() )
	{
		this.throwError( [this.elem.fName] );
	}
}

String.prototype.luhn = function()
{
	var i = this.length;
	var checkSum = "", digit;
	while ( digit = this.charAt( --i ) )
	{
		checkSum += ( i % 2 == 0 ) ? digit * 2 : digit;
	}
	checkSum = eval( checkSum.split('').join('+') );
	return ( checkSum % 10 == 0 );
}
//	EOF

/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.extended.js

	Included Validators
	-------------------
	alnum
	ssn
	zip
	phone

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.alnum = function( minLen, tCase, numbers, spaces, puncs )
{
	if ( this.typeMismatch( 'text' ) ) return;

	tCase = this.setArg( tCase, "a" );
	
	//alert( [minLen,tCase,numbers,spaces,puncs] );

	numbers = ( numbers == "true" || numbers == "1" );
	spaces = ( spaces == "true" || spaces == "1" );

	//alert( [minLen,tCase,numbers,spaces,puncs] );
		
	var okChars = "",
		arrE	= ['None','Any','No','No','Any'];

	if ( minLen != '*' )
	{
		minLen =  parseInt( minLen, 10 );
		arrE[0] = minLen;
	} else {
		minLen = 0;
	}

	switch( tCase.toUpperCase() )
	{
		case 'U':
			okChars += 'A-Z';
			arrE[1] =  'UPPER';
			break;
		case 'L':
			okChars += 'a-z';
			arrE[1] =  'lower';
			break;
		case 'C':
			okChars += 'A-Z][a-z';
			arrE[1] =  'Intial capital';
			minLen--;
			break;
		default:
			okChars += 'a-zA-Z';
			break;		
	}

	if ( numbers == true )
	{
		okChars += '0-9';
		arrE[2] =  'Yes';
	}
	if ( spaces == true )
	{
		okChars += ' ';
		arrE[3] =  'Yes';
	}
	if ( puncs == "any" )
	{
		arrE[4]  = "Any";
	}
	else if ( puncs == "none" )
	{
		arrE[4] = "None";
	}
	else 
	{
		puncs = puncs.replace( /pipe/g, "|" );
		okChars += puncs;
		arrE[4] =  puncs; //.toPattern().replace( /\\/g, "" );
	}
	var length = ( minLen != "*" )?
		"{" + minLen + ",}":
		"+";
	var regex = ( puncs == "any" ) ?
		new RegExp( "^([" + okChars + "]|[^a-zA-Z0-9\\s])" + length + "$" ):
		new RegExp( "^[" + okChars + "]" + length + "$" );
	
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.value, this.elem.fName, arrE[0], arrE[1], arrE[2], arrE[3], arrE[4]] );
	}
}

fValidate.prototype.ssn = function()
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( !( /^\d{3}\-\d{2}\-\d{4}$/.test( this.elem.value ) ) )
		this.throwError();
}

fValidate.prototype.zip = function( sep )
{
	if ( this.typeMismatch( 'text' ) ) return;
	sep = this.setArg( sep, "- " );
	var regex = new RegExp( "^[0-9]{5}(|[" + sep.toPattern() + "][0-9]{4})?$" );
	if ( ! regex.test( this.elem.value ) )
	{
		this.throwError();
	}
}

fValidate.prototype.phone = function( format )
{
	if ( this.typeMismatch( 'text' ) ) return;
	format       = this.setArg( format, 0 );
	var patterns = [
		/^(\(?\d\d\d\)?)?[ -]?\d\d\d[ -]?\d\d\d\d$/,	//	loose
		/^(\(\d\d\d\) )?\d\d\d[ -]\d\d\d\d$/			//	strict
		];
	if ( !patterns[format].test( this.elem.value ) )
	{
		if ( format == 1 )
		{
			this.throwError();
		} else {
			this.throwError( [], 1 );
		}
	}
}
//	EOF

/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.international.js

	Included Validators
	-------------------
	cazip
	ukpost
	germanpost
	swisspost

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.cazip = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^[A-Z][0-9][A-Z] [0-9][A-Z][0-9]$/.test( elem.value ) ) )
	{
		this.throwError();
	}
}
fValidate.prototype.capost = fValidate.prototype.cazip;

fValidate.prototype.ukpost = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^[A-Z]{1,2}\d[\dA-Z] ?\d[A-Z]{2}$/.test( elem.value ) ) )
	{
		this.throwError();
	}
}

fValidate.prototype.germanpost = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^(?:CH\-)\d{4}$/.test( elem.value ) ) )
	{
		this.throwError();
	}
}

fValidate.prototype.swisspost = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^(?:D\-)\d{5}$/.test( this.elem.value ) ) )
	{
		this.throwError();
	}
}
//	EOF

/*********************************************************
*
*--	fValidate US-English language file.
*
*	Translation by: Peter Bailey
*	Email: me@peterbailey.net
*
*	Visit http://www.peterbailey.net/fValidate/api/i18n/
*	for additional translations and instructions on
*	making your own translation.
*
*	!!! WARNING !!! Changing anything but the literal 
*	strings will likely cause script failure!
*
*	Note: This document most easily read/edited with tab-
*	spacing set to 4
*
*********************************************************/

if ( typeof fvalidate == 'undefined' )
{
	var fvalidate = new Object();
}

fvalidate.i18n =
{
	//	Validation errors
	errors:
	{
		blank:		[
			["Please enter ", 0]
			],
		length:		[
			[0, " must be at least ", 1, " characters long"],
			[0, " must be no more than ", 1, " characters long.\nThe current text is ", 2, " characters long."]
			],
		equalto:	[
			[0, " must be equal to ", 1]
			],
		number:		[
			["The number you entered for ", 0, " is not valid"]
			],
		numeric:	[
			["Only numeric values are valid for the ", 0],
			["A minimum of ", 0, " numeric values are required for the ", 1]
			],
		alnum:		[
			["The data you entered, \"", 0, "\", does not match the requested format for ", 1,  
			"\nMinimum Length: ", 2,
			"\nCase: ", 3,
			"\nNumbers allowed: ", 4,
			"\nSpaces allowed: ", 5,
			"\nPunctuation characters allowed: ", 6, "\n"]
			],
		decimal:	[
			["The data you entered,", 0, " is not valid.  Please re-enter the ", 1]
			],
		decimalr:	[
			[0, " is not a valid. Please re-enter."]
			],
		ip:			[
			["Please enter a valid IP"],
			["The port number you specified, ", 0, ",  is out of range.\nIt must be between ", 1, " and ", 2]
			],
		ssn:		[
			["You need to enter a valid Social Security Number.\nYour SSN must be entered in 'XXX-XX-XXXX' format."]
			],
		money:		[
			[0, " does not match the required format of ", 1]
			],
		cc:			[
			["The ", 0, " you entered is not valid. Please check again and re-enter."]
			],
		ccDate:		[
			["You credit card has expired! Please use a different card."]
			],
		zip:		[
			["Please enter a valid 5 or 9 digit Zip code."]
			],
		phone:		[
			["Please enter a valid phone number plus Area Code."],
			["Please enter a valid phone number - seven or ten digits."]
			],
		email:		[
			["Please enter a valid email address"]
			],
		url:		[
			[0, " is not a valid domain"]
			],
		date:		[
			["The data entered for ", 0, " is not a valid date\nPlease enter a date using the following format: ", 1],
			["Date must be before ", 0],
			["Date must be on or before ", 0],
			["Date must be after ", 0],
			["Date must be on or after ", 0]
			],
		select:		[
			["Please select a valid option for ", 0]
			],
		selectm:	[
			["Please select between ", 0, " and ", 1, " options for ", 2, ".\nYou currently have ", 3, " selected"]
			],
		selecti:	[
			["Please select a valid option for ", 0]
			],
		checkbox:	[
			["Please check ", 0, " before continuing"],
			["Please select between ", 0, " and ", 1, " options for ", 2, ".\nYou currently have ", 3, " selected"]
			],
		radio:		[
			["Please check ", 0, " before continuing"],
			["Please select an option for ", 0 ]
			],
		comparison:	[
			[0, " must be ", 1, " ", 2]
			],
		eitheror:	[
			["One and only one of the following fields must be entered:\n\t-", 0, "\n"]
			],
		atleast:	[
			["At least ", 0, " of the following fields must be entered:\n\t-", 1, "\n\nYou have only ", 2, " filled in.\n"]
			],
		allornone:	[
			["All or none of the following fields must be entered and accurate:\n\t-", 0, "\nYou have only ", 1, " accurate field entered.\n"]
			],
		file:		[
			["The file must be one of the following types:\n", 0, "\nNote: File extension may be case-sensitive."]
			],
		custom:		[
			[0, " is invalid."]
			],
		cazip:		[
			["Please enter a valid postal code."]
			],
		ukpost:		[
			["Please enter a valid postcode."]
			],
		germanpost:	[
			["Please enter a valid postcode."]
			],
		swisspost:	[
			["Please enter a valid postcode."]
			]
	},

	comparison:
	{
		gt:		"greater than",
		lt:		"less than",
		gte:	"greater than or equal to",
		lte:	"less than or equal to",
		eq:		"equal to",
		neq:	"not equal to"
	},

	//	Developer assist errors
	devErrors:
	{
		number:		["The lower-bound (", 0, ") is greater than the upper-bound (", 1, ") on this element: ", 2],
		length:		["The minimum length (", 0, ") is greater than the maxiumum legnth (", 1, ") on this element: ", 2],
		cc:			["Credit Card type (", 0, ") not found."],

		lines:		["! WARNING ! -- fValidate developer-assist error\n", "\nIf you are not the developer, please contact the website administrator regarding this error."],
		paramError: ["You must include the '", 0, "' parameter for the '", 1, "' validator type on this field: ", 2],
		notFound:	["The validator '", 0, "' was not found.\nRequested by: ", 1],
		noLabel:	["No element found for label: ", 0],
		noBox:		["An element with the requested id '", 0, "' was not found for the 'boxError' config value."],
		missingName:["The hidden input calling the following logical validator must have a valid name\nattribute when used in conjunction with the 'box' error-type.\n\t", 0],
		mismatch:	["Validator/Element type mismatch.\n\nElement: ", 0, "\nElement type: ", 1, "\nType required by validator: ", 2],
		noCCType:	["You must include a SELECT item with Credit Card type choices!"]
	},

	//	Config values
	config :
	{
		confirmMsg :		"Your data is about to be sent.\nPlease click 'Ok' to proceed or 'Cancel' to abort.",
		confirmAbortMsg :	"Submission cancelled.  Data has not been sent."
	},

	//	Tooltip attached to Box-item errors
	boxToolTip:	"Click to target field",

	//	Message displayed at top of alert error in group mode
	groupAlert:	"The following errors occured:\n\n- ",

	//	Literal translation of the English 'or', include padding spaces.
	or:			" or "
}

/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.logical.js

	Included Validators
	-------------------
	equalto
	eitheror
	atleast
	allornone
	comparison

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.equalto = function( oName )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof oName == 'undefined' )
	{
		this.paramError( 'oName' );
	}
	var otherElem = this.form.elements[oName];
	if ( this.elem.value != otherElem.value )
	{
		this.throwError( [this.elem.fName,otherElem.fName] );			
	}
}

fValidate.prototype.eitheror = function()
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	if ( typeof arguments[0] == 'undefined' )
	{
		this.paramError( 'delim' );
		return;
	}
	if ( typeof arguments[1] == 'undefined' )
	{
		this.paramError( 'fields' );
		return;
	}
	var arg, i  = 0,
		fields  = new Array(),
		field,
		nbCount = 0,		
		args    = arguments[1].split( arguments[0] );		

	this.elem.fields = new Array();
	
	while ( arg = args[i++] )
	{
		field = this.form.elements[arg];
		fields.push( field.fName );
		this.elem.fields.push( field );

		if ( !this.isBlank( arg ) )
		{
			nbCount++;
		}
	}
	if ( nbCount != 1 )
	{
		this.throwError( [fields.join( "\n\t-" )] );
	}
}

fValidate.prototype.atleast = function()
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	if ( typeof arguments[0] == undefined )
	{
		this.paramError( 'qty' );
		return;
	}
	if ( typeof arguments[1] == undefined )
	{
		this.paramError( 'delim' );
		return;
	}
	if ( typeof arguments[2] == undefined )
	{
		this.paramError( 'fields' );
		return;
	}
	var arg, i  = 0,
		fields  = new Array(),
		field,
		nbCount = 0,
		args    = arguments[2].split( arguments[1] );

	this.elem.fields = new Array();
	
	while ( arg = args[i++] )
	{
		field = this.form.elements[arg];
		fields.push( field.fName );
		this.elem.fields.push( field );

		if ( !this.isBlank( arg ) )
		{
			nbCount++;
		}
	}
	if ( nbCount < arguments[0] )
	{
		this.throwError( [arguments[0], fields.join( "\n\t-" ), nbCount] );
	}
}

fValidate.prototype.allornone = function()
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	if ( typeof arguments[0] == 'undefined' )
	{
		this.paramError( 'delim' );
		return;
	}
	if ( typeof arguments[1] == 'undefined' )
	{
		this.paramError( 'fields' );
		return;
	}
	var arg, i  = 0,
		fields  = new Array(),
		field,
		nbCount = 0,
		args    = arguments[1].split( arguments[0] );
	
	this.elem.fields = new Array();

	while ( arg = args[i++] )
	{
		field = this.form.elements[arg];
		fields.push( field.fName );
		this.elem.fields.push( field );

		if ( !this.isBlank( arg ) )
		{
			nbCount++;
		}
	}
	if ( nbCount > 0 && nbCount < args.length )
	{
		this.throwError( [fields.join( "\n\t-" ), nbCount] );
	}
}

fValidate.prototype.comparison = function( field1, operator, field2 )
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	var elem1	= this.form.elements[field1],
		elem2	= this.form.elements[field2],
		value1	= this.getValue( elem1 ),
		value2	= this.getValue( elem2 );
		i18n	= this.i18n.comparison;
		i		= -1;
	
	var operators =
	[
		['>',	i18n.gt],
		['<',	i18n.lt],
		['>=',	i18n.gte],
		['<=',	i18n.lte],
		['==',	i18n.eq],
		['!=',	i18n.neq]
	];
	while( operators[++i][0] != operator ){ }
	this.elem.fields = [elem1, elem2];
	if ( ! eval( value1 + operator + value2 ) )
	{
		this.throwError( [elem1.fName, operators[i][1], elem2.fName] );
	}
}
//	EOF

/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.numbers.js

	Included Validators
	-------------------
	number
	numeric
	decimal
	decimalr

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.number = function( type, lb, ub )
{
	if ( this.typeMismatch( 'text' ) ) return;
	var num  = ( type == 0 ) ? parseInt( this.elem.value, 10 ) : parseFloat( this.elem.value );
	lb       = this.setArg( lb, 0 );
	ub       = this.setArg( ub, Number.infinity );
	if ( lb > ub )
	{
		this.devError( [lb, ub, this.elem.name] );
		return;
	}
	var fail = Boolean( isNaN( num ) || num != this.elem.value );
	if ( !fail )
	{
		switch( true )
		{
			case ( lb != false && ub != false ) : fail = !Boolean( lb <= num && num <= ub ); break;
			case ( lb != false ) : fail = Boolean( num < lb ); break;
			case ( ub != false ) : fail = Boolean( num > ub ); break;
		}
	}
	if ( fail )
	{
		this.throwError( [this.elem.fName] );
		return;
	}
	this.elemPass = true;
}

fValidate.prototype.numeric = function( len )
{
	if ( this.typeMismatch( 'text' ) ) return;
	len = this.setArg( len, '*' );
	var regex = new RegExp( ( len == '*' ) ? "^\\d+$" : "^\\d{" + parseInt( len, 10 ) + "}\\d*$" );
	if ( !regex.test( this.elem.value ) )
	{
		if ( len == "*" )
		{
			this.throwError( [this.elem.fName] );
		} else {
			this.throwError( [len, this.elem.fName], 1 );
		}
	}
}

fValidate.prototype.decimal = function( lval, rval )
{
	if ( this.typeMismatch( 'text' ) ) return;
	var regex = '', elem = this.elem;
	if ( lval != '*' ) lval = parseInt( lval, 10 );
	if ( rval != '*' ) rval = parseInt( rval, 10 );
	
	if ( lval == 0 )
		regex = "^\\.[0-9]{" + rval + "}$";	
	else if ( lval == '*' )
		regex = "^[0-9]*\\.[0-9]{" + rval + "}$";
	else if ( rval == '*' )
		regex = "^[0-9]{" + lval + "}\\.[0-9]+$";
	else
		regex = "^[0-9]{" + lval + "}\\.[0-9]{" + rval + "}$";
		
	regex = new RegExp( regex );

	if ( !regex.test( elem.value ) )
	{
		this.throwError( [elem.value,elem.fName] );
	}	
}

fValidate.prototype.decimalr = function( lmin, lmax, rmin, rmax )
{
	if ( this.typeMismatch( 'text' ) ) return;
	lmin = ( lmin == '*' )? 0 : parseInt( lmin, 10 );
	lmax = ( lmax == '*' )? '': parseInt( lmax, 10 );
	rmin = ( rmin == '*' )? 0 : parseInt( rmin, 10 );
	rmax = ( rmax == '*' )? '': parseInt( rmax, 10 );
	var	decReg = "^[0-9]{"+lmin+","+lmax+"}\\.[0-9]{"+rmin+","+rmax+"}$"
	var regex = new RegExp(decReg);
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName] );
	}
	return true;
}
//	EOF

/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.special.js

	Included Validators
	-------------------
	custom

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.custom = function( flags, reverseTest )
{
	if ( this.typeMismatch( 'text' ) ) return;
	flags     = ( flags ) ? flags.replace( /[^gim]/ig ) : "";
	var regex = new RegExp( this.elem.getAttribute( this.config.pattern ), flags );
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName] );
	}	
}
//	EOF

/***************************************************	

	fValidate
	Copyright (c) 2000-2003
	by Peter Bailey
	www.peterbailey.net/fValidate/

	fValidate.web.js

	Included Validators
	-------------------
	email
	url
	ip

	This file is only part of a larger validation
	library	and will not function autonomously.

	Created at a tab-spacing of four (4)

****************************************************/

fValidate.prototype.email = function( level )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof level == 'undefined' ) level = 0;
	var emailPatterns = [
		/.+@.+\..+$/i,
		/^\w.+@\w.+\.[a-z]+$/i,
		/^\w[-_a-z~.]+@\w[-_a-z~.]+\.[a-z]{2}[a-z]*$/i,
		/^\w[\w\d]+(\.[\w\d]+)*@\w[\w\d]+(\.[\w\d]+)*\.[a-z]{2,7}$/i
		];
	if ( ! emailPatterns[level].test( this.elem.value ) )
	{
		this.throwError();
	}	
}	

fValidate.prototype.url = function( hosts, hostOptional, allowQS )
{
	if ( this.typeMismatch( 'text' ) ) return;

	this.setArg( hosts, "http" );
	
	var front = "^(?:(" + hosts.replace( /\,/g, "|" ) + ")\\:\\/\\/)";
	var end   = ( Boolean( allowQS ) == true ) ? "(\\?.*)?$" : "$";

	if ( Boolean( hostOptional ) == true ) front += "?";
	var regex = new RegExp( front + "([\\w\\d-]+\\.?)+" + end );
	
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName] );
	}
}	

fValidate.prototype.ip = function( portMin, portMax )
{
	if ( this.typeMismatch( 'text' ) ) return;
	portMin = this.setArg( portMin, 0 );
	portMax = this.setArg( portMax, 99999 );
	if ( !( /^\d{1,3}(\.\d{1,3}){3}(:\d+)?$/.test( this.elem.value ) ) )
	{
		this.throwError();
	}
	else
	{
		var part, i = 0, parts = this.elem.value.split( /[.:]/ );
		while ( part = parts[i++] )
		{
			if ( i == 5 ) // Check port
			{
				if ( part < portMin || part > portMax )
				{
					this.throwError( [part, portMin, portMax], 1 );
				}
			}
			else if ( part < 0 || part > 255 )
			{
				this.throwError();
			}
		}
	}
}
//	EOF

/*< blank basic *******************************************************************/
fValidate.prototype.blank = function()
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( this.isBlank() )
	{
		this.throwError( [this.elem.fName] );
	}
}
/*/>*/
/*< number numbers *******************************************************************/
fValidate.prototype.number = function( type, lb, ub )
{
	if ( this.typeMismatch( 'text' ) ) return;
	var num  = ( type == 0 ) ? parseInt( this.elem.value, 10 ) : parseFloat( this.elem.value );
	lb       = this.setArg( lb, 0 );
	ub       = this.setArg( ub, Number.infinity );
	if ( lb > ub )
	{
		this.devError( [lb, ub, this.elem.name] );
		return;
	}
	var fail = Boolean( isNaN( num ) || num != this.elem.value );
	if ( !fail )
	{
		switch( true )
		{
			case ( lb != false && ub != false ) : fail = !Boolean( lb <= num && num <= ub ); break;
			case ( lb != false ) : fail = Boolean( num < lb ); break;
			case ( ub != false ) : fail = Boolean( num > ub ); break;
		}
	}
	if ( fail )
	{
		this.throwError( [this.elem.fName] );
		return;
	}
	this.elemPass = true;
}
/*/>*/
/*< numeric numbers *******************************************************************/
fValidate.prototype.numeric = function( len )
{
	if ( this.typeMismatch( 'text' ) ) return;
	len = this.setArg( len, '*' );
	var regex = new RegExp( ( len == '*' ) ? "^\\d+$" : "^\\d{" + parseInt( len, 10 ) + "}\\d*$" );
	if ( !regex.test( this.elem.value ) )
	{
		if ( len == "*" )
		{
			this.throwError( [this.elem.fName] );
		} else {
			this.throwError( [len, this.elem.fName], 1 );
		}
	}
}
/*/>*/
/*< length basic *******************************************************************/
fValidate.prototype.length = function( len, maxLen )
{
	if ( this.typeMismatch( 'text' ) ) return;
	var vlen = this.elem.value.length;
	len		= Math.abs( len );
	maxLen	= Math.abs( this.setArg( maxLen, Number.infinity ) );
	if ( len > maxLen )
	{
		this.devError( [len, maxLen, this.elem.name] );
		return;
	}
	if ( len > parseInt( vlen, 10 ) )
	{
		this.throwError( [this.elem.fName, len] );
	}	
	if ( vlen > maxLen )
	{
		this.throwError( [this.elem.fName, maxLen, vlen], 1 );
	}
}
/*/>*/
/*< alnum extended *******************************************************************/
fValidate.prototype.alnum = function( minLen, tCase, numbers, spaces, puncs )
{
	if ( this.typeMismatch( 'text' ) ) return;

	tCase = this.setArg( tCase, "a" );
	
	//alert( [minLen,tCase,numbers,spaces,puncs] );

	numbers = ( numbers == "true" || numbers == "1" );
	spaces = ( spaces == "true" || spaces == "1" );

	//alert( [minLen,tCase,numbers,spaces,puncs] );
		
	var okChars = "",
		arrE	= ['None','Any','No','No','Any'];

	if ( minLen != '*' )
	{
		minLen =  parseInt( minLen, 10 );
		arrE[0] = minLen;
	} else {
		minLen = 0;
	}

	switch( tCase.toUpperCase() )
	{
		case 'U':
			okChars += 'A-Z';
			arrE[1] =  'UPPER';
			break;
		case 'L':
			okChars += 'a-z';
			arrE[1] =  'lower';
			break;
		case 'C':
			okChars += 'A-Z][a-z';
			arrE[1] =  'Intial capital';
			minLen--;
			break;
		default:
			okChars += 'a-zA-Z';
			break;		
	}

	if ( numbers == true )
	{
		okChars += '0-9';
		arrE[2] =  'Yes';
	}
	if ( spaces == true )
	{
		okChars += ' ';
		arrE[3] =  'Yes';
	}
	if ( puncs == "any" )
	{
		arrE[4]  = "Any";
	}
	else if ( puncs == "none" )
	{
		arrE[4] = "None";
	}
	else 
	{
		puncs = puncs.replace( /pipe/g, "|" );
		okChars += puncs;
		arrE[4] =  puncs; //.toPattern().replace( /\\/g, "" );
	}
	var length = ( minLen != "*" )?
		"{" + minLen + ",}":
		"+";
	var regex = ( puncs == "any" ) ?
		new RegExp( "^([" + okChars + "]|[^a-zA-Z0-9\\s])" + length + "$" ):
		new RegExp( "^[" + okChars + "]" + length + "$" );
	
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.value, this.elem.fName, arrE[0], arrE[1], arrE[2], arrE[3], arrE[4]] );
	}
}
/*/>*/
/*< equalto logical *******************************************************************/
fValidate.prototype.equalto = function( oName )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof oName == 'undefined' )
	{
		this.paramError( 'oName' );
	}
	var otherElem = this.form.elements[oName];
	if ( this.elem.value != otherElem.value )
	{
		this.throwError( [this.elem.fName,otherElem.fName] );			
	}
}
/*/>*/
/*< ssn extended *******************************************************************/
fValidate.prototype.ssn = function()
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( !( /^\d{3}\-\d{2}\-\d{4}$/.test( this.elem.value ) ) )
		this.throwError();
}
/*/>*/
/*< select controls *******************************************************************/
fValidate.prototype.select = function()
{
	if ( this.typeMismatch( 's1' ) ) return;
	if ( this.elem.selectedIndex == 0 )
	{
		this.throwError( [this.elem.fName] );
	}
}
/*/>*/
/*< selectm controls *******************************************************************/
fValidate.prototype.selectm = function( minS, maxS )
{
	if ( this.typeMismatch( 'sm' ) ) return;
	if ( typeof minS == 'undefined' )
	{
		this.paramError( 'minS' );
	}
	if ( maxS == 999 || maxS == '*' || typeof maxS == 'undefined' || maxS > this.elem.length ) maxS = this.elem.length;

	var count = 0;	
	for ( var opt, i = 0; ( opt = this.elem.options[i] ); i++ )
	{
		if ( opt.selected ) count++;
	}

	if ( count < minS || count > maxS )
	{
		this.throwError( [minS, maxS, this.elem.fName, count] );
	}
}
/*/>*/
/*< selecti controls *******************************************************************/
fValidate.prototype.selecti = function( indexes )
{

	if ( this.typeMismatch( 's1' ) ) return;
	if ( typeof indexes == 'undefined' )
	{
		this.paramError( 'indexes' );
		return;
	}
	indexes = indexes.split( "," );
	var selectOK = true;

	for ( var i = 0; i < indexes.length; i++ )
	{
		if ( this.elem.options[indexes[i]].selected )
		{
			selectOK = false;
			break;
		}
	}
	if ( !selectOK )
	{
		this.throwError( [this.elem.fName] );
	}
}
/*/>*/
/*< cazip international *******************************************************************/
fValidate.prototype.cazip = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^[A-Z][0-9][A-Z] [0-9][A-Z][0-9]$/.test( elem.value ) ) )
	{
		this.throwError();
	}
}
fValidate.prototype.capost = fValidate.prototype.cazip;
/*/>*/
/*< ukpost international *******************************************************************/
fValidate.prototype.ukpost = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^[A-Z]{1,2}\d[\dA-Z] ?\d[A-Z]{2}$/.test( elem.value ) ) )
	{
		this.throwError();
	}
}
/*/>*/
/*< germanpost international *******************************************************************/
fValidate.prototype.germanpost = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^(?:CH\-)\d{4}$/.test( elem.value ) ) )
	{
		this.throwError();
	}
}
/*/>*/
/*< swisspost international *******************************************************************/
fValidate.prototype.swisspost = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^(?:D\-)\d{5}$/.test( this.elem.value ) ) )
	{
		this.throwError();
	}
}
/*/>*/
/*< email web *******************************************************************/
fValidate.prototype.email = function( level )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof level == 'undefined' ) level = 0;
	var emailPatterns = [
		/.+@.+\..+$/i,
		/^\w.+@\w.+\.[a-z]+$/i,
		/^\w[-_a-z~.]+@\w[-_a-z~.]+\.[a-z]{2}[a-z]*$/i,
		/^\w[\w\d]+(\.[\w\d]+)*@\w[\w\d]+(\.[\w\d]+)*\.[a-z]{2,7}$/i
		];
	if ( ! emailPatterns[level].test( this.elem.value ) )
	{
		this.throwError();
	}	
}	
/*/>*/
/*< url web *******************************************************************/
fValidate.prototype.url = function( hosts, hostOptional, allowQS )
{
	if ( this.typeMismatch( 'text' ) ) return;

	this.setArg( hosts, "http" );
	
	var front = "^(?:(" + hosts.replace( /\,/g, "|" ) + ")\\:\\/\\/)";
	var end   = ( Boolean( allowQS ) == true ) ? "(\\?.*)?$" : "$";

	if ( Boolean( hostOptional ) == true ) front += "?";
	var regex = new RegExp( front + "([\\w\\d-]+\\.?)+" + end );
	
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName] );
	}
}	
/*/>*/
/*< ip web *******************************************************************/
fValidate.prototype.ip = function( portMin, portMax )
{
	if ( this.typeMismatch( 'text' ) ) return;
	portMin = this.setArg( portMin, 0 );
	portMax = this.setArg( portMax, 99999 );
	if ( !( /^\d{1,3}(\.\d{1,3}){3}(:\d+)?$/.test( this.elem.value ) ) )
	{
		this.throwError();
	}
	else
	{
		var part, i = 0, parts = this.elem.value.split( /[.:]/ );
		while ( part = parts[i++] )
		{
			if ( i == 5 ) // Check port
			{
				if ( part < portMin || part > portMax )
				{
					this.throwError( [part, portMin, portMax], 1 );
				}
			}
			else if ( part < 0 || part > 255 )
			{
				this.throwError();
			}
		}
	}
}
/*/>*/
/*< decimal numbers *******************************************************************/
fValidate.prototype.decimal = function( lval, rval )
{
	if ( this.typeMismatch( 'text' ) ) return;
	var regex = '', elem = this.elem;
	if ( lval != '*' ) lval = parseInt( lval, 10 );
	if ( rval != '*' ) rval = parseInt( rval, 10 );
	
	if ( lval == 0 )
		regex = "^\\.[0-9]{" + rval + "}$";	
	else if ( lval == '*' )
		regex = "^[0-9]*\\.[0-9]{" + rval + "}$";
	else if ( rval == '*' )
		regex = "^[0-9]{" + lval + "}\\.[0-9]+$";
	else
		regex = "^[0-9]{" + lval + "}\\.[0-9]{" + rval + "}$";
		
	regex = new RegExp( regex );

	if ( !regex.test( elem.value ) )
	{
		this.throwError( [elem.value,elem.fName] );
	}	
}
/*/>*/
/*< decimalr numbers *******************************************************************/
fValidate.prototype.decimalr = function( lmin, lmax, rmin, rmax )
{
	if ( this.typeMismatch( 'text' ) ) return;
	lmin = ( lmin == '*' )? 0 : parseInt( lmin, 10 );
	lmax = ( lmax == '*' )? '': parseInt( lmax, 10 );
	rmin = ( rmin == '*' )? 0 : parseInt( rmin, 10 );
	rmax = ( rmax == '*' )? '': parseInt( rmax, 10 );
	var	decReg = "^[0-9]{"+lmin+","+lmax+"}\\.[0-9]{"+rmin+","+rmax+"}$"
	var regex = new RegExp(decReg);
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName] );
	}
	return true;
}
/*/>*/
/*< zip extended *******************************************************************/
fValidate.prototype.zip = function( sep )
{
	if ( this.typeMismatch( 'text' ) ) return;
	sep = this.setArg( sep, "- " );
	var regex = new RegExp( "^[0-9]{5}(|[" + sep.toPattern() + "][0-9]{4})?$" );
	if ( ! regex.test( this.elem.value ) )
	{
		this.throwError();
	}
}
/*/>*/
/*< phone extended *******************************************************************/
fValidate.prototype.phone = function( format )
{
	if ( this.typeMismatch( 'text' ) ) return;
	format       = this.setArg( format, 0 );
	var patterns = [
		/^(\(?\d\d\d\)?)?[ -]?\d\d\d[ -]?\d\d\d\d$/,	//	loose
		/^(\(\d\d\d\) )?\d\d\d[ -]\d\d\d\d$/			//	strict
		];
	if ( !patterns[format].test( this.elem.value ) )
	{
		if ( format == 1 )
		{
			this.throwError();
		} else {
			this.throwError( [], 1 );
		}
	}
}
/*/>*/
/*< date datetime *******************************************************************/
fValidate.prototype.date = function( formatStr, delim, code, specDate )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof formatStr == 'undefined' )
	{
		this.paramError( 'formatStr' );
		return;
	}

	delim = this.setArg( delim, "/" );

	var error	= [this.elem.fName, formatStr.replace( /\//g, delim )];
	var format  = formatStr.split( "/" );
	var compare = this.elem.value.split( delim );
	var order   = new Object();
	
	for ( var i = 0; i < format.length; i++ )
	{
		switch( format[i].charAt( 0 ).toLowerCase() )
		{
			case 'm' :
				order.months = i;
				break;
			case 'd' :
				order.days = i;
				break;
			case 'y' :
				order.years = i;
				break;
		}
	}
	var thisDate = new Date( compare[order.years], compare[order.months]-1, compare[order.days] );
	
	if ( isNaN( thisDate ) || thisDate.getDate() != compare[order.days] || thisDate.getMonth() != compare[order.months]-1 || thisDate.getFullYear().toString().length != formatStr.match( /y/g ).length )
	{
		this.throwError( error );
		return;
	}
	
	var compareElem = this.form.elements[specDate];
	if ( typeof compareElem != 'undefined' )
	{
		specDate = compareElem.validDate || compareElem.value;
	}
	var compareDate = ( specDate == 'today' )?
		new Date():
		new Date( specDate );
	compareDate.setHours(0);
	compareDate.setMinutes(0);
	compareDate.setSeconds(0);
	compareDate.setMilliseconds(0);
	
	var timeDiff = compareDate.getTime() - thisDate.getTime();
	var dateOk   = false;
	
	switch ( parseInt( code ) ) {
		case 1 :	// Before specDate
			dateOk	= Boolean( timeDiff > 0 );
			error	= 1;
			break;
		case 2 :	// Before or on specDate
			dateOk	= Boolean( ( timeDiff + 86400000 ) > 0 );
			error	= 2;
			break;
		case 3 :	// After specDate
			dateOk	= Boolean( timeDiff < 0 );
			error	= 3;
			break;
		case 4 :	// After or on specDate
			dateOk	= Boolean( ( timeDiff - 86400000 ) < 0 );
			error	= 4;
			break;
		default : dateOk = true;
		}
	if ( !dateOk )
	{
		this.throwError( [specDate], error );
	}
	this.elem.validDate = thisDate.toString();
}	
/*/>*/
/*< money ecommerce *******************************************************************/
fValidate.prototype.money = function( ds, grp, dml )
{
	if ( this.typeMismatch( 'text' ) ) return;
	
	ds  = ( ds == ' ' )  ? false : ds.toPattern();
	grp = ( grp == ' ' ) ? false : grp.toPattern();
	dml = ( dml == ' ' ) ? false : dml.toPattern();
	
	var moneySyntax, pattern;
	
	switch( true )
	{
		case Boolean( ds && grp && dml ):		// Dollar sign, grouping, and decimal
			pattern		= "^" + ds + "(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})(" + dml + "[0-9]{2})$";
			moneySyntax = ds + "XX" + grp + "XXX" + dml + "XX";
			break;
		case Boolean( ds && grp && !dml ):		// Dollar sign and grouping
			pattern		= "^" + ds + "(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})$";
			moneySyntax = "" + ds + "XX" + grp + "XXX";
			break;
		case Boolean( ds && !grp && dml ):		// Dollar sign and decimal
			pattern		="^" + ds + "[0-9]*(\\.[0-9]{2})$";
			moneySyntax ="" + ds + "XXXXX" + dml + "XX";
			break;
		case Boolean( !ds && grp && dml ):		// Grouping and decimal
			pattern		="^(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})(" + dml + "[0-9]{2})?$";
			moneySyntax ="XX" + grp + "XXX" + dml + "XX";
			break;
		case Boolean( ds && !grp && !dml ):		// Dollar sign only
			pattern		="^" + ds + "[0-9]*$";
			moneySyntax ="" + ds + "XXXXX";
			break;
		case Boolean( !ds && grp && !dml ):		// Grouping only
			pattern		="^(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})$";
			moneySyntax ="XX" + grp + "XXX";
			break;
		case Boolean( !ds && !grp && dml ):		// Decimal only
			pattern		="^[0-9]*(" + dml + "[0-9]{2})$";
			moneySyntax ="XXXXX" + dml + "XX";
			break;
		case Boolean( !ds && !grp && !dml ):	// No params set, all special chars become optional
			pattern		="^.?(?:(?:[0-9]{1,3}.?)(?:[0-9]{3}.?)*[0-9]{3}|[0-9]{1,3})(.[0-9]{2})?$";
			moneySyntax ="[?]XX[?]XXX[?XX]";
	}
			
	var regex = new RegExp( pattern );
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName, moneySyntax.replace( /\\/g, '' )] );
	}
}
/*/>*/
/*< checkbox controls *******************************************************************/
fValidate.prototype.checkbox = function( minC, maxC )
{
	if ( this.typeMismatch( 'cb' ) ) return;
	if ( typeof minC == 'undefined' )
	{
		this.paramError( 'minC' );
		return;
	}
	if ( this.elem == this.form.elements[this.elem.name] && !this.elem.checked )
	{
		this.throwError( [this.elem.fName] );
	}
	else
	{
		this.elem = this.form.elements[this.elem.name];
		var len   = this.elem.length;
		var count = 0;
		
		if ( maxC == 999 || maxC == '*' || typeof maxC == 'undefined' || maxC > this.elem.length )
		{
			maxC == len;
		}
		var i = len;
		while( i-- > 0 )
		{
			if ( this.elem[i].checked )
			{
				count++;
			}
		}
		if ( count < minC || count > maxC )
		{
			this.throwError( [minC, maxC, this.elem[0].fName, count] );
		}			
	}
}
/*/>*/
/*< radio controls *******************************************************************/
fValidate.prototype.radio = function()
{
	if ( this.typeMismatch( 'rg' ) ) return;
	if ( this.elem == this.form.elements[this.elem.name] && !this.elem.checked )
	{
		this.throwError( [this.elem.fName] );
	}
	else
	{
		this.elem = this.form.elements[this.elem.name];
		
		for ( var i = 0; i < this.elem.length; i++ )
		{
			if ( this.elem.item( i ).checked )
			{
				return;
			}
		}
		this.throwError( [this.elem[0].fName] );
	}
}
/*/>*/
/*< eitheror logical *******************************************************************/
fValidate.prototype.eitheror = function()
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	if ( typeof arguments[0] == 'undefined' )
	{
		this.paramError( 'delim' );
		return;
	}
	if ( typeof arguments[1] == 'undefined' )
	{
		this.paramError( 'fields' );
		return;
	}
	var arg, i  = 0,
		fields  = new Array(),
		field,
		nbCount = 0,		
		args    = arguments[1].split( arguments[0] );		

	this.elem.fields = new Array();
	
	while ( arg = args[i++] )
	{
		field = this.form.elements[arg];
		fields.push( field.fName );
		this.elem.fields.push( field );

		if ( !this.isBlank( arg ) )
		{
			nbCount++;
		}
	}
	if ( nbCount != 1 )
	{
		this.throwError( [fields.join( "\n\t-" )] );
	}
}
/*/>*/
/*< atleast logical *******************************************************************/
fValidate.prototype.atleast = function()
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	if ( typeof arguments[0] == undefined )
	{
		this.paramError( 'qty' );
		return;
	}
	if ( typeof arguments[1] == undefined )
	{
		this.paramError( 'delim' );
		return;
	}
	if ( typeof arguments[2] == undefined )
	{
		this.paramError( 'fields' );
		return;
	}
	var arg, i  = 0,
		fields  = new Array(),
		field,
		nbCount = 0,
		args    = arguments[2].split( arguments[1] );

	this.elem.fields = new Array();
	
	while ( arg = args[i++] )
	{
		field = this.form.elements[arg];
		fields.push( field.fName );
		this.elem.fields.push( field );

		if ( !this.isBlank( arg ) )
		{
			nbCount++;
		}
	}
	if ( nbCount < arguments[0] )
	{
		this.throwError( [arguments[0], fields.join( "\n\t-" ), nbCount] );
	}
}
/*/>*/
/*< allornone logical *******************************************************************/
fValidate.prototype.allornone = function()
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	if ( typeof arguments[0] == 'undefined' )
	{
		this.paramError( 'delim' );
		return;
	}
	if ( typeof arguments[1] == 'undefined' )
	{
		this.paramError( 'fields' );
		return;
	}
	var arg, i  = 0,
		fields  = new Array(),
		field,
		nbCount = 0,
		args    = arguments[1].split( arguments[0] );
	
	this.elem.fields = new Array();

	while ( arg = args[i++] )
	{
		field = this.form.elements[arg];
		fields.push( field.fName );
		this.elem.fields.push( field );

		if ( !this.isBlank( arg ) )
		{
			nbCount++;
		}
	}
	if ( nbCount > 0 && nbCount < args.length )
	{
		this.throwError( [fields.join( "\n\t-" ), nbCount] );
	}
}
/*/>*/
/*< comparison logical *******************************************************************/
fValidate.prototype.comparison = function( field1, operator, field2 )
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	var elem1	= this.form.elements[field1],
		elem2	= this.form.elements[field2],
		value1	= this.getValue( elem1 ),
		value2	= this.getValue( elem2 );
		i18n	= this.i18n.comparison;
		i		= -1;
	
	var operators =
	[
		['>',	i18n.gt],
		['<',	i18n.lt],
		['>=',	i18n.gte],
		['<=',	i18n.lte],
		['==',	i18n.eq],
		['!=',	i18n.neq]
	];
	while( operators[++i][0] != operator ){ }
	this.elem.fields = [elem1, elem2];
	if ( ! eval( value1 + operator + value2 ) )
	{
		this.throwError( [elem1.fName, operators[i][1], elem2.fName] );
	}
}
/*/>*/
/*< file controls *******************************************************************/
fValidate.prototype.file = function( extensions, cSens )
{
	if ( this.typeMismatch( 'file' ) ) return;
	if ( typeof extensions == 'undefined' )
	{
		this.paramError( 'extensions' );
		return;
	}
	cSens = Boolean( cSens ) ? "" : "i";
	var regex = new RegExp( "^.+\\.(" + extensions.replace( /,/g, "|" ) + ")$", cSens );
	if ( ! regex.test( this.elem.value ) )
	{
		this.throwError( [extensions.replace( /,/g, "\n" )] );
	}
}
/*/>*/
/*< custom special *******************************************************************/
fValidate.prototype.custom = function( flags, reverseTest )
{
	if ( this.typeMismatch( 'text' ) ) return;
	flags     = ( flags ) ? flags.replace( /[^gim]/ig ) : "";
	var regex = new RegExp( this.elem.getAttribute( this.config.pattern ), flags );
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName] );
	}	
}
/*/>*/
/*< cc ecommerce *******************************************************************/
fValidate.prototype.cc = function()
{
	if ( this.typeMismatch( 'text' ) ) return;
	var typeElem = this.form.elements[this.config.ccType];

	if ( !typeElem )
	{
		this.devError( 'noCCType' )
		return;
	}
	var ccType   = typeElem.options[typeElem.selectedIndex].value.toUpperCase();

	var types    = {
		'VISA'    : /^4\d{12}(\d{3})?$/,
		'MC'      : /^5[1-5]\d{14}$/,
		'DISC'    : /^6011\d{12}$/,
		'AMEX'    : /^3[4|7]\d{13}$/,        
		'DINERS'  : /^3[0|6|8]\d{12}$/,
		'ENROUTE' : /^2[014|149]\d{11}$/,
		'JCB'     : /^3[088|096|112|158|337|528]\d{12}$/,
		'SWITCH'  : /^(49030[2-9]|49033[5-9]|49110[1-2]|4911(7[4-9]|8[1-2])|4936[0-9]{2}|564182|6333[0-4][0-9]|6759[0-9]{2})\d{10}(\d{2,3})?$/,
		'DELTA'   : /^4(1373[3-7]|462[0-9]{2}|5397[8|9]|54313|5443[2-5]|54742|567(2[5-9]|3[0-9]|4[0-5])|658[3-7][0-9]|659(0[1-9]|[1-4][0-9]|50)|844[09|10]|909[6-7][0-9]|9218[1|2]|98824)\d{10}$/,
		'SOLO'    : /^(6334[5-9][0-9]|6767[0-9]{2})\d{10}(\d{2,3})?$/
		};
	if ( typeElem.validated == false && this.groupError == true ) return;
	if ( typeof types[ccType] == 'undefined' && typeElem.validated == false && this.groupError == false )
	{
		this.devError( [ccType] );
		return;
	}
	this.elem.value = this.elem.value.replace( /[^\d]/g, "" );
	if ( !types[ccType].test( this.elem.value ) || !this.elem.value.luhn() )
	{
		this.throwError( [this.elem.fName] );
	}
}

String.prototype.luhn = function()
{
	var i = this.length;
	var checkSum = "", digit;
	while ( digit = this.charAt( --i ) )
	{
		checkSum += ( i % 2 == 0 ) ? digit * 2 : digit;
	}
	checkSum = eval( checkSum.split('').join('+') );
	return ( checkSum % 10 == 0 );
}
/*/>*/
/*< ccDate ecommerce *******************************************************************/
fValidate.prototype.ccDate = function( month, year )
{
	if ( this.typeMismatch( 's1' ) ) return;
	year	= parseInt( this.getValue( this.form.elements[year] ), 10 ) + 2000;
	month	= parseInt( this.getValue( this.form.elements[month] ), 10 );

	var today	= new Date();
	var expDate = new Date( year, month )

	if ( expDate < today )
	{
		alert( ["Card Expired",today,expDate].join( "\n" ) );
	}
}
/*/>*/
/*	EOF */


