//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package mx.validators { import mx.resources.IResourceManager; import mx.resources.ResourceManager; [ResourceBundle("validators")] /** * The ZipCodeValidator class validates that a String * has the correct length and format for a five-digit ZIP code, * a five-digit+four-digit United States ZIP code, or Canadian postal code. * * @mxml * *

The <mx:ZipCodeValidator> tag * inherits all of the tag attributes of its superclass, * and adds the following tag attributes:

* *
 *  <mx:ZipCodeValidator
 *    allowedFormatChars=" -" 
 *    domain="US Only | US or Canada | Canada Only"
 *    invalidCharError="The ZIP code contains invalid characters." 
 *    invalidDomainError="The domain parameter is invalid. It must be either 'US Only', 'Canada Only', or 'US or Canada'." 
 *    wrongCAFormatError="The Canadian postal code must be formatted 'A1B 2C3'." 
 *    wrongLengthError="The ZIP code must be 5 digits or 5+4 digits." 
 *    wrongUSFormatError="The ZIP+4 code must be formatted '12345-6789'." 
 *  />
 *  
* * @see mx.validators.ZipCodeValidatorDomainType * * @includeExample examples/ZipCodeValidatorExample.mxml * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public class ZipCodeValidator extends Validator { include "../core/Version.as"; //-------------------------------------------------------------------------- // // Class constants // //-------------------------------------------------------------------------- /** * @private */ private static const DOMAIN_US:uint = 1; /** * @private */ private static const DOMAIN_US_OR_CANADA:uint = 2; /** * @private */ private static const DOMAIN_CANADA:uint = 3; //-------------------------------------------------------------------------- // // Class methods // //-------------------------------------------------------------------------- /** * Convenience method for calling a validator. * Each of the standard Flex validators has a similar convenience method. * * @param validator The ZipCodeValidator instance. * * @param value A field to validate. * * @param baseField Text representation of the subfield * specified in the value parameter. * For example, if the value parameter specifies value.zipCode, * the baseField value is "zipCode". * * @return An Array of ValidationResult objects, with one ValidationResult * object for each field examined by the validator. * * @see mx.validators.ValidationResult * * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public static function validateZipCode(validator:ZipCodeValidator, value:Object, baseField:String):Array { var results:Array = []; // Resource-backed properties of the validator. var allowedFormatChars:String = validator.allowedFormatChars; var domain:String = validator.domain; var resourceManager:IResourceManager = ResourceManager.getInstance(); var zip:String = String(value); var len:int = zip.length; var domainType:uint = DOMAIN_US; switch (domain) { case ZipCodeValidatorDomainType.US_OR_CANADA: { domainType = DOMAIN_US_OR_CANADA; break; } case ZipCodeValidatorDomainType.US_ONLY: { domainType = DOMAIN_US; break; } case ZipCodeValidatorDomainType.CANADA_ONLY: { domainType = DOMAIN_CANADA; break; } default: { results.push(new ValidationResult( true, baseField, "invalidDomain", validator.invalidDomainError)); return results; } } var n:int; var i:int; var c:String; // Make sure localAllowedFormatChars contains no numbers or letters. n = allowedFormatChars.length; for (i = 0; i < n; i++) { c = allowedFormatChars.charAt(i); if (DECIMAL_DIGITS.indexOf(c) != -1 || ROMAN_LETTERS.indexOf(c) != -1) { var message:String = resourceManager.getString( "validators", "invalidFormatCharsZCV"); throw new Error(message); } } // Now start checking the ZIP code. // At present, only US and Canadian ZIP codes are supported. // As a result, the easiest thing to check first // to determine the domain is the length. // A length of 5 or 10 means a US ZIP code // and a length of 6 or 7 means a Canadian ZIP. // If more countries are supported in the future, it may make sense // to check other conditions first depending on the domain specified // and all the possible ZIP code formats for that domain. // For now, this approach makes the most sense. // Make sure there are no invalid characters in the ZIP. for (i = 0; i < len; i++) { c = zip.charAt(i); if (ROMAN_LETTERS.indexOf(c) == -1 && DECIMAL_DIGITS.indexOf(c) == -1 && allowedFormatChars.indexOf(c) == -1) { results.push(new ValidationResult( true, baseField, "invalidChar", validator.invalidCharError)); return results; } } // Find out if the ZIP code contains any letters. var containsLetters:Boolean = false; for (i = 0; i < len; i++) { if (ROMAN_LETTERS.indexOf(zip.charAt(i)) != -1) { containsLetters = true; break; } } // do an initial check on the length if ((len < 5 || len > 10) || (len == 8) || (!containsLetters && (len == 6 || len == 7))) { // it's the wrong length for either a US or Canadian zip results.push(new ValidationResult( true, baseField, "wrongLength", validator.wrongLengthError)); return results; } // if we got this far, we're doing good so far switch (domainType) { case DOMAIN_US: { if (validator.validateUSCode(zip, containsLetters) == false) { results.push(new ValidationResult( true, baseField, "wrongUSFormat", validator.wrongUSFormatError)); return results; } break; } case DOMAIN_CANADA: { if (validator.validateCACode(zip, containsLetters) == false) { results.push(new ValidationResult( true, baseField, "wrongCAFormat", validator.wrongCAFormatError)); return results; } break; } case DOMAIN_US_OR_CANADA: { var valid:Boolean = true; var validationResult:ValidationResult; if (len == 5 || len == 9 || len == 10) // US { if (validator.validateUSCode(zip, containsLetters) == false) { validationResult = new ValidationResult( true, baseField, "wrongUSFormat", validator.wrongUSFormatError); valid = false; } } else // CA { if (validator.validateCACode(zip, containsLetters) == false) { validationResult = new ValidationResult( true, baseField, "wrongCAFormat", validator.wrongCAFormatError); valid = false; } } if (!valid) { results.push(validationResult); return results; } break; } } return results; } /** * @private */ private function validateUSCode (zip:String, containsLetters:Boolean):Boolean { var len:int = zip.length; if (containsLetters) { return false; } // Make sure the first 5 characters are all digits. var i:uint; for (i = 0; i < 5; i++) { if (DECIMAL_DIGITS.indexOf(zip.charAt(i)) == -1) { return false; } } if (len == 9 || len == 10) { if (len == 10) { // Make sure the 6th character // is an allowed formatting character. if (allowedFormatChars.indexOf(zip.charAt(5)) == -1) { return false; } i++; } // Make sure the remaining 4 characters are digits. for (; i < len; i++) { if (DECIMAL_DIGITS.indexOf(zip.charAt(i)) == -1) { return false; } } } return true; } /** * @private */ private function validateCACode (zip:String, containsLetters:Boolean):Boolean { var len:int = zip.length; // check the basics if (!containsLetters) { return false; } var i:uint = 0; // Make sure the zip is in the form 'ldlfdld' // where l is a letter, d is a digit, // and f is an allowed formatting character. if (ROMAN_LETTERS.indexOf(zip.charAt(i++)) == -1 || DECIMAL_DIGITS.indexOf(zip.charAt(i++)) == -1 || ROMAN_LETTERS.indexOf(zip.charAt(i++)) == -1) { return false; } if (len == 7 && allowedFormatChars.indexOf(zip.charAt(i++)) == -1) { return false; } if (DECIMAL_DIGITS.indexOf(zip.charAt(i++)) == -1 || ROMAN_LETTERS.indexOf(zip.charAt(i++)) == -1 || DECIMAL_DIGITS.indexOf(zip.charAt(i++)) == -1) { return false; } return true; } //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function ZipCodeValidator() { super(); } //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // allowedFormatChars //---------------------------------- /** * @private */ private var _allowedFormatChars:String; /** * @private */ private var allowedFormatCharsOverride:String; [Inspectable(category="General", defaultValue="null")] /** * The set of formatting characters allowed in the ZIP code. * This can not have digits or alphabets [a-z A-Z]. * * @default " -". * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get allowedFormatChars():String { return _allowedFormatChars; } /** * @private */ public function set allowedFormatChars(value:String):void { if (value != null) { for (var i:int = 0; i < value.length; i++) { var c:String = value.charAt(i); if (DECIMAL_DIGITS.indexOf(c) != -1 || ROMAN_LETTERS.indexOf(c) != -1) { var message:String = resourceManager.getString( "validators", "invalidFormatCharsZCV"); throw new Error(message); } } } allowedFormatCharsOverride = value; _allowedFormatChars = value != null ? value : resourceManager.getString( "validators", "zipCodeValidatorAllowedFormatChars"); } //---------------------------------- // domain //---------------------------------- /** * @private * Storage for the domain property. */ private var _domain:String; /** * @private */ private var domainOverride:String; [Inspectable(category="General", defaultValue="null")] /** * Type of ZIP code to check. * In MXML, valid values are "US or Canada", * "US Only" and "Canada Only". * *

In ActionScript, you can use the following constants to set this property: * ZipCodeValidatorDomainType.US_ONLY, * ZipCodeValidatorDomainType.US_OR_CANADA, or * ZipCodeValidatorDomainType.CANADA_ONLY.

* * @default ZipCodeValidatorDomainType.US_ONLY * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get domain():String { return _domain; } /** * @private */ public function set domain(value:String):void { domainOverride = value; _domain = value != null ? value : resourceManager.getString( "validators", "zipCodeValidatorDomain"); } //-------------------------------------------------------------------------- // // Properties: Errors // //-------------------------------------------------------------------------- //---------------------------------- // invalidCharError //---------------------------------- /** * @private * Storage for the invalidCharError property. */ private var _invalidCharError:String; /** * @private */ private var invalidCharErrorOverride:String; [Inspectable(category="Errors", defaultValue="null")] /** * Error message when the ZIP code contains invalid characters. * * @default "The ZIP code contains invalid characters." * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get invalidCharError():String { return _invalidCharError; } /** * @private */ public function set invalidCharError(value:String):void { invalidCharErrorOverride = value; _invalidCharError = value != null ? value : resourceManager.getString( "validators", "invalidCharErrorZCV"); } //---------------------------------- // invalidDomainError //---------------------------------- /** * @private * Storage for the invalidDomainError property. */ private var _invalidDomainError:String; /** * @private */ private var invalidDomainErrorOverride:String; [Inspectable(category="Errors", defaultValue="null")] /** * Error message when the domain property contains an invalid value. * * @default "The domain parameter is invalid. It must be either 'US Only' or 'US or Canada'." * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get invalidDomainError():String { return _invalidDomainError; } /** * @private */ public function set invalidDomainError(value:String):void { invalidDomainErrorOverride = value; _invalidDomainError = value != null ? value : resourceManager.getString( "validators", "invalidDomainErrorZCV"); } //---------------------------------- // wrongCAFormatError //---------------------------------- /** * @private * Storage for the wrongCAFormatError property. */ private var _wrongCAFormatError:String; /** * @private */ private var wrongCAFormatErrorOverride:String; [Inspectable(category="Errors", defaultValue="null")] /** * Error message for an invalid Canadian postal code. * * @default "The Canadian postal code must be formatted 'A1B 2C3'." * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get wrongCAFormatError():String { return _wrongCAFormatError; } /** * @private */ public function set wrongCAFormatError(value:String):void { wrongCAFormatErrorOverride = value; _wrongCAFormatError = value != null ? value : resourceManager.getString( "validators", "wrongCAFormatError"); } //---------------------------------- // wrongLengthError //---------------------------------- /** * @private * Storage for the wrongLengthError property. */ private var _wrongLengthError:String; /** * @private */ private var wrongLengthErrorOverride:String; [Inspectable(category="Errors", defaultValue="null")] /** * Error message for an invalid US ZIP code. * * @default "The ZIP code must be 5 digits or 5+4 digits." * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get wrongLengthError():String { return _wrongLengthError; } /** * @private */ public function set wrongLengthError(value:String):void { wrongLengthErrorOverride = value; _wrongLengthError = value != null ? value : resourceManager.getString( "validators", "wrongLengthErrorZCV"); } //---------------------------------- // wrongUSFormatError //---------------------------------- /** * @private * Storage for the wrongUSFormatError property. */ private var _wrongUSFormatError:String; /** * @private */ private var wrongUSFormatErrorOverride:String; [Inspectable(category="Errors", defaultValue="null")] /** * Error message for an incorrectly formatted ZIP code. * * @default "The ZIP+4 code must be formatted '12345-6789'." * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get wrongUSFormatError():String { return _wrongUSFormatError; } /** * @private */ public function set wrongUSFormatError(value:String):void { wrongUSFormatErrorOverride = value; _wrongUSFormatError = value != null ? value : resourceManager.getString( "validators", "wrongUSFormatError"); } //-------------------------------------------------------------------------- // // Overridden methods // //-------------------------------------------------------------------------- /** * @private */ override protected function resourcesChanged():void { super.resourcesChanged(); allowedFormatChars = allowedFormatCharsOverride; domain = domainOverride; invalidDomainError = invalidDomainErrorOverride; invalidCharError = invalidCharErrorOverride; wrongCAFormatError = wrongCAFormatErrorOverride; wrongLengthError = wrongLengthErrorOverride; wrongUSFormatError = wrongUSFormatErrorOverride; } /** * Override of the base class doValidation() method * to validate a ZIP code. * *

You do not call this method directly; * Flex calls it as part of performing a validation. * If you create a custom Validator class, you must implement this method.

* * @param value Object to validate. * * @return An Array of ValidationResult objects, with one ValidationResult * object for each field examined by the validator. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ override protected function doValidation(value:Object):Array { var results:Array = super.doValidation(value); // Return if there are errors // or if the required property is set to false and length is 0. var val:String = value ? String(value) : ""; if (results.length > 0 || ((val.length == 0) && !required)) return results; else return ZipCodeValidator.validateZipCode(this, value, null); } } }