1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2003-2007 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package mx.validators 13{ 14 15import flash.events.Event; 16import flash.events.EventDispatcher; 17import flash.events.IEventDispatcher; 18import mx.binding.BindingManager; 19import mx.core.IMXMLObject; 20import mx.events.FlexEvent; 21import mx.events.ValidationResultEvent; 22import mx.managers.ISystemManager; 23import mx.managers.SystemManager; 24import mx.resources.IResourceManager; 25import mx.resources.ResourceManager; 26import mx.validators.IValidator; 27 28//-------------------------------------- 29// Events 30//-------------------------------------- 31 32/** 33 * Dispatched when validation succeeds. 34 * 35 * @eventType mx.events.ValidationResultEvent.VALID 36 * 37 * @langversion 3.0 38 * @playerversion Flash 9 39 * @playerversion AIR 1.1 40 * @productversion Flex 3 41 */ 42[Event(name="valid", type="mx.events.ValidationResultEvent")] 43 44/** 45 * Dispatched when validation fails. 46 * 47 * @eventType mx.events.ValidationResultEvent.INVALID 48 * 49 * @langversion 3.0 50 * @playerversion Flash 9 51 * @playerversion AIR 1.1 52 * @productversion Flex 3 53 */ 54[Event(name="invalid", type="mx.events.ValidationResultEvent")] 55 56//-------------------------------------- 57// Other metadata 58//-------------------------------------- 59 60[ResourceBundle("core")] 61[ResourceBundle("validators")] 62 63/** 64 * The Validator class is the base class for all Flex validators. 65 * This class implements the ability for a validator to make a field 66 * required, which means that the user must enter a value in the field 67 * or the validation fails. 68 * 69 * @mxml 70 * 71 * <p>The Validator class defines the following tag attributes, 72 * which all of its subclasses inherit:</p> 73 * 74 * <pre> 75 * <mx:Validator 76 * enabled="true|false" 77 * listener="<i>Value of the source property</i>" 78 * property="<i>No default</i>" 79 * required="true|false" 80 * requiredFieldError="This field is required." 81 * source="<i>No default</i>" 82 * trigger="<i>Value of the source property</i>" 83 * triggerEvent="valueCommit" 84 * /> 85 * </pre> 86 * 87 * @see mx.events.ValidationResultEvent 88 * @see mx.validators.ValidationResult 89 * @see mx.validators.RegExpValidationResult 90 * 91 * @includeExample examples/SimpleValidatorExample.mxml 92 * 93 * @langversion 3.0 94 * @playerversion Flash 9 95 * @playerversion AIR 1.1 96 * @productversion Flex 3 97 */ 98public class Validator extends EventDispatcher implements IMXMLObject,IValidator 99{ 100 include "../core/Version.as"; 101 102 //-------------------------------------------------------------------------- 103 // 104 // Class constants 105 // 106 //-------------------------------------------------------------------------- 107 108 /** 109 * A string containing the upper- and lower-case letters 110 * of the Roman alphabet ("A" through "Z" and "a" through "z"). 111 * 112 * @langversion 3.0 113 * @playerversion Flash 9 114 * @playerversion AIR 1.1 115 * @productversion Flex 3 116 */ 117 protected static const ROMAN_LETTERS:String = 118 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 119 120 /** 121 * A String containing the decimal digits 0 through 9. 122 * 123 * @langversion 3.0 124 * @playerversion Flash 9 125 * @playerversion AIR 1.1 126 * @productversion Flex 3 127 */ 128 protected static const DECIMAL_DIGITS:String = "0123456789"; 129 130 //-------------------------------------------------------------------------- 131 // 132 // Class methods 133 // 134 //-------------------------------------------------------------------------- 135 136 /** 137 * Invokes all the validators in the <code>validators</code> Array. 138 * Returns an Array containing one ValidationResultEvent object 139 * for each validator that failed. 140 * Returns an empty Array if all validators succeed. 141 * 142 * @param validators An Array containing the Validator objects to execute. 143 * 144 * @return Array of ValidationResultEvent objects, where the Array 145 * contains one ValidationResultEvent object for each validator 146 * that failed. 147 * The Array is empty if all validators succeed. 148 * 149 * @langversion 3.0 150 * @playerversion Flash 9 151 * @playerversion AIR 1.1 152 * @productversion Flex 3 153 */ 154 public static function validateAll(validators:Array):Array 155 { 156 var result:Array = []; 157 158 var n:int = validators.length; 159 for (var i:int = 0; i < n; i++) 160 { 161 var v:IValidator = validators[i] as IValidator; 162 if (v && v.enabled) 163 { 164 var resultEvent:ValidationResultEvent = v.validate(); 165 166 if (resultEvent.type != ValidationResultEvent.VALID) 167 result.push(resultEvent); 168 } 169 } 170 171 return result; 172 } 173 174 /** 175 * @private 176 */ 177 private static function findObjectFromString(doc:Object, 178 value:String):Object 179 { 180 var obj:Object = doc; 181 var parts:Array = value.split("."); 182 183 var n:int = parts.length; 184 for (var i:int = 0; i < n; i++) 185 { 186 try 187 { 188 obj = obj[parts[i]]; 189 190 // There's no guarantee that the objects have 191 // already been created when this function fires; 192 // for example, in the deferred instantiation case, 193 // this function fires before the object for validation 194 // has been created. 195 if (obj == null) 196 { 197 //return true; 198 } 199 } 200 catch(error:Error) 201 { 202 if ((error is TypeError) && 203 (error.message.indexOf("null has no properties") != -1)) 204 { 205 var resourceManager:IResourceManager = 206 ResourceManager.getInstance(); 207 var message:String = resourceManager.getString( 208 "validators", "fieldNotFound", [ value ]); 209 throw new Error(message); 210 } 211 else 212 { 213 throw error; 214 } 215 } 216 } 217 218 return obj; 219 } 220 221 /** 222 * @private 223 */ 224 private static function trimString(str:String):String 225 { 226 var startIndex:int = 0; 227 while (str.indexOf(' ', startIndex) == startIndex) 228 { 229 ++startIndex; 230 } 231 232 var endIndex:int = str.length - 1; 233 while (str.lastIndexOf(' ', endIndex) == endIndex) 234 { 235 --endIndex; 236 } 237 238 return endIndex >= startIndex ? 239 str.slice(startIndex, endIndex + 1) : 240 ""; 241 } 242 243 //-------------------------------------------------------------------------- 244 // 245 // Constructor 246 // 247 //-------------------------------------------------------------------------- 248 249 /** 250 * Constructor. 251 * 252 * @langversion 3.0 253 * @playerversion Flash 9 254 * @playerversion AIR 1.1 255 * @productversion Flex 3 256 */ 257 public function Validator() 258 { 259 super(); 260 261 // Register as a weak listener for "change" events from ResourceManager. 262 // If Validators registered as a strong listener, 263 // they wouldn't get garbage collected. 264 resourceManager.addEventListener( 265 Event.CHANGE, resourceManager_changeHandler, false, 0, true); 266 267 resourcesChanged(); 268 } 269 270 //-------------------------------------------------------------------------- 271 // 272 // Variables 273 // 274 //-------------------------------------------------------------------------- 275 276 /** 277 * @private 278 */ 279 private var document:Object; 280 281 //-------------------------------------------------------------------------- 282 // 283 // Properties 284 // 285 //-------------------------------------------------------------------------- 286 287 //---------------------------------- 288 // actualTrigger 289 //---------------------------------- 290 291 /** 292 * Contains the trigger object, if any, 293 * or the source object. Used to determine the listener object 294 * for the <code>triggerEvent</code>. 295 * 296 * @langversion 3.0 297 * @playerversion Flash 9 298 * @playerversion AIR 1.1 299 * @productversion Flex 3 300 */ 301 protected function get actualTrigger():IEventDispatcher 302 { 303 if (_trigger) 304 return _trigger; 305 306 else if (_source) 307 return _source as IEventDispatcher; 308 309 return null; 310 } 311 312 //---------------------------------- 313 // actualListeners 314 //---------------------------------- 315 316 /** 317 * Contains an Array of listener objects, if any, 318 * or the source object. Used to determine which object 319 * to notify about the validation result. 320 * 321 * @langversion 3.0 322 * @playerversion Flash 9 323 * @playerversion AIR 1.1 324 * @productversion Flex 3 325 */ 326 protected function get actualListeners():Array 327 { 328 var result:Array = []; 329 330 if (_listener) 331 result.push(_listener); 332 333 else if (_source) 334 result.push(_source); 335 336 return result; 337 } 338 339 //---------------------------------- 340 // enabled 341 //---------------------------------- 342 343 /** 344 * @private 345 * Storage for the enabled property. 346 */ 347 private var _enabled:Boolean = true; 348 349 [Inspectable(category="General", defaultValue="true")] 350 351 /** 352 * Setting this value to <code>false</code> will stop the validator 353 * from performing validation. 354 * When a validator is disabled, it dispatch no events, 355 * and the <code>validate()</code> method returns null. 356 * 357 * @default true 358 * 359 * @langversion 3.0 360 * @playerversion Flash 9 361 * @playerversion AIR 1.1 362 * @productversion Flex 3 363 */ 364 public function get enabled():Boolean 365 { 366 return _enabled; 367 } 368 369 /** 370 * @private 371 */ 372 public function set enabled(value:Boolean):void 373 { 374 _enabled = value; 375 } 376 377 //---------------------------------- 378 // listener 379 //---------------------------------- 380 381 /** 382 * @private 383 * Storage for the listener property. 384 */ 385 private var _listener:Object; 386 387 [Inspectable(category="General")] 388 389 /** 390 * Specifies the validation listener. 391 * 392 * <p>If you do not specify a listener, 393 * Flex uses the value of the <code>source</code> property. 394 * After Flex determines the source component, 395 * it changes the border color of the component, 396 * displays an error message for a failure, 397 * or hides any existing error message for a successful validation.</p> 398 * 399 * 400 * @langversion 3.0 401 * @playerversion Flash 9 402 * @playerversion AIR 1.1 403 * @productversion Flex 3 404 */ 405 406 /* This behavior has been removed. 407 * <p>If Flex does not find an appropriate listener, 408 * validation errors propagate to the Application object, causing Flex 409 * to display an Alert box containing the validation error message.</p> 410 * 411 * <p>Specifying <code>this</code> causes the validation error 412 * to propagate to the Application object, 413 * and displays an Alert box containing the validation error message.</p> 414 * 415 * @langversion 3.0 416 * @playerversion Flash 9 417 * @playerversion AIR 1.1 418 * @productversion Flex 3 419 */ 420 public function get listener():Object 421 { 422 return _listener; 423 } 424 425 /** 426 * @private 427 */ 428 public function set listener(value:Object):void 429 { 430 removeListenerHandler(); 431 _listener = value; 432 addListenerHandler(); 433 } 434 435 //---------------------------------- 436 // property 437 //---------------------------------- 438 439 /** 440 * @private 441 * Storage for the property property. 442 */ 443 private var _property:String; 444 445 [Inspectable(category="General")] 446 447 /** 448 * A String specifying the name of the property 449 * of the <code>source</code> object that contains 450 * the value to validate. 451 * The property is optional, but if you specify <code>source</code>, 452 * you should set a value for this property as well. 453 * 454 * @default null 455 * 456 * @langversion 3.0 457 * @playerversion Flash 9 458 * @playerversion AIR 1.1 459 * @productversion Flex 3 460 */ 461 public function get property():String 462 { 463 return _property; 464 } 465 466 /** 467 * @private 468 */ 469 public function set property(value:String):void 470 { 471 _property = value; 472 } 473 474 //---------------------------------- 475 // required 476 //---------------------------------- 477 478 [Inspectable(category="General", defaultValue="true")] 479 480 /** 481 * If <code>true</code>, specifies that a missing or empty 482 * value causes a validation error. 483 * 484 * @default true 485 * 486 * @langversion 3.0 487 * @playerversion Flash 9 488 * @playerversion AIR 1.1 489 * @productversion Flex 3 490 */ 491 public var required:Boolean = true; 492 493 //---------------------------------- 494 // resourceManager 495 //---------------------------------- 496 497 /** 498 * @private 499 * Storage for the resourceManager property. 500 */ 501 private var _resourceManager:IResourceManager = ResourceManager.getInstance(); 502 503 /** 504 * @private 505 * This metadata suppresses a trace() in PropertyWatcher: 506 * "warning: unable to bind to property 'resourceManager' ..." 507 */ 508 [Bindable("unused")] 509 510 /** 511 * @copy mx.core.UIComponent#resourceManager 512 * 513 * @langversion 3.0 514 * @playerversion Flash 9 515 * @playerversion AIR 1.1 516 * @productversion Flex 3 517 */ 518 protected function get resourceManager():IResourceManager 519 { 520 return _resourceManager; 521 } 522 523 //---------------------------------- 524 // source 525 //---------------------------------- 526 527 /** 528 * @private 529 * Storage for the source property. 530 */ 531 private var _source:Object; 532 533 [Inspectable(category="General")] 534 535 /** 536 * Specifies the object containing the property to validate. 537 * Set this to an instance of a component or a data model. 538 * You use data binding syntax in MXML to specify the value. 539 * This property supports dot-delimited Strings 540 * for specifying nested properties. 541 * 542 * If you specify a value to the <code>source</code> property, 543 * then you should specify a value to the <code>property</code> 544 * property as well. 545 * The <code>source</code> property is optional. 546 * 547 * @default null 548 * 549 * @langversion 3.0 550 * @playerversion Flash 9 551 * @playerversion AIR 1.1 552 * @productversion Flex 3 553 */ 554 public function get source():Object 555 { 556 return _source; 557 } 558 559 /** 560 * @private 561 */ 562 public function set source(value:Object):void 563 { 564 if (_source == value) 565 return; 566 567 if (value is String) 568 { 569 var message:String = resourceManager.getString( 570 "validators", "SAttribute", [ value ]); 571 throw new Error(message); 572 } 573 574 // Remove the listener from the old source. 575 removeTriggerHandler(); 576 removeListenerHandler(); 577 578 _source = value; 579 580 // Listen for the trigger event on the new source. 581 addTriggerHandler(); 582 addListenerHandler(); 583 } 584 585 //---------------------------------- 586 // subFields 587 //---------------------------------- 588 589 /** 590 * An Array of Strings containing the names for the properties contained 591 * in the <code>value</code> Object passed to the <code>validate()</code> method. 592 * For example, CreditCardValidator sets this property to 593 * <code>[ "cardNumber", "cardType" ]</code>. 594 * This value means that the <code>value</code> Object 595 * passed to the <code>validate()</code> method 596 * should contain a <code>cardNumber</code> and a <code>cardType</code> property. 597 * 598 * <p>Subclasses of the Validator class that 599 * validate multiple data fields (like CreditCardValidator and DateValidator) 600 * should assign this property in their constructor. </p> 601 * 602 * @langversion 3.0 603 * @playerversion Flash 9 604 * @playerversion AIR 1.1 605 * @productversion Flex 3 606 */ 607 protected var subFields:Array = []; 608 609 //---------------------------------- 610 // trigger 611 //---------------------------------- 612 613 /** 614 * @private 615 * Storage for the trigger property. 616 */ 617 private var _trigger:IEventDispatcher; 618 619 [Inspectable(category="General")] 620 621 /** 622 * Specifies the component generating the event that triggers the validator. 623 * If omitted, by default Flex uses the value of the <code>source</code> property. 624 * When the <code>trigger</code> dispatches a <code>triggerEvent</code>, 625 * validation executes. 626 * 627 * @langversion 3.0 628 * @playerversion Flash 9 629 * @playerversion AIR 1.1 630 * @productversion Flex 3 631 */ 632 public function get trigger():IEventDispatcher 633 { 634 return _trigger; 635 } 636 637 /** 638 * @private 639 */ 640 public function set trigger(value:IEventDispatcher):void 641 { 642 removeTriggerHandler(); 643 _trigger = value; 644 addTriggerHandler(); 645 } 646 647 //---------------------------------- 648 // triggerEvent 649 //---------------------------------- 650 651 /** 652 * @private 653 * Storage for the triggerEvent property. 654 */ 655 private var _triggerEvent:String = FlexEvent.VALUE_COMMIT; 656 657 [Inspectable(category="General")] 658 659 /** 660 * Specifies the event that triggers the validation. 661 * If omitted, Flex uses the <code>valueCommit</code> event. 662 * Flex dispatches the <code>valueCommit</code> event 663 * when a user completes data entry into a control. 664 * Usually this is when the user removes focus from the component, 665 * or when a property value is changed programmatically. 666 * If you want a validator to ignore all events, 667 * set <code>triggerEvent</code> to the empty string (""). 668 * 669 * @langversion 3.0 670 * @playerversion Flash 9 671 * @playerversion AIR 1.1 672 * @productversion Flex 3 673 */ 674 public function get triggerEvent():String 675 { 676 return _triggerEvent; 677 } 678 679 /** 680 * @private 681 */ 682 public function set triggerEvent(value:String):void 683 { 684 if (_triggerEvent == value) 685 return; 686 687 removeTriggerHandler(); 688 _triggerEvent = value; 689 addTriggerHandler(); 690 } 691 692 //-------------------------------------------------------------------------- 693 // 694 // Properties: Errors 695 // 696 //-------------------------------------------------------------------------- 697 698 //---------------------------------- 699 // requiredFieldError 700 //---------------------------------- 701 702 /** 703 * @private 704 * Storage for the requiredFieldError property. 705 */ 706 private var _requiredFieldError:String; 707 708 /** 709 * @private 710 */ 711 private var requiredFieldErrorOverride:String; 712 713 [Inspectable(category="Errors", defaultValue="null")] 714 715 /** 716 * Error message when a value is missing and the 717 * <code>required</code> property is <code>true</code>. 718 * 719 * @default "This field is required." 720 * 721 * @langversion 3.0 722 * @playerversion Flash 9 723 * @playerversion AIR 1.1 724 * @productversion Flex 3 725 */ 726 public function get requiredFieldError():String 727 { 728 return _requiredFieldError; 729 } 730 731 /** 732 * @private 733 */ 734 public function set requiredFieldError(value:String):void 735 { 736 requiredFieldErrorOverride = value; 737 738 _requiredFieldError = value != null ? 739 value : 740 resourceManager.getString( 741 "validators", "requiredFieldError"); 742 } 743 744 //-------------------------------------------------------------------------- 745 // 746 // Methods: IMXMLObject 747 // 748 //-------------------------------------------------------------------------- 749 750 /** 751 * Called automatically by the MXML compiler when the Validator 752 * is created using an MXML tag. 753 * 754 * @param document The MXML document containing this Validator. 755 * 756 * @param id Ignored. 757 * 758 * @langversion 3.0 759 * @playerversion Flash 9 760 * @playerversion AIR 1.1 761 * @productversion Flex 3 762 */ 763 public function initialized(document:Object, id:String):void 764 { 765 this.document = document; 766 } 767 768 //-------------------------------------------------------------------------- 769 // 770 // Methods 771 // 772 //-------------------------------------------------------------------------- 773 774 /** 775 * This method is called when a Validator is constructed, 776 * and again whenever the ResourceManager dispatches 777 * a <code>"change"</code> Event to indicate 778 * that the localized resources have changed in some way. 779 * 780 * <p>This event will be dispatched when you set the ResourceManager's 781 * <code>localeChain</code> property, when a resource module 782 * has finished loading, and when you call the ResourceManager's 783 * <code>update()</code> method.</p> 784 * 785 * <p>Subclasses should override this method and, after calling 786 * <code>super.resourcesChanged()</code>, do whatever is appropriate 787 * in response to having new resource values.</p> 788 * 789 * @langversion 3.0 790 * @playerversion Flash 9 791 * @playerversion AIR 1.1 792 * @productversion Flex 3 793 */ 794 protected function resourcesChanged():void 795 { 796 requiredFieldError = requiredFieldErrorOverride; 797 } 798 799 /** 800 * @private 801 */ 802 private function addTriggerHandler():void 803 { 804 if (actualTrigger) 805 actualTrigger.addEventListener(_triggerEvent, triggerHandler); 806 } 807 808 /** 809 * @private 810 */ 811 private function removeTriggerHandler():void 812 { 813 if (actualTrigger) 814 actualTrigger.removeEventListener(_triggerEvent, triggerHandler); 815 } 816 817 /** 818 * Sets up all of the listeners for the 819 * <code>valid</code> and <code>invalid</code> 820 * events dispatched from the validator. Subclasses of the Validator class 821 * should first call the <code>removeListenerHandler()</code> method, 822 * and then the <code>addListenerHandler()</code> method if 823 * the value of one of their listeners or sources changes. 824 * The CreditCardValidator and DateValidator classes use this function internally. 825 * 826 * @langversion 3.0 827 * @playerversion Flash 9 828 * @playerversion AIR 1.1 829 * @productversion Flex 3 830 */ 831 protected function addListenerHandler():void 832 { 833 var actualListener:Object; 834 var listeners:Array = actualListeners; 835 836 var n:int = listeners.length; 837 for (var i:int = 0; i < n; i++) 838 { 839 actualListener = listeners[i]; 840 if (actualListener is IValidatorListener) 841 { 842 addEventListener(ValidationResultEvent.VALID, 843 IValidatorListener(actualListener).validationResultHandler); 844 845 addEventListener(ValidationResultEvent.INVALID, 846 IValidatorListener(actualListener).validationResultHandler); 847 } 848 } 849 } 850 851 /** 852 * Disconnects all of the listeners for the 853 * <code>valid</code> and <code>invalid</code> 854 * events dispatched from the validator. Subclasses should first call the 855 * <code>removeListenerHandler()</code> method and then the 856 * <code>addListenerHandler</code> method if 857 * the value of one of their listeners or sources changes. 858 * The CreditCardValidator and DateValidator classes use this function internally. 859 * 860 * @langversion 3.0 861 * @playerversion Flash 9 862 * @playerversion AIR 1.1 863 * @productversion Flex 3 864 */ 865 protected function removeListenerHandler():void 866 { 867 var actualListener:Object; 868 var listeners:Array = actualListeners; 869 870 var n:int = listeners.length; 871 for (var i:int = 0; i < n; i++) 872 { 873 actualListener = listeners[i]; 874 if (actualListener is IValidatorListener) 875 { 876 removeEventListener(ValidationResultEvent.VALID, 877 IValidatorListener(actualListener).validationResultHandler); 878 879 removeEventListener(ValidationResultEvent.INVALID, 880 IValidatorListener(actualListener).validationResultHandler); 881 } 882 } 883 } 884 885 /** 886 * Returns <code>true</code> if <code>value</code> is not null. 887 * 888 * @param value The value to test. 889 * 890 * @return <code>true</code> if <code>value</code> is not null. 891 * 892 * @langversion 3.0 893 * @playerversion Flash 9 894 * @playerversion AIR 1.1 895 * @productversion Flex 3 896 */ 897 protected function isRealValue(value:Object):Boolean 898 { 899 return (value != null); 900 } 901 902 /** 903 * Performs validation and optionally notifies 904 * the listeners of the result. 905 * 906 * @param value Optional value to validate. 907 * If null, then the validator uses the <code>source</code> and 908 * <code>property</code> properties to determine the value. 909 * If you specify this argument, you should also set the 910 * <code>listener</code> property to specify the target component 911 * for any validation error messages. 912 * 913 * @param suppressEvents If <code>false</code>, then after validation, 914 * the validator will notify the listener of the result. 915 * 916 * @return A ValidationResultEvent object 917 * containing the results of the validation. 918 * For a successful validation, the 919 * <code>ValidationResultEvent.results</code> Array property is empty. 920 * For a validation failure, the 921 * <code>ValidationResultEvent.results</code> Array property contains 922 * one ValidationResult object for each field checked by the validator, 923 * both for fields that failed the validation and for fields that passed. 924 * Examine the <code>ValidationResult.isError</code> 925 * property to determine if the field passed or failed the validation. 926 * 927 * @see mx.events.ValidationResultEvent 928 * @see mx.validators.ValidationResult 929 * 930 * @langversion 3.0 931 * @playerversion Flash 9 932 * @playerversion AIR 1.1 933 * @productversion Flex 3 934 */ 935 public function validate( 936 value:Object = null, 937 suppressEvents:Boolean = false):ValidationResultEvent 938 { 939 if (value == null) 940 value = getValueFromSource(); 941 942 if (isRealValue(value) || required) 943 { 944 // Validate if the target is required or our value is non-null. 945 return processValidation(value, suppressEvents); 946 } 947 else 948 { 949 // We assume if value is null and required is false that 950 // validation was successful. 951 var resultEvent:ValidationResultEvent = 952 new ValidationResultEvent(ValidationResultEvent.VALID); 953 if (!suppressEvents && _enabled) 954 { 955 dispatchEvent(resultEvent); 956 } 957 return resultEvent; 958 } 959 } 960 961 /** 962 * Returns the Object to validate. Subclasses, such as the 963 * CreditCardValidator and DateValidator classes, 964 * override this method because they need 965 * to access the values from multiple subfields. 966 * 967 * @return The Object to validate. 968 * 969 * @langversion 3.0 970 * @playerversion Flash 9 971 * @playerversion AIR 1.1 972 * @productversion Flex 3 973 */ 974 protected function getValueFromSource():Object 975 { 976 var message:String; 977 978 if (_source && _property) 979 { 980 return _source[_property]; 981 } 982 983 else if (!_source && _property) 984 { 985 message = resourceManager.getString( 986 "validators", "SAttributeMissing"); 987 throw new Error(message); 988 } 989 990 else if (_source && !_property) 991 { 992 message = resourceManager.getString( 993 "validators", "PAttributeMissing"); 994 throw new Error(message); 995 } 996 997 return null; 998 } 999 1000 /** 1001 * @private 1002 * Main internally used function to handle validation process. 1003 */ 1004 private function processValidation( 1005 value:Object, 1006 suppressEvents:Boolean):ValidationResultEvent 1007 { 1008 var resultEvent:ValidationResultEvent; 1009 1010 if (_enabled) 1011 { 1012 var errorResults:Array = doValidation(value); 1013 1014 resultEvent = handleResults(errorResults); 1015 } 1016 else 1017 { 1018 suppressEvents = true; // Don't send any events 1019 } 1020 1021 if (!suppressEvents) 1022 { 1023 dispatchEvent(resultEvent); 1024 } 1025 1026 return resultEvent; 1027 } 1028 1029 /** 1030 * Executes the validation logic of this validator, 1031 * including validating that a missing or empty value 1032 * causes a validation error as defined by 1033 * the value of the <code>required</code> property. 1034 * 1035 * <p>If you create a subclass of a validator class, 1036 * you must override this method. </p> 1037 * 1038 * @param value Value to validate. 1039 * 1040 * @return For an invalid result, an Array of ValidationResult objects, 1041 * with one ValidationResult object for each field examined 1042 * by the validator that failed validation. 1043 * 1044 * @see mx.validators.ValidationResult 1045 * 1046 * @langversion 3.0 1047 * @playerversion Flash 9 1048 * @playerversion AIR 1.1 1049 * @productversion Flex 3 1050 */ 1051 protected function doValidation(value:Object):Array 1052 { 1053 var results:Array = []; 1054 1055 var result:ValidationResult = validateRequired(value); 1056 if (result) 1057 results.push(result); 1058 1059 return results; 1060 } 1061 1062 /** 1063 * @private 1064 * Determines if an object is valid based on its 1065 * <code>required</code> property. 1066 * This is a convenience method for calling a validator from within a 1067 * custom validation function. 1068 */ 1069 private function validateRequired(value:Object):ValidationResult 1070 { 1071 if (required) 1072 { 1073 var val:String = (value != null) ? String(value) : ""; 1074 1075 val = trimString(val); 1076 1077 // If the string is empty and required is set to true 1078 // then throw a requiredFieldError. 1079 if (val.length == 0) 1080 { 1081 return new ValidationResult(true, "", "requiredField", 1082 requiredFieldError); 1083 } 1084 } 1085 1086 return null; 1087 } 1088 1089 /** 1090 * Returns a ValidationResultEvent from the Array of error results. 1091 * Internally, this function takes the results from the 1092 * <code>doValidation()</code> method and puts it into a ValidationResultEvent object. 1093 * Subclasses, such as the RegExpValidator class, 1094 * should override this function if they output a subclass 1095 * of ValidationResultEvent objects, such as the RegExpValidationResult objects, and 1096 * needs to populate the object with additional information. You never 1097 * call this function directly, and you should rarely override it. 1098 * 1099 * @param errorResults Array of ValidationResult objects. 1100 * 1101 * @return The ValidationResultEvent returned by the <code>validate()</code> method. 1102 * 1103 * @langversion 3.0 1104 * @playerversion Flash 9 1105 * @playerversion AIR 1.1 1106 * @productversion Flex 3 1107 */ 1108 protected function handleResults(errorResults:Array):ValidationResultEvent 1109 { 1110 var resultEvent:ValidationResultEvent; 1111 1112 if (errorResults.length > 0) 1113 { 1114 resultEvent = 1115 new ValidationResultEvent(ValidationResultEvent.INVALID); 1116 resultEvent.results = errorResults; 1117 1118 if (subFields.length > 0) 1119 { 1120 var errorFields:Object = {}; 1121 var subField:String; 1122 1123 // Now we need to send valid results 1124 // for every subfield that didn't fail. 1125 var n:int; 1126 var i:int; 1127 1128 n = errorResults.length; 1129 for (i = 0; i < n; i++) 1130 { 1131 subField = errorResults[i].subField; 1132 if (subField) 1133 { 1134 errorFields[subField] = true; 1135 } 1136 } 1137 1138 n = subFields.length; 1139 for (i = 0; i < n; i++) 1140 { 1141 if (!errorFields[subFields[i]]) 1142 { 1143 errorResults.push(new ValidationResult(false,subFields[i])); 1144 } 1145 } 1146 } 1147 } 1148 else 1149 { 1150 resultEvent = new ValidationResultEvent(ValidationResultEvent.VALID); 1151 } 1152 1153 return resultEvent; 1154 } 1155 1156 //-------------------------------------------------------------------------- 1157 // 1158 // Event handlers 1159 // 1160 //-------------------------------------------------------------------------- 1161 1162 /** 1163 * @private 1164 */ 1165 private function triggerHandler(event:Event):void 1166 { 1167 validate(); 1168 } 1169 1170 /** 1171 * @private 1172 */ 1173 private function resourceManager_changeHandler(event:Event):void 1174 { 1175 resourcesChanged(); 1176 } 1177} 1178 1179} 1180