 
			/*< 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" ) );
				}
			}
			/*/>*/
			
