📄 maskedtextinput.as
字号:
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2003-2006 Adobe Macromedia Software LLC and its licensors.
// All Rights Reserved. The following is Source Code and is subject to all
// restrictions on such code as contained in the End User License Agreement
// accompanying this product.
//
////////////////////////////////////////////////////////////////////////////////
package com.adobe.flex.extras.controls
{
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TextEvent;
import flash.ui.Keyboard;
import mx.controls.TextInput;
import mx.core.Application;
import mx.core.EdgeMetrics;
import mx.core.IFlexDisplayObject;
import mx.core.IInvalidating;
import mx.core.UIComponent;
import mx.core.UITextField;
import mx.core.mx_internal;
import mx.managers.FocusManager;
import mx.skins.Border;
import mx.skins.ProgrammaticSkin;
import mx.styles.ISimpleStyleClient;
import mx.skins.RectangularBorder;
import flash.text.TextFormat;
import flash.text.TextField;
import mx.controls.TextArea;
import flash.utils.getTimer;
import com.adobe.flex.extras.skins.MTISkin;
use namespace mx_internal;
//--------------------------------------
// Events
//--------------------------------------
/**
* Dispatched when the last character is entered in the
* Masked Text Input control through user input.
*
* @eventType flash.events.Event
* @tiptext inputMaskEnd event
*/
[Event(name="inputMaskEnd", type="flash.events.Event")]
//--------------------------------------
// Styles
//--------------------------------------
/**
* The color of the background cell.
* @default 0xFF0000 if required property is set, 0x008CEA otherwise
*/
[Style(name="cellColor", type="uint", format="Color",inherit="no")]
/**
* The color of the text when required property is set,
* and the field is left incomplete.
* @default 0xFF0000
*/
[Style(name="errorTextColor", type="uint", format="Color",inherit="no")]
//--------------------------------------
// Skins
//--------------------------------------
/**
* Name of the class to use as the skin for the background.
*
* @default "com.adobe.flex.extras.controls.skins.MTISkin"
*/
[Style(name="MTISkin", type="Class", inherit="no")]
/**
* The Masked Text Input component is a single-line,
* text input field. This component adds support for
* the validation of input against a specified mask expression.
* For using the control, input mask should be provided
* by setting the <code>inputMask</code> property of the
* control. This control shows meaningful behavior only
* when <code>inputMask</code> is specified in a correct manner.
*
* <p>If the mask is not specified correctly or it is
* not provided, then the control will work as a
* standard Text Input control.
*
* @mxml
*
* <p>The <code><mx:MaskedTextInput></code> tag inherits the attributes
* of its superclass and adds the following attributes:</p>
*
* <pre>
* <fc:MaskedTextInput
* <b>Properties</b>
* inputMask=""
* text=""
* fullText=""
* defaultCharacter="_"
* required=false
* autoAdvance=false
*
* <b>Styles</b>
* cellColor="0x008CEA"
* errorTextColor="0xFF0000"
*
* <b>Events</b>
* inputMaskEnd="<i>No default</i>"
* />
* </pre>
*
* @includeExample ../../../../../../docs/com/adobe/flex/extras/controls/example/MaskedTextInputExample/MaskedTextInputExample.mxml
*
* @see mx.controls.TextInput
*
* @tiptext TextInput is a single-line, editable text field.
*
*/
public class MaskedTextInput extends TextInput
{
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*/
public function MaskedTextInput()
{
super();
// Adding Listeners for various events
addEventListener(TextEvent.TEXT_INPUT,interceptChar,true,0);
addEventListener(MouseEvent.CLICK,reposition,true);
addEventListener(MouseEvent.MOUSE_DOWN,reposition,true);
addEventListener(KeyboardEvent.KEY_DOWN,interceptKey,true);
addEventListener(FocusEvent.FOCUS_IN,interceptFocus,false);
addEventListener(FocusEvent.FOCUS_OUT,interceptFocus);
addEventListener(Event.CHANGE,menuHandler);
// commented to retain the default Tab and Shift-Tab behavior
// uncomment if you want the focus to be shifted to the
// next/previous sub-field in case of a Tab/Shift-Tab respectively.
//addEventListener(FocusEvent.KEY_FOCUS_CHANGE,tabHandler);
this.doubleClickEnabled = true;
addEventListener(MouseEvent.DOUBLE_CLICK,handleDoubleClick,true);
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* @private
* The UITextField control for displaying embeded hints.
*/
private var embedTextField:UITextField;
/**
* @private
* Storage for Escape character.
*/
private const ESCAPE:String = "/";
/**
* Internal array to store the data in the Text Field.
*/
mx_internal var _working:Array = [];
/**
* @private
* Storage for current cursor position.
*/
private var _position:Number = 0;
/**
* @private
* Flag set when focus is set by using mouse click.
*/
private var focusByClick:Boolean = false;
/**
* @private
* Storage for the time when double click event happened.
*/
private var lastTime:Number = 0;
/**
* @private
* Flag set when _working is updated.
*/
private var workingUpdated:Boolean = false;
/**
* @private
* Flag set when inputMask is updated.
*/
private var maskUpdated:Boolean = false;
/**
* @private
* Flag set when text is updated.
*/
private var textUpdated:Boolean = false;
/**
* @private
* Flag set when font-family/font-size is updated.
*/
private var fontUpdated:Boolean = true;
/**
* @private
* Flag set when either the mask is entered wrongly or is not specified.
* The control will work as a standard Text Input if defaultBehaviour is set
*/
private var defaultBehaviour:Boolean = true;
/**
* @private
* Storage for the length of the Text Field.
*/
private var actualLength:Number=0;
/**
* @private
* The String to be shown as the embeded hint.
*/
private var embedStr:String = "";
/**
* @private
* Specifies that the field is a date only field.
*/
private var dateField:Boolean = false;
/**
* @private
* Skin names.
* Allows subclasses to re-define the skin property names.
*/
mx_internal var backgroundSkinName:String = "MTISkin";
/**
* @private
* Storage for the autoAdvance property.
*/
private var _autoAdvance:Boolean = false;
[Bindable("change")]
[Inspectable(category="General", defaultValue="false")]
/**
* If set to true, focus will automatically move to the next field
* in the tab order.
*
* @default false
*/
public function set autoAdvance( value:Boolean ) : void
{
_autoAdvance = value;
}
public function get autoAdvance() : Boolean
{
return _autoAdvance;
}
/**
* @private
* Storage for the required property.
*/
private var _required:Boolean = false;
[Bindable("change")]
[Inspectable(category="General", defaultValue="false")]
/**
* If set and if the field is left incomplete,
* the color of the characters in the field will be changed
* to errorTextColor or to red if errorTextColor is not specified,
*
* @default false
*/
public function set required( value:Boolean ) : void
{
_required = value;
// when required is changed dynamically,
// then the change should be reflected.
invalidateDisplayList();
}
public function get required() : Boolean
{
return _required;
}
/**
* @private
* Storage for the defaultCharacter property.
*/
private var _defaultCharacter:String = "_";
[Bindable("change")]
[Inspectable(category="General", defaultValue="_")]
/**
* The character used in place of an empty space
* when fullText is returned.
*
* @default "_"
*/
public function set defaultCharacter( str:String ) : void
{
_defaultCharacter = str.charAt(0);
}
public function get defaultCharacter() : String
{
return _defaultCharacter;
}
/**
* @private
* Storage for the input mask.
*/
private var _inputMask:String="";
[Bindable("change")]
[Inspectable(category="General", defaultValue="")]
/**
* The input mask used for validating the input.
*
*/
public function get inputMask() : String
{
return _inputMask;
}
public function set inputMask(s:String) : void
{
maskMap = [];
_inputMask = s;
dateField = false;
switch(_inputMask)
{
case "MM/DD/YYYY" : _inputMask = "##//##//####";
embedStr = "MM DD YYYY";
dateField = true;
break;
case "DD/MM/YYYY" : _inputMask = "##//##//####";
embedStr = "DD MM YYYY";
dateField = true;
break;
case "YYYY/MM/DD" : _inputMask = "####//##//##";
embedStr = "YYYY MM DD";
dateField = true;
break;
case "YYYY/DD/MM" : _inputMask = "####//##//##";
embedStr = "YYYY DD MM";
dateField = true;
break;
default: break;
}
defaultBehaviour = false;
checkMask();
actualLength = calculateMaxChars();
if(!defaultBehaviour)
maxChars = actualLength;
maskUpdated = true;
invalidateDisplayList();
}
/**
* @private
* Storage for the text property.
*/
private var _text:String = "";
[Bindable("change")]
[Bindable("valueCommit")]
[Inspectable(category="General", defaultValue="")]
/**
* Returns only the text entered by the user.
*/
override public function get text():String
{
if(defaultBehaviour)
return super.text;
var result:String = "";
for(var i:Number=0; i < _working.length; i++) {
var c:String = _working[i];
if(!maskMap[i][1])
{
continue;
}
else if(c == " ")
c = "";
result += c;
}
return result;
}
override public function set text(value:String):void
{
if(defaultBehaviour)
{
super.text = value;
//invalidateDisplayList();
return;
}
_text = value;
textUpdated = true;
invalidateDisplayList();
}
[Bindable("change")]
[Bindable("valueCommit")]
[Inspectable(category="General", defaultValue="")]
/**
* Returns the whole text displayed in the Text Field.
*/
public function get fullText() : String
{
if(defaultBehaviour)
return super.text;
var result:String = "";
for(var i:Number=0; i < _working.length; i++) {
var c:String = _working[i];
if( c == " " ) c = _defaultCharacter;
result += c;
}
return result;
}
/**
* Internal array to store each character in the mask
* and whether it is to be entered by the user or displayed as it is.
*/
mx_internal var maskMap:Array;
/**
* @private
* Calculate the number of characters which are displayed
* (i.e., number of character in the inputMask excluding
* the ESCAPE character) and can be entered in the text field.
* Also populate the array maskMap which specifies that
* a character at a particular position is to be
* entered by the user or displayed as it is.
*/
private function calculateMaxChars():Number
{
maskMap = new Array();
var count:Number = 0;
for(var i:int=0,k:int=0;i<_inputMask.length;i++,k++)
{
if((_inputMask.charAt(i) == ESCAPE && _inputMask.charAt(i+1) == ESCAPE)
|| (_inputMask.charAt(i) == ESCAPE && isMask(_inputMask.charAt(i+1))))
{
maskMap[k] = [_inputMask.charAt(i+1), false];
i++;
}
else if(isMask(_inputMask.charAt(i)))
{
maskMap[k] = [_inputMask.charAt(i), true];
}
else
maskMap[k] = [_inputMask.charAt(i), false];
count++;
}
return count;
}
/**
* @private
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -