You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by William Hoover <wh...@nemours.org> on 2007/10/18 18:06:20 UTC

Input Text Mask?

Is anyone interested in using the mask script (below) to a component in a Wicket extension? The script prevents invalid input in a text field as the user types (similar to the Atlas version: http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx). I didn't see a component in Wicket that would accomplish this out-of-the-box and thought it would be a cool addition to Wicket. 

For example to force the input to mask a phone number:
<input type="text" onfocus="InputTextMask.processMaskFocus(this, "(999)999-9999", true);" />

/**
 * InputTextMask script used for mask/regexp operations.
 * Mask Individual Character Usage:
 * 9 - designates only numeric values
 * L - designates only uppercase letter values
 * l - designates only lowercase letter values
 * A - designates only alphanumeric values
 * X - denotes that a custom client script regular expression is specified</li>
 * All other characters are assumed to be "special" characters used to mask
 * the input component
 * Example 1:
 * (999)999-9999 only numeric values can be entered where the the character
 * position value is 9. Parenthesis and dash are non-editable/mask characters.
 * Example 2:
 * 99L-ll-X[^A-C]X only numeric values for the first two characters,
 * uppercase values for the third character, lowercase letters for the
 * fifth/sixth characters, and the last character X[^A-C]X together counts 
 * as the eighth character regular expression that would allow all characters 
 * but "A", "B", and "C". Dashes outside the regular expression are 
 * non-editable/mask characters.
 */
var InputTextMask = {
	processMaskFocus: function(input, mask, clearWhenInvalid){
		// create an input mask and register it on the specified input (if it hasnt already been added by a previous call
		InputTextMask.createInputMask(input, mask, clearWhenInvalid);
		if(input.value.length == 0){
			// when the input value is empty populate it with the viewing mask and move the cursor to the
			// beginning of the input field
			var cursorPos = InputTextMask.getCursorPosition(input, input.value);
			input.value = input.mask.viewMask;
			InputTextMask.moveCursorToPosition(input, null, cursorPos);
		}
	},
	getEvent: function(e) {
		// get the event either from the window or from the passed event
		return (typeof event != 'undefined')? event: e;
	},
	handleEventBubble: function(keyEvent, keyCode){
		// this method ensures that the key enterned by the user is not propagated unless it is a tab or arrow key
		try {
			if(keyCode && (keyCode.isTab || keyCode.isLeftOrRightArrow)){
				// allow all tab/arrow keys by returning true- no further action required
				return true;
			}
			keyEvent.cancelBubble = true;
			if(keyEvent.stopPropagation){
				// prevent other event triggers
				keyEvent.stopPropagation();
			}
			if(keyEvent.preventDefault){
				// prevent the default event from firing. in this case it is propagation of the keyed input
				keyEvent.preventDefault();
			}
			return false;
		} catch(e) {
			alert(e.message);
		}
	},
	createInputMask: function(input, mask, clearWhenInvalid) {
		// if this input hasnt already registered its mask go ahead and do so now. This only needs to be performed the
		// first time the input is encountered when it gains focus. It will attach the MaskType object to the input object
		// add add all of the appropriate event listeners to ensure that the mask is applied
		if(!input.mask || input.mask.rawMask != mask){
			input.mask = new InputTextMask.MaskType(input, mask, clearWhenInvalid);
			// add the event listeners that will ensure that when the input contains an incomplete mask it will be remove.
			// Also, make sure that the keydown event is fired from this point forward thus invoking the mask format.
			if(input.addEventListener){
				// most doms
				input.addEventListener('blur', function(){input.mask.removeValueWhenInvalid();}, false);
				input.addEventListener('keydown', function(e){return input.mask.processMaskFormatting(e);}, false);
				if(window.opera){
					// in opera- need to ensure that the keypress event isnt interfering with this input mask
					input.addEventListener('keypress', function(e){return InputTextMask.handleEventBubble(InputTextMask.getEvent(e), null);}, false);
				}
			} else if(input.attachEvent) {
				// ie
				input.attachEvent('onblur', function(){input.mask.removeValueWhenInvalid();});
				input.attachEvent('onkeydown', function(e){return input.mask.processMaskFormatting(e);});
			} else {
				// other browsers that do not support dynamic event propagations
				input.onBlur = function(){input.mask.removeValueWhenInvalid();};
				input.onKeyDown = function(e){input.mask.processMaskFormatting(e)};
			}
		}
	},
	getCursorPosition: function(input, previousValue) {
		// gets the current cursor position (s=start, e=end) and creates/returns a new CursorPosition instance
		var s, e, r;
		if(input.createTextRange){
			// ie- need to capture the start/end cursor positions
			r = document.selection.createRange().duplicate();
			r.moveEnd('character', previousValue.length);
			if(r.text === ''){
				s = previousValue.length;
			} else {
				s = previousValue.lastIndexOf(r.text);
			}
			r = document.selection.createRange().duplicate();
			r.moveStart('character', -previousValue.length);
			e = r.text.length;
		} else {
			// other browsers
			s = input.selectionStart;
			e = input.selectionEnd;
		}
		return new InputTextMask.CursorPosition(s, e, r, previousValue);
	},
	moveCursorToPosition: function(input, keyCode, cursorPosition) {
		// moves a cursor position for the passed input element to the specified cursor position- because the 
		// range cursor position is 1 indexed we add an additional space (unless the pressed key is a backspace)
		var p = (!keyCode || (keyCode && keyCode.isBackspace))? cursorPosition.start: cursorPosition.start + 1;
		if(input.createTextRange){
			// ie move- cursor to the index p
			cursorPosition.range.move('character', p);
			cursorPosition.range.select();
		} else {
			// other browser- move cursor to the index p
			input.selectionStart = p;
			input.selectionEnd = p;
		}
	},
	injectValue: function(input, keyCode, cursorPosition) {
		// inject the validated key into the input mask at the specified cursor position and return true on success
		var key = (keyCode.isBackspace)? '_': input.mask.getValidatedKey(keyCode, cursorPosition);
		if(key){
			input.value = cursorPosition.previousValue.substring(0, cursorPosition.start) + key + cursorPosition.previousValue.substring(cursorPosition.start + 1, cursorPosition.previousValue.length);
			return true;
		}
		// invalid key
		return false;
	},
	MaskType: function(inputTextElement, mask, clearWhenInvalid) {
		// this object instance is holds relative mask properties for a specified input element
		this.inputTextElement = inputTextElement;
		// designates whether or not the input value is cleared when its mask is incomplete and a blur event is triggered
		this.clearWhenInvalid = clearWhenInvalid;
		// holds the last validated key code
		this.lastValidatedKeyCode = null;
		// the mask value used to validate/mask valid input
		this.rawMask = mask;
		// the mask displayed in the input
		this.viewMask = '';
		// the string array of all the raw mask values (some indexes contain more than one char so we need to track this) 
		this.maskArray = new Array();
		var mai = 0;
		var regexp = '';
		// cycle through the raw mask and perform view mask conversions
		for(var i=0; i<mask.length; i++){
			if(regexp){
				if(regexp == 'X'){
					// end of current regexp slot
					regexp = '';
				}
				if(mask.charAt(i) == 'X'){
					// current mask array index contains the complete regexp so we need to store it in the array
					this.maskArray[mai] = regexp;
					mai++;
					regexp = null;
				} else {
					// still in the middle of the regexp keep adding the current character to the regexp
					regexp += mask.charAt(i);
				}
			} else if(mask.charAt(i) == 'X'){
				// current slot is a regexp
				regexp += 'X';
				this.viewMask += '_';
			} else if(mask.charAt(i) == '9' || mask.charAt(i) == 'L' || mask.charAt(i) == 'l' || mask.charAt(i) == 'A') {
				// the current mask character is one of the predefined/reserved characters
				this.viewMask += '_';
				this.maskArray[mai] = mask.charAt(i);
				mai++;
			} else {
				// just a regular char
				this.viewMask += mask.charAt(i);
				this.maskArray[mai] = mask.charAt(i);
				mai++;
			}
		}
		// the predefined/reserved characters need to be replaced with the viewing mask char that desigantes an editable value (underscore)
		this.specialChars = this.viewMask.replace(/(L|l|9|A|_|X)/g,'');
		this.getValidatedKey = function(keyCode, cursorPosition) {
			// validates if the passed key code is valid for the specified cursor position and returns the value if it is. otherwise, return false
			var maskKey = this.maskArray[cursorPosition.start];
			if(maskKey == '9'){
				// only allow numbers at the specified slot
				return keyCode.pressedKey.match(/[0-9]/);
			} else if(maskKey == 'L'){
				// only allow uppercase letters at specified slot (convert if necessary)
				return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toUpperCase(): null;
			} else if(maskKey == 'l'){
				// only allow lowercase letters at specified slot (convert if necessary)
				return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toLowerCase(): null;
			} else {
				if(maskKey == 'A'){
					// only allow alpha-numeric values at the specified slot
					return keyCode.pressedKey.match(/[A-Za-z0-9]/);
				} else {
					// only allow values that are verified by the specified regexp at the specified slot
					return (this.maskArray[cursorPosition.start].length > 1)? keyCode.pressedKey.match(new RegExp(maskKey)): null;
				}
			}
		};
		this.removeValueWhenInvalid = function(){
			// removes value from the input element when the mask is incomplete
			if(this.inputTextElement.value.indexOf('_') > -1){
				this.inputTextElement.value = '';
			}
		};
		this.processMaskFormatting = function(e) {
			// capture event (should be the keydown event)
			var onKeyDownEvent = InputTextMask.getEvent(e);
			// create the key code from the event. 
			var keyCode = new InputTextMask.KeyCode(onKeyDownEvent);
			if(InputTextMask.handleEventBubble(onKeyDownEvent, keyCode)){
				// the pressed key is allowed to propagate- no mask injection required
				return true;
			}
			var v = this.inputTextElement.value;
			if(v.length === 0){
				// when the input value is empty populate it with the viewing mask
				this.inputTextElement.value = this.viewMask;
			}
			var cursorPos = InputTextMask.getCursorPosition(this.inputTextElement, v);
			if(cursorPos.end == cursorPos.previousValue.length && !keyCode.isBackspace){
				// input cursor position is at the end of the mask- do not allow any more characters to be keyed
				return false;
			}
			// move the cursor position to the next slot that does not contain a mask character
			while(this.inputTextElement.mask.specialChars.match(RegExp.escape(cursorPos.previousValue.charAt(((keyCode.isBackspace)? cursorPos.start-1: cursorPos.start))))){
				if(keyCode.isBackspace) {
					// backspace needs to move the cursor backwards
					cursorPos.decStart();
				} else {
					// still moving cursor one space to the right
					cursorPos.incStart();
				}
				if(cursorPos.start >= cursorPos.previousValue.length || cursorPos.start < 0){
					// end of the mask- no more keys should be keyed
					return false;
				}
			}
			if(keyCode.isBackspace){
				// need to go back one space to the left
				cursorPos.decStart();
			}
			// inject the key that was pressed into the input value mask
			if(InputTextMask.injectValue(this.inputTextElement, keyCode, cursorPos)){
				// when the injection is sucessful move the cursor to the next slot to the right of the injected key
				InputTextMask.moveCursorToPosition(this.inputTextElement, keyCode, cursorPos);
			}
			// because the pressed key is being injected we always need to return false to prevent duplicate
			// key injection
			return false;
		};
	},
	KeyCode: function(onKeyDownEvent) {
		this.onKeyDownEvent = onKeyDownEvent;
		// get the unicode value from the key event
		this.unicode = onKeyDownEvent.which? onKeyDownEvent.which: (onKeyDownEvent.keyCode? onKeyDownEvent.keyCode: (onKeyDownEvent.charCode? onKeyDownEvent.charCode: 0));
		this.isShiftPressed = onKeyDownEvent.shiftKey == false || onKeyDownEvent.shiftKey == true? onKeyDownEvent.shiftKey: (onKeyDownEvent.modifiers && (onKeyDownEvent.modifiers & 4)); //bitWise AND
		// TODO : need to get cap lock capture for onkeydown event
		//this.isCapLock = ((!this.isShiftPressed && this.unicode >= 65 && this.unicode <= 90) || (this.unicode >= 97 && this.unicode <= 122 && this.isShiftPressed));
		if(this.unicode >= 96 && this.unicode <= 105) {
			this.unicode -= 48; // handle number keypad
		}
		if(this.unicode >= 65 && this.unicode <= 90 && !this.isShiftPressed){
			this.unicode += 32; // handle uppercase
		}
		this.isTab = (this.unicode == 9)? true: false;
		this.isBackspace = (this.unicode == 8)? true: false;
		this.isLeftOrRightArrow = (this.unicode == 37 || this.unicode == 39)? true: false;
		// capture the actual key for the passed key code
		this.pressedKey = String.fromCharCode(this.unicode);
	},
	CursorPosition: function(start, end, range, previousValue) {
		// holds the cursor position values
		this.start = isNaN(start)? 0: start;
		this.end = isNaN(end)? 0: end;
		this.range = range;
		this.previousValue = previousValue;
		this.incStart = function(){
			this.start++;
		};
		this.decStart = function(){
			this.start--;
		};
	}
};
// Add escape prototype feature to RegExp object
// text.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$0');
// text.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g, '\\$1');
if(!RegExp.escape) {
	RegExp.escape = function(text){
		var sp;
		if(!arguments.callee.sRE){
			sp=['/','.','*','+','?','|','(',')','[',']','{','}','\\'];
			arguments.callee.sRE = new RegExp('(\\' + sp.join('|\\') + ')','g');
		}
		return text.replace(arguments.callee.sRE, '\\$1');
	};
}


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Input Text Mask?

Posted by Eelco Hillenius <ee...@gmail.com>.
On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> Okay, sounds good... I assume I will be notified on which approach that will be decided by the committers at some point in the process?

Of course. We'll discuss in public anyway.

Eelco

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


RE: Input Text Mask?

Posted by William Hoover <wh...@nemours.org>.
Okay, sounds good... I assume I will be notified on which approach that will be decided by the committers at some point in the process?

-----Original Message-----
From: Eelco Hillenius [mailto:eelco.hillenius@gmail.com]
Sent: Thursday, October 18, 2007 5:08 PM
To: users@wicket.apache.org
Subject: Re: Input Text Mask?


On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> I created a Jira Issue (https://issues.apache.org/jira/browse/WICKET-1085) with attached source. I placed the issue under extensions as others suggested.

Thanks.

> Would I still have to go through sf.net?

It would either be put in wicket-stuff minis - in which case you can
maintain it directly yourself after you get access to the wicket-stuff
project - or if we want to use it for the date field components, and
all comitters agree, we can put it in extensions.

Eelco

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Input Text Mask?

Posted by Eelco Hillenius <ee...@gmail.com>.
On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> I created a Jira Issue (https://issues.apache.org/jira/browse/WICKET-1085) with attached source. I placed the issue under extensions as others suggested.

Thanks.

> Would I still have to go through sf.net?

It would either be put in wicket-stuff minis - in which case you can
maintain it directly yourself after you get access to the wicket-stuff
project - or if we want to use it for the date field components, and
all comitters agree, we can put it in extensions.

Eelco

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


RE: Input Text Mask?

Posted by William Hoover <wh...@nemours.org>.
I created a Jira Issue (https://issues.apache.org/jira/browse/WICKET-1085) with attached source. I placed the issue under extensions as others suggested. Would I still have to go through sf.net?

-----Original Message-----
From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
Sent: Thursday, October 18, 2007 3:57 PM
To: users@wicket.apache.org
Subject: Re: Input Text Mask?


create a sf.net account and i will give you commit access to wicketstuff repo.

-igor


On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> Sure. How would I go about doing so?
>
> -----Original Message-----
> From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
> Sent: Thursday, October 18, 2007 1:11 PM
> To: users@wicket.apache.org
> Subject: Re: Input Text Mask?
>
>
> would you be interested in making this a subclass of textfield and
> throwing it into wicketstuff-minis project which is in wicket-stuff?
>
> -igor
>
>
> On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> > Is anyone interested in using the mask script (below) to a component in a Wicket extension? The script prevents invalid input in a text field as the user types (similar to the Atlas version: http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx). I didn't see a component in Wicket that would accomplish this out-of-the-box and thought it would be a cool addition to Wicket.
> >
> > For example to force the input to mask a phone number:
> > <input type="text" onfocus="InputTextMask.processMaskFocus(this, "(999)999-9999", true);" />
> >
> > /**
> >  * InputTextMask script used for mask/regexp operations.
> >  * Mask Individual Character Usage:
> >  * 9 - designates only numeric values
> >  * L - designates only uppercase letter values
> >  * l - designates only lowercase letter values
> >  * A - designates only alphanumeric values
> >  * X - denotes that a custom client script regular expression is specified</li>
> >  * All other characters are assumed to be "special" characters used to mask
> >  * the input component
> >  * Example 1:
> >  * (999)999-9999 only numeric values can be entered where the the character
> >  * position value is 9. Parenthesis and dash are non-editable/mask characters.
> >  * Example 2:
> >  * 99L-ll-X[^A-C]X only numeric values for the first two characters,
> >  * uppercase values for the third character, lowercase letters for the
> >  * fifth/sixth characters, and the last character X[^A-C]X together counts
> >  * as the eighth character regular expression that would allow all characters
> >  * but "A", "B", and "C". Dashes outside the regular expression are
> >  * non-editable/mask characters.
> >  */
> > var InputTextMask = {
> >         processMaskFocus: function(input, mask, clearWhenInvalid){
> >                 // create an input mask and register it on the specified input (if it hasnt already been added by a previous call
> >                 InputTextMask.createInputMask(input, mask, clearWhenInvalid);
> >                 if(input.value.length == 0){
> >                         // when the input value is empty populate it with the viewing mask and move the cursor to the
> >                         // beginning of the input field
> >                         var cursorPos = InputTextMask.getCursorPosition(input, input.value);
> >                         input.value = input.mask.viewMask;
> >                         InputTextMask.moveCursorToPosition(input, null, cursorPos);
> >                 }
> >         },
> >         getEvent: function(e) {
> >                 // get the event either from the window or from the passed event
> >                 return (typeof event != 'undefined')? event: e;
> >         },
> >         handleEventBubble: function(keyEvent, keyCode){
> >                 // this method ensures that the key enterned by the user is not propagated unless it is a tab or arrow key
> >                 try {
> >                         if(keyCode && (keyCode.isTab || keyCode.isLeftOrRightArrow)){
> >                                 // allow all tab/arrow keys by returning true- no further action required
> >                                 return true;
> >                         }
> >                         keyEvent.cancelBubble = true;
> >                         if(keyEvent.stopPropagation){
> >                                 // prevent other event triggers
> >                                 keyEvent.stopPropagation();
> >                         }
> >                         if(keyEvent.preventDefault){
> >                                 // prevent the default event from firing. in this case it is propagation of the keyed input
> >                                 keyEvent.preventDefault();
> >                         }
> >                         return false;
> >                 } catch(e) {
> >                         alert(e.message);
> >                 }
> >         },
> >         createInputMask: function(input, mask, clearWhenInvalid) {
> >                 // if this input hasnt already registered its mask go ahead and do so now. This only needs to be performed the
> >                 // first time the input is encountered when it gains focus. It will attach the MaskType object to the input object
> >                 // add add all of the appropriate event listeners to ensure that the mask is applied
> >                 if(!input.mask || input.mask.rawMask != mask){
> >                         input.mask = new InputTextMask.MaskType(input, mask, clearWhenInvalid);
> >                         // add the event listeners that will ensure that when the input contains an incomplete mask it will be remove.
> >                         // Also, make sure that the keydown event is fired from this point forward thus invoking the mask format.
> >                         if(input.addEventListener){
> >                                 // most doms
> >                                 input.addEventListener('blur', function(){input.mask.removeValueWhenInvalid();}, false);
> >                                 input.addEventListener('keydown', function(e){return input.mask.processMaskFormatting(e);}, false);
> >                                 if(window.opera){
> >                                         // in opera- need to ensure that the keypress event isnt interfering with this input mask
> >                                         input.addEventListener('keypress', function(e){return InputTextMask.handleEventBubble(InputTextMask.getEvent(e), null);}, false);
> >                                 }
> >                         } else if(input.attachEvent) {
> >                                 // ie
> >                                 input.attachEvent('onblur', function(){input.mask.removeValueWhenInvalid();});
> >                                 input.attachEvent('onkeydown', function(e){return input.mask.processMaskFormatting(e);});
> >                         } else {
> >                                 // other browsers that do not support dynamic event propagations
> >                                 input.onBlur = function(){input.mask.removeValueWhenInvalid();};
> >                                 input.onKeyDown = function(e){input.mask.processMaskFormatting(e)};
> >                         }
> >                 }
> >         },
> >         getCursorPosition: function(input, previousValue) {
> >                 // gets the current cursor position (s=start, e=end) and creates/returns a new CursorPosition instance
> >                 var s, e, r;
> >                 if(input.createTextRange){
> >                         // ie- need to capture the start/end cursor positions
> >                         r = document.selection.createRange().duplicate();
> >                         r.moveEnd('character', previousValue.length);
> >                         if(r.text === ''){
> >                                 s = previousValue.length;
> >                         } else {
> >                                 s = previousValue.lastIndexOf(r.text);
> >                         }
> >                         r = document.selection.createRange().duplicate();
> >                         r.moveStart('character', -previousValue.length);
> >                         e = r.text.length;
> >                 } else {
> >                         // other browsers
> >                         s = input.selectionStart;
> >                         e = input.selectionEnd;
> >                 }
> >                 return new InputTextMask.CursorPosition(s, e, r, previousValue);
> >         },
> >         moveCursorToPosition: function(input, keyCode, cursorPosition) {
> >                 // moves a cursor position for the passed input element to the specified cursor position- because the
> >                 // range cursor position is 1 indexed we add an additional space (unless the pressed key is a backspace)
> >                 var p = (!keyCode || (keyCode && keyCode.isBackspace))? cursorPosition.start: cursorPosition.start + 1;
> >                 if(input.createTextRange){
> >                         // ie move- cursor to the index p
> >                         cursorPosition.range.move('character', p);
> >                         cursorPosition.range.select();
> >                 } else {
> >                         // other browser- move cursor to the index p
> >                         input.selectionStart = p;
> >                         input.selectionEnd = p;
> >                 }
> >         },
> >         injectValue: function(input, keyCode, cursorPosition) {
> >                 // inject the validated key into the input mask at the specified cursor position and return true on success
> >                 var key = (keyCode.isBackspace)? '_': input.mask.getValidatedKey(keyCode, cursorPosition);
> >                 if(key){
> >                         input.value = cursorPosition.previousValue.substring(0, cursorPosition.start) + key + cursorPosition.previousValue.substring(cursorPosition.start + 1, cursorPosition.previousValue.length);
> >                         return true;
> >                 }
> >                 // invalid key
> >                 return false;
> >         },
> >         MaskType: function(inputTextElement, mask, clearWhenInvalid) {
> >                 // this object instance is holds relative mask properties for a specified input element
> >                 this.inputTextElement = inputTextElement;
> >                 // designates whether or not the input value is cleared when its mask is incomplete and a blur event is triggered
> >                 this.clearWhenInvalid = clearWhenInvalid;
> >                 // holds the last validated key code
> >                 this.lastValidatedKeyCode = null;
> >                 // the mask value used to validate/mask valid input
> >                 this.rawMask = mask;
> >                 // the mask displayed in the input
> >                 this.viewMask = '';
> >                 // the string array of all the raw mask values (some indexes contain more than one char so we need to track this)
> >                 this.maskArray = new Array();
> >                 var mai = 0;
> >                 var regexp = '';
> >                 // cycle through the raw mask and perform view mask conversions
> >                 for(var i=0; i<mask.length; i++){
> >                         if(regexp){
> >                                 if(regexp == 'X'){
> >                                         // end of current regexp slot
> >                                         regexp = '';
> >                                 }
> >                                 if(mask.charAt(i) == 'X'){
> >                                         // current mask array index contains the complete regexp so we need to store it in the array
> >                                         this.maskArray[mai] = regexp;
> >                                         mai++;
> >                                         regexp = null;
> >                                 } else {
> >                                         // still in the middle of the regexp keep adding the current character to the regexp
> >                                         regexp += mask.charAt(i);
> >                                 }
> >                         } else if(mask.charAt(i) == 'X'){
> >                                 // current slot is a regexp
> >                                 regexp += 'X';
> >                                 this.viewMask += '_';
> >                         } else if(mask.charAt(i) == '9' || mask.charAt(i) == 'L' || mask.charAt(i) == 'l' || mask.charAt(i) == 'A') {
> >                                 // the current mask character is one of the predefined/reserved characters
> >                                 this.viewMask += '_';
> >                                 this.maskArray[mai] = mask.charAt(i);
> >                                 mai++;
> >                         } else {
> >                                 // just a regular char
> >                                 this.viewMask += mask.charAt(i);
> >                                 this.maskArray[mai] = mask.charAt(i);
> >                                 mai++;
> >                         }
> >                 }
> >                 // the predefined/reserved characters need to be replaced with the viewing mask char that desigantes an editable value (underscore)
> >                 this.specialChars = this.viewMask.replace(/(L|l|9|A|_|X)/g,'');
> >                 this.getValidatedKey = function(keyCode, cursorPosition) {
> >                         // validates if the passed key code is valid for the specified cursor position and returns the value if it is. otherwise, return false
> >                         var maskKey = this.maskArray[cursorPosition.start];
> >                         if(maskKey == '9'){
> >                                 // only allow numbers at the specified slot
> >                                 return keyCode.pressedKey.match(/[0-9]/);
> >                         } else if(maskKey == 'L'){
> >                                 // only allow uppercase letters at specified slot (convert if necessary)
> >                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toUpperCase(): null;
> >                         } else if(maskKey == 'l'){
> >                                 // only allow lowercase letters at specified slot (convert if necessary)
> >                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toLowerCase(): null;
> >                         } else {
> >                                 if(maskKey == 'A'){
> >                                         // only allow alpha-numeric values at the specified slot
> >                                         return keyCode.pressedKey.match(/[A-Za-z0-9]/);
> >                                 } else {
> >                                         // only allow values that are verified by the specified regexp at the specified slot
> >                                         return (this.maskArray[cursorPosition.start].length > 1)? keyCode.pressedKey.match(new RegExp(maskKey)): null;
> >                                 }
> >                         }
> >                 };
> >                 this.removeValueWhenInvalid = function(){
> >                         // removes value from the input element when the mask is incomplete
> >                         if(this.inputTextElement.value.indexOf('_') > -1){
> >                                 this.inputTextElement.value = '';
> >                         }
> >                 };
> >                 this.processMaskFormatting = function(e) {
> >                         // capture event (should be the keydown event)
> >                         var onKeyDownEvent = InputTextMask.getEvent(e);
> >                         // create the key code from the event.
> >                         var keyCode = new InputTextMask.KeyCode(onKeyDownEvent);
> >                         if(InputTextMask.handleEventBubble(onKeyDownEvent, keyCode)){
> >                                 // the pressed key is allowed to propagate- no mask injection required
> >                                 return true;
> >                         }
> >                         var v = this.inputTextElement.value;
> >                         if(v.length === 0){
> >                                 // when the input value is empty populate it with the viewing mask
> >                                 this.inputTextElement.value = this.viewMask;
> >                         }
> >                         var cursorPos = InputTextMask.getCursorPosition(this.inputTextElement, v);
> >                         if(cursorPos.end == cursorPos.previousValue.length && !keyCode.isBackspace){
> >                                 // input cursor position is at the end of the mask- do not allow any more characters to be keyed
> >                                 return false;
> >                         }
> >                         // move the cursor position to the next slot that does not contain a mask character
> >                         while(this.inputTextElement.mask.specialChars.match(RegExp.escape(cursorPos.previousValue.charAt(((keyCode.isBackspace)? cursorPos.start-1: cursorPos.start))))){
> >                                 if(keyCode.isBackspace) {
> >                                         // backspace needs to move the cursor backwards
> >                                         cursorPos.decStart();
> >                                 } else {
> >                                         // still moving cursor one space to the right
> >                                         cursorPos.incStart();
> >                                 }
> >                                 if(cursorPos.start >= cursorPos.previousValue.length || cursorPos.start < 0){
> >                                         // end of the mask- no more keys should be keyed
> >                                         return false;
> >                                 }
> >                         }
> >                         if(keyCode.isBackspace){
> >                                 // need to go back one space to the left
> >                                 cursorPos.decStart();
> >                         }
> >                         // inject the key that was pressed into the input value mask
> >                         if(InputTextMask.injectValue(this.inputTextElement, keyCode, cursorPos)){
> >                                 // when the injection is sucessful move the cursor to the next slot to the right of the injected key
> >                                 InputTextMask.moveCursorToPosition(this.inputTextElement, keyCode, cursorPos);
> >                         }
> >                         // because the pressed key is being injected we always need to return false to prevent duplicate
> >                         // key injection
> >                         return false;
> >                 };
> >         },
> >         KeyCode: function(onKeyDownEvent) {
> >                 this.onKeyDownEvent = onKeyDownEvent;
> >                 // get the unicode value from the key event
> >                 this.unicode = onKeyDownEvent.which? onKeyDownEvent.which: (onKeyDownEvent.keyCode? onKeyDownEvent.keyCode: (onKeyDownEvent.charCode? onKeyDownEvent.charCode: 0));
> >                 this.isShiftPressed = onKeyDownEvent.shiftKey == false || onKeyDownEvent.shiftKey == true? onKeyDownEvent.shiftKey: (onKeyDownEvent.modifiers && (onKeyDownEvent.modifiers & 4)); //bitWise AND
> >                 // TODO : need to get cap lock capture for onkeydown event
> >                 //this.isCapLock = ((!this.isShiftPressed && this.unicode >= 65 && this.unicode <= 90) || (this.unicode >= 97 && this.unicode <= 122 && this.isShiftPressed));
> >                 if(this.unicode >= 96 && this.unicode <= 105) {
> >                         this.unicode -= 48; // handle number keypad
> >                 }
> >                 if(this.unicode >= 65 && this.unicode <= 90 && !this.isShiftPressed){
> >                         this.unicode += 32; // handle uppercase
> >                 }
> >                 this.isTab = (this.unicode == 9)? true: false;
> >                 this.isBackspace = (this.unicode == 8)? true: false;
> >                 this.isLeftOrRightArrow = (this.unicode == 37 || this.unicode == 39)? true: false;
> >                 // capture the actual key for the passed key code
> >                 this.pressedKey = String.fromCharCode(this.unicode);
> >         },
> >         CursorPosition: function(start, end, range, previousValue) {
> >                 // holds the cursor position values
> >                 this.start = isNaN(start)? 0: start;
> >                 this.end = isNaN(end)? 0: end;
> >                 this.range = range;
> >                 this.previousValue = previousValue;
> >                 this.incStart = function(){
> >                         this.start++;
> >                 };
> >                 this.decStart = function(){
> >                         this.start--;
> >                 };
> >         }
> > };
> > // Add escape prototype feature to RegExp object
> > // text.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$0');
> > // text.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g, '\\$1');
> > if(!RegExp.escape) {
> >         RegExp.escape = function(text){
> >                 var sp;
> >                 if(!arguments.callee.sRE){
> >                         sp=['/','.','*','+','?','|','(',')','[',']','{','}','\\'];
> >                         arguments.callee.sRE = new RegExp('(\\' + sp.join('|\\') + ')','g');
> >                 }
> >                 return text.replace(arguments.callee.sRE, '\\$1');
> >         };
> > }
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Input Text Mask?

Posted by Igor Vaynberg <ig...@gmail.com>.
create a sf.net account and i will give you commit access to wicketstuff repo.

-igor


On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> Sure. How would I go about doing so?
>
> -----Original Message-----
> From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
> Sent: Thursday, October 18, 2007 1:11 PM
> To: users@wicket.apache.org
> Subject: Re: Input Text Mask?
>
>
> would you be interested in making this a subclass of textfield and
> throwing it into wicketstuff-minis project which is in wicket-stuff?
>
> -igor
>
>
> On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> > Is anyone interested in using the mask script (below) to a component in a Wicket extension? The script prevents invalid input in a text field as the user types (similar to the Atlas version: http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx). I didn't see a component in Wicket that would accomplish this out-of-the-box and thought it would be a cool addition to Wicket.
> >
> > For example to force the input to mask a phone number:
> > <input type="text" onfocus="InputTextMask.processMaskFocus(this, "(999)999-9999", true);" />
> >
> > /**
> >  * InputTextMask script used for mask/regexp operations.
> >  * Mask Individual Character Usage:
> >  * 9 - designates only numeric values
> >  * L - designates only uppercase letter values
> >  * l - designates only lowercase letter values
> >  * A - designates only alphanumeric values
> >  * X - denotes that a custom client script regular expression is specified</li>
> >  * All other characters are assumed to be "special" characters used to mask
> >  * the input component
> >  * Example 1:
> >  * (999)999-9999 only numeric values can be entered where the the character
> >  * position value is 9. Parenthesis and dash are non-editable/mask characters.
> >  * Example 2:
> >  * 99L-ll-X[^A-C]X only numeric values for the first two characters,
> >  * uppercase values for the third character, lowercase letters for the
> >  * fifth/sixth characters, and the last character X[^A-C]X together counts
> >  * as the eighth character regular expression that would allow all characters
> >  * but "A", "B", and "C". Dashes outside the regular expression are
> >  * non-editable/mask characters.
> >  */
> > var InputTextMask = {
> >         processMaskFocus: function(input, mask, clearWhenInvalid){
> >                 // create an input mask and register it on the specified input (if it hasnt already been added by a previous call
> >                 InputTextMask.createInputMask(input, mask, clearWhenInvalid);
> >                 if(input.value.length == 0){
> >                         // when the input value is empty populate it with the viewing mask and move the cursor to the
> >                         // beginning of the input field
> >                         var cursorPos = InputTextMask.getCursorPosition(input, input.value);
> >                         input.value = input.mask.viewMask;
> >                         InputTextMask.moveCursorToPosition(input, null, cursorPos);
> >                 }
> >         },
> >         getEvent: function(e) {
> >                 // get the event either from the window or from the passed event
> >                 return (typeof event != 'undefined')? event: e;
> >         },
> >         handleEventBubble: function(keyEvent, keyCode){
> >                 // this method ensures that the key enterned by the user is not propagated unless it is a tab or arrow key
> >                 try {
> >                         if(keyCode && (keyCode.isTab || keyCode.isLeftOrRightArrow)){
> >                                 // allow all tab/arrow keys by returning true- no further action required
> >                                 return true;
> >                         }
> >                         keyEvent.cancelBubble = true;
> >                         if(keyEvent.stopPropagation){
> >                                 // prevent other event triggers
> >                                 keyEvent.stopPropagation();
> >                         }
> >                         if(keyEvent.preventDefault){
> >                                 // prevent the default event from firing. in this case it is propagation of the keyed input
> >                                 keyEvent.preventDefault();
> >                         }
> >                         return false;
> >                 } catch(e) {
> >                         alert(e.message);
> >                 }
> >         },
> >         createInputMask: function(input, mask, clearWhenInvalid) {
> >                 // if this input hasnt already registered its mask go ahead and do so now. This only needs to be performed the
> >                 // first time the input is encountered when it gains focus. It will attach the MaskType object to the input object
> >                 // add add all of the appropriate event listeners to ensure that the mask is applied
> >                 if(!input.mask || input.mask.rawMask != mask){
> >                         input.mask = new InputTextMask.MaskType(input, mask, clearWhenInvalid);
> >                         // add the event listeners that will ensure that when the input contains an incomplete mask it will be remove.
> >                         // Also, make sure that the keydown event is fired from this point forward thus invoking the mask format.
> >                         if(input.addEventListener){
> >                                 // most doms
> >                                 input.addEventListener('blur', function(){input.mask.removeValueWhenInvalid();}, false);
> >                                 input.addEventListener('keydown', function(e){return input.mask.processMaskFormatting(e);}, false);
> >                                 if(window.opera){
> >                                         // in opera- need to ensure that the keypress event isnt interfering with this input mask
> >                                         input.addEventListener('keypress', function(e){return InputTextMask.handleEventBubble(InputTextMask.getEvent(e), null);}, false);
> >                                 }
> >                         } else if(input.attachEvent) {
> >                                 // ie
> >                                 input.attachEvent('onblur', function(){input.mask.removeValueWhenInvalid();});
> >                                 input.attachEvent('onkeydown', function(e){return input.mask.processMaskFormatting(e);});
> >                         } else {
> >                                 // other browsers that do not support dynamic event propagations
> >                                 input.onBlur = function(){input.mask.removeValueWhenInvalid();};
> >                                 input.onKeyDown = function(e){input.mask.processMaskFormatting(e)};
> >                         }
> >                 }
> >         },
> >         getCursorPosition: function(input, previousValue) {
> >                 // gets the current cursor position (s=start, e=end) and creates/returns a new CursorPosition instance
> >                 var s, e, r;
> >                 if(input.createTextRange){
> >                         // ie- need to capture the start/end cursor positions
> >                         r = document.selection.createRange().duplicate();
> >                         r.moveEnd('character', previousValue.length);
> >                         if(r.text === ''){
> >                                 s = previousValue.length;
> >                         } else {
> >                                 s = previousValue.lastIndexOf(r.text);
> >                         }
> >                         r = document.selection.createRange().duplicate();
> >                         r.moveStart('character', -previousValue.length);
> >                         e = r.text.length;
> >                 } else {
> >                         // other browsers
> >                         s = input.selectionStart;
> >                         e = input.selectionEnd;
> >                 }
> >                 return new InputTextMask.CursorPosition(s, e, r, previousValue);
> >         },
> >         moveCursorToPosition: function(input, keyCode, cursorPosition) {
> >                 // moves a cursor position for the passed input element to the specified cursor position- because the
> >                 // range cursor position is 1 indexed we add an additional space (unless the pressed key is a backspace)
> >                 var p = (!keyCode || (keyCode && keyCode.isBackspace))? cursorPosition.start: cursorPosition.start + 1;
> >                 if(input.createTextRange){
> >                         // ie move- cursor to the index p
> >                         cursorPosition.range.move('character', p);
> >                         cursorPosition.range.select();
> >                 } else {
> >                         // other browser- move cursor to the index p
> >                         input.selectionStart = p;
> >                         input.selectionEnd = p;
> >                 }
> >         },
> >         injectValue: function(input, keyCode, cursorPosition) {
> >                 // inject the validated key into the input mask at the specified cursor position and return true on success
> >                 var key = (keyCode.isBackspace)? '_': input.mask.getValidatedKey(keyCode, cursorPosition);
> >                 if(key){
> >                         input.value = cursorPosition.previousValue.substring(0, cursorPosition.start) + key + cursorPosition.previousValue.substring(cursorPosition.start + 1, cursorPosition.previousValue.length);
> >                         return true;
> >                 }
> >                 // invalid key
> >                 return false;
> >         },
> >         MaskType: function(inputTextElement, mask, clearWhenInvalid) {
> >                 // this object instance is holds relative mask properties for a specified input element
> >                 this.inputTextElement = inputTextElement;
> >                 // designates whether or not the input value is cleared when its mask is incomplete and a blur event is triggered
> >                 this.clearWhenInvalid = clearWhenInvalid;
> >                 // holds the last validated key code
> >                 this.lastValidatedKeyCode = null;
> >                 // the mask value used to validate/mask valid input
> >                 this.rawMask = mask;
> >                 // the mask displayed in the input
> >                 this.viewMask = '';
> >                 // the string array of all the raw mask values (some indexes contain more than one char so we need to track this)
> >                 this.maskArray = new Array();
> >                 var mai = 0;
> >                 var regexp = '';
> >                 // cycle through the raw mask and perform view mask conversions
> >                 for(var i=0; i<mask.length; i++){
> >                         if(regexp){
> >                                 if(regexp == 'X'){
> >                                         // end of current regexp slot
> >                                         regexp = '';
> >                                 }
> >                                 if(mask.charAt(i) == 'X'){
> >                                         // current mask array index contains the complete regexp so we need to store it in the array
> >                                         this.maskArray[mai] = regexp;
> >                                         mai++;
> >                                         regexp = null;
> >                                 } else {
> >                                         // still in the middle of the regexp keep adding the current character to the regexp
> >                                         regexp += mask.charAt(i);
> >                                 }
> >                         } else if(mask.charAt(i) == 'X'){
> >                                 // current slot is a regexp
> >                                 regexp += 'X';
> >                                 this.viewMask += '_';
> >                         } else if(mask.charAt(i) == '9' || mask.charAt(i) == 'L' || mask.charAt(i) == 'l' || mask.charAt(i) == 'A') {
> >                                 // the current mask character is one of the predefined/reserved characters
> >                                 this.viewMask += '_';
> >                                 this.maskArray[mai] = mask.charAt(i);
> >                                 mai++;
> >                         } else {
> >                                 // just a regular char
> >                                 this.viewMask += mask.charAt(i);
> >                                 this.maskArray[mai] = mask.charAt(i);
> >                                 mai++;
> >                         }
> >                 }
> >                 // the predefined/reserved characters need to be replaced with the viewing mask char that desigantes an editable value (underscore)
> >                 this.specialChars = this.viewMask.replace(/(L|l|9|A|_|X)/g,'');
> >                 this.getValidatedKey = function(keyCode, cursorPosition) {
> >                         // validates if the passed key code is valid for the specified cursor position and returns the value if it is. otherwise, return false
> >                         var maskKey = this.maskArray[cursorPosition.start];
> >                         if(maskKey == '9'){
> >                                 // only allow numbers at the specified slot
> >                                 return keyCode.pressedKey.match(/[0-9]/);
> >                         } else if(maskKey == 'L'){
> >                                 // only allow uppercase letters at specified slot (convert if necessary)
> >                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toUpperCase(): null;
> >                         } else if(maskKey == 'l'){
> >                                 // only allow lowercase letters at specified slot (convert if necessary)
> >                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toLowerCase(): null;
> >                         } else {
> >                                 if(maskKey == 'A'){
> >                                         // only allow alpha-numeric values at the specified slot
> >                                         return keyCode.pressedKey.match(/[A-Za-z0-9]/);
> >                                 } else {
> >                                         // only allow values that are verified by the specified regexp at the specified slot
> >                                         return (this.maskArray[cursorPosition.start].length > 1)? keyCode.pressedKey.match(new RegExp(maskKey)): null;
> >                                 }
> >                         }
> >                 };
> >                 this.removeValueWhenInvalid = function(){
> >                         // removes value from the input element when the mask is incomplete
> >                         if(this.inputTextElement.value.indexOf('_') > -1){
> >                                 this.inputTextElement.value = '';
> >                         }
> >                 };
> >                 this.processMaskFormatting = function(e) {
> >                         // capture event (should be the keydown event)
> >                         var onKeyDownEvent = InputTextMask.getEvent(e);
> >                         // create the key code from the event.
> >                         var keyCode = new InputTextMask.KeyCode(onKeyDownEvent);
> >                         if(InputTextMask.handleEventBubble(onKeyDownEvent, keyCode)){
> >                                 // the pressed key is allowed to propagate- no mask injection required
> >                                 return true;
> >                         }
> >                         var v = this.inputTextElement.value;
> >                         if(v.length === 0){
> >                                 // when the input value is empty populate it with the viewing mask
> >                                 this.inputTextElement.value = this.viewMask;
> >                         }
> >                         var cursorPos = InputTextMask.getCursorPosition(this.inputTextElement, v);
> >                         if(cursorPos.end == cursorPos.previousValue.length && !keyCode.isBackspace){
> >                                 // input cursor position is at the end of the mask- do not allow any more characters to be keyed
> >                                 return false;
> >                         }
> >                         // move the cursor position to the next slot that does not contain a mask character
> >                         while(this.inputTextElement.mask.specialChars.match(RegExp.escape(cursorPos.previousValue.charAt(((keyCode.isBackspace)? cursorPos.start-1: cursorPos.start))))){
> >                                 if(keyCode.isBackspace) {
> >                                         // backspace needs to move the cursor backwards
> >                                         cursorPos.decStart();
> >                                 } else {
> >                                         // still moving cursor one space to the right
> >                                         cursorPos.incStart();
> >                                 }
> >                                 if(cursorPos.start >= cursorPos.previousValue.length || cursorPos.start < 0){
> >                                         // end of the mask- no more keys should be keyed
> >                                         return false;
> >                                 }
> >                         }
> >                         if(keyCode.isBackspace){
> >                                 // need to go back one space to the left
> >                                 cursorPos.decStart();
> >                         }
> >                         // inject the key that was pressed into the input value mask
> >                         if(InputTextMask.injectValue(this.inputTextElement, keyCode, cursorPos)){
> >                                 // when the injection is sucessful move the cursor to the next slot to the right of the injected key
> >                                 InputTextMask.moveCursorToPosition(this.inputTextElement, keyCode, cursorPos);
> >                         }
> >                         // because the pressed key is being injected we always need to return false to prevent duplicate
> >                         // key injection
> >                         return false;
> >                 };
> >         },
> >         KeyCode: function(onKeyDownEvent) {
> >                 this.onKeyDownEvent = onKeyDownEvent;
> >                 // get the unicode value from the key event
> >                 this.unicode = onKeyDownEvent.which? onKeyDownEvent.which: (onKeyDownEvent.keyCode? onKeyDownEvent.keyCode: (onKeyDownEvent.charCode? onKeyDownEvent.charCode: 0));
> >                 this.isShiftPressed = onKeyDownEvent.shiftKey == false || onKeyDownEvent.shiftKey == true? onKeyDownEvent.shiftKey: (onKeyDownEvent.modifiers && (onKeyDownEvent.modifiers & 4)); //bitWise AND
> >                 // TODO : need to get cap lock capture for onkeydown event
> >                 //this.isCapLock = ((!this.isShiftPressed && this.unicode >= 65 && this.unicode <= 90) || (this.unicode >= 97 && this.unicode <= 122 && this.isShiftPressed));
> >                 if(this.unicode >= 96 && this.unicode <= 105) {
> >                         this.unicode -= 48; // handle number keypad
> >                 }
> >                 if(this.unicode >= 65 && this.unicode <= 90 && !this.isShiftPressed){
> >                         this.unicode += 32; // handle uppercase
> >                 }
> >                 this.isTab = (this.unicode == 9)? true: false;
> >                 this.isBackspace = (this.unicode == 8)? true: false;
> >                 this.isLeftOrRightArrow = (this.unicode == 37 || this.unicode == 39)? true: false;
> >                 // capture the actual key for the passed key code
> >                 this.pressedKey = String.fromCharCode(this.unicode);
> >         },
> >         CursorPosition: function(start, end, range, previousValue) {
> >                 // holds the cursor position values
> >                 this.start = isNaN(start)? 0: start;
> >                 this.end = isNaN(end)? 0: end;
> >                 this.range = range;
> >                 this.previousValue = previousValue;
> >                 this.incStart = function(){
> >                         this.start++;
> >                 };
> >                 this.decStart = function(){
> >                         this.start--;
> >                 };
> >         }
> > };
> > // Add escape prototype feature to RegExp object
> > // text.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$0');
> > // text.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g, '\\$1');
> > if(!RegExp.escape) {
> >         RegExp.escape = function(text){
> >                 var sp;
> >                 if(!arguments.callee.sRE){
> >                         sp=['/','.','*','+','?','|','(',')','[',']','{','}','\\'];
> >                         arguments.callee.sRE = new RegExp('(\\' + sp.join('|\\') + ')','g');
> >                 }
> >                 return text.replace(arguments.callee.sRE, '\\$1');
> >         };
> > }
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


RE: Input Text Mask?

Posted by William Hoover <wh...@nemours.org>.
johan, see https://issues.apache.org/jira/browse/WICKET-1085

-----Original Message-----
From: Johan Compagner [mailto:jcompagner@gmail.com]
Sent: Saturday, October 20, 2007 12:55 PM
To: users@wicket.apache.org
Subject: Re: Input Text Mask?


I think such a thing in extentions would also be nice.

johan


On 10/18/07, Igor Vaynberg <ig...@gmail.com> wrote:
>
> would you be interested in making this a subclass of textfield and
> throwing it into wicketstuff-minis project which is in wicket-stuff?
>
> -igor
>
>
> On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> > Is anyone interested in using the mask script (below) to a component in
> a Wicket extension? The script prevents invalid input in a text field as the
> user types (similar to the Atlas version:
> http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx). I didn't see a
> component in Wicket that would accomplish this out-of-the-box and thought it
> would be a cool addition to Wicket.
> >
> > For example to force the input to mask a phone number:
> > <input type="text" onfocus="InputTextMask.processMaskFocus(this,
> "(999)999-9999", true);" />
> >
> > /**
> >  * InputTextMask script used for mask/regexp operations.
> >  * Mask Individual Character Usage:
> >  * 9 - designates only numeric values
> >  * L - designates only uppercase letter values
> >  * l - designates only lowercase letter values
> >  * A - designates only alphanumeric values
> >  * X - denotes that a custom client script regular expression is
> specified</li>
> >  * All other characters are assumed to be "special" characters used to
> mask
> >  * the input component
> >  * Example 1:
> >  * (999)999-9999 <LiveCall:(999)999-9999> only numeric values can be
> entered where the the character
> >  * position value is 9. Parenthesis and dash are non-editable/mask
> characters.
> >  * Example 2:
> >  * 99L-ll-X[^A-C]X only numeric values for the first two characters,
> >  * uppercase values for the third character, lowercase letters for the
> >  * fifth/sixth characters, and the last character X[^A-C]X together
> counts
> >  * as the eighth character regular expression that would allow all
> characters
> >  * but "A", "B", and "C". Dashes outside the regular expression are
> >  * non-editable/mask characters.
> >  */
> > var InputTextMask = {
> >         processMaskFocus: function(input, mask, clearWhenInvalid){
> >                 // create an input mask and register it on the specified
> input (if it hasnt already been added by a previous call
> >                 InputTextMask.createInputMask(input, mask,
> clearWhenInvalid);
> >                 if(input.value.length == 0){
> >                         // when the input value is empty populate it
> with the viewing mask and move the cursor to the
> >                         // beginning of the input field
> >                         var cursorPos = InputTextMask.getCursorPosition(input,
> input.value);
> >                         input.value = input.mask.viewMask;
> >                         InputTextMask.moveCursorToPosition(input, null,
> cursorPos);
> >                 }
> >         },
> >         getEvent: function(e) {
> >                 // get the event either from the window or from the
> passed event
> >                 return (typeof event != 'undefined')? event: e;
> >         },
> >         handleEventBubble: function(keyEvent, keyCode){
> >                 // this method ensures that the key enterned by the user
> is not propagated unless it is a tab or arrow key
> >                 try {
> >                         if(keyCode && (keyCode.isTab ||
> keyCode.isLeftOrRightArrow)){
> >                                 // allow all tab/arrow keys by returning
> true- no further action required
> >                                 return true;
> >                         }
> >                         keyEvent.cancelBubble = true;
> >                         if(keyEvent.stopPropagation){
> >                                 // prevent other event triggers
> >                                 keyEvent.stopPropagation();
> >                         }
> >                         if(keyEvent.preventDefault){
> >                                 // prevent the default event from
> firing. in this case it is propagation of the keyed input
> >                                 keyEvent.preventDefault();
> >                         }
> >                         return false;
> >                 } catch(e) {
> >                         alert(e.message);
> >                 }
> >         },
> >         createInputMask: function(input, mask, clearWhenInvalid) {
> >                 // if this input hasnt already registered its mask go
> ahead and do so now. This only needs to be performed the
> >                 // first time the input is encountered when it gains
> focus. It will attach the MaskType object to the input object
> >                 // add add all of the appropriate event listeners to
> ensure that the mask is applied
> >                 if(!input.mask || input.mask.rawMask != mask){
> >                         input.mask = new InputTextMask.MaskType(input,
> mask, clearWhenInvalid);
> >                         // add the event listeners that will ensure that
> when the input contains an incomplete mask it will be remove.
> >                         // Also, make sure that the keydown event is
> fired from this point forward thus invoking the mask format.
> >                         if(input.addEventListener){
> >                                 // most doms
> >                                 input.addEventListener('blur',
> function(){input.mask.removeValueWhenInvalid();}, false);
> >                                 input.addEventListener('keydown',
> function(e){return input.mask.processMaskFormatting(e);}, false);
> >                                 if(window.opera){
> >                                         // in opera- need to ensure that
> the keypress event isnt interfering with this input mask
> >                                         input.addEventListener('keypress',
> function(e){return InputTextMask.handleEventBubble(InputTextMask.getEvent(e),
> null);}, false);
> >                                 }
> >                         } else if(input.attachEvent) {
> >                                 // ie
> >                                 input.attachEvent('onblur', function(){
> input.mask.removeValueWhenInvalid();});
> >                                 input.attachEvent('onkeydown',
> function(e){return input.mask.processMaskFormatting(e);});
> >                         } else {
> >                                 // other browsers that do not support
> dynamic event propagations
> >                                 input.onBlur = function(){
> input.mask.removeValueWhenInvalid();};
> >                                 input.onKeyDown = function(e){
> input.mask.processMaskFormatting(e)};
> >                         }
> >                 }
> >         },
> >         getCursorPosition: function(input, previousValue) {
> >                 // gets the current cursor position (s=start, e=end) and
> creates/returns a new CursorPosition instance
> >                 var s, e, r;
> >                 if(input.createTextRange){
> >                         // ie- need to capture the start/end cursor
> positions
> >                         r = document.selection.createRange
> ().duplicate();
> >                         r.moveEnd('character', previousValue.length);
> >                         if(r.text === ''){
> >                                 s = previousValue.length;
> >                         } else {
> >                                 s = previousValue.lastIndexOf(r.text);
> >                         }
> >                         r = document.selection.createRange
> ().duplicate();
> >                         r.moveStart('character', -previousValue.length);
> >                         e = r.text.length;
> >                 } else {
> >                         // other browsers
> >                         s = input.selectionStart;
> >                         e = input.selectionEnd;
> >                 }
> >                 return new InputTextMask.CursorPosition(s, e, r,
> previousValue);
> >         },
> >         moveCursorToPosition: function(input, keyCode, cursorPosition) {
> >                 // moves a cursor position for the passed input element
> to the specified cursor position- because the
> >                 // range cursor position is 1 indexed we add an
> additional space (unless the pressed key is a backspace)
> >                 var p = (!keyCode || (keyCode && keyCode.isBackspace))?
> cursorPosition.start: cursorPosition.start + 1;
> >                 if(input.createTextRange){
> >                         // ie move- cursor to the index p
> >                         cursorPosition.range.move('character', p);
> >                         cursorPosition.range.select();
> >                 } else {
> >                         // other browser- move cursor to the index p
> >                         input.selectionStart = p;
> >                         input.selectionEnd = p;
> >                 }
> >         },
> >         injectValue: function(input, keyCode, cursorPosition) {
> >                 // inject the validated key into the input mask at the
> specified cursor position and return true on success
> >                 var key = (keyCode.isBackspace)? '_':
> input.mask.getValidatedKey(keyCode, cursorPosition);
> >                 if(key){
> >                         input.value =
> cursorPosition.previousValue.substring(0, cursorPosition.start) + key +
> cursorPosition.previousValue.substring(cursorPosition.start + 1,
> cursorPosition.previousValue.length);
> >                         return true;
> >                 }
> >                 // invalid key
> >                 return false;
> >         },
> >         MaskType: function(inputTextElement, mask, clearWhenInvalid) {
> >                 // this object instance is holds relative mask
> properties for a specified input element
> >                 this.inputTextElement = inputTextElement;
> >                 // designates whether or not the input value is cleared
> when its mask is incomplete and a blur event is triggered
> >                 this.clearWhenInvalid = clearWhenInvalid;
> >                 // holds the last validated key code
> >                 this.lastValidatedKeyCode = null;
> >                 // the mask value used to validate/mask valid input
> >                 this.rawMask = mask;
> >                 // the mask displayed in the input
> >                 this.viewMask = '';
> >                 // the string array of all the raw mask values (some
> indexes contain more than one char so we need to track this)
> >                 this.maskArray = new Array();
> >                 var mai = 0;
> >                 var regexp = '';
> >                 // cycle through the raw mask and perform view mask
> conversions
> >                 for(var i=0; i<mask.length; i++){
> >                         if(regexp){
> >                                 if(regexp == 'X'){
> >                                         // end of current regexp slot
> >                                         regexp = '';
> >                                 }
> >                                 if(mask.charAt(i) == 'X'){
> >                                         // current mask array index
> contains the complete regexp so we need to store it in the array
> >                                         this.maskArray[mai] = regexp;
> >                                         mai++;
> >                                         regexp = null;
> >                                 } else {
> >                                         // still in the middle of the
> regexp keep adding the current character to the regexp
> >                                         regexp += mask.charAt(i);
> >                                 }
> >                         } else if(mask.charAt(i) == 'X'){
> >                                 // current slot is a regexp
> >                                 regexp += 'X';
> >                                 this.viewMask += '_';
> >                         } else if(mask.charAt(i) == '9' || mask.charAt(i)
> == 'L' || mask.charAt(i) == 'l' || mask.charAt(i) == 'A') {
> >                                 // the current mask character is one of
> the predefined/reserved characters
> >                                 this.viewMask += '_';
> >                                 this.maskArray[mai] = mask.charAt(i);
> >                                 mai++;
> >                         } else {
> >                                 // just a regular char
> >                                 this.viewMask += mask.charAt(i);
> >                                 this.maskArray[mai] = mask.charAt(i);
> >                                 mai++;
> >                         }
> >                 }
> >                 // the predefined/reserved characters need to be
> replaced with the viewing mask char that desigantes an editable value
> (underscore)
> >                 this.specialChars = this.viewMask.replace
> (/(L|l|9|A|_|X)/g,'');
> >                 this.getValidatedKey = function(keyCode, cursorPosition)
> {
> >                         // validates if the passed key code is valid for
> the specified cursor position and returns the value if it is. otherwise,
> return false
> >                         var maskKey = this.maskArray[
> cursorPosition.start];
> >                         if(maskKey == '9'){
> >                                 // only allow numbers at the specified
> slot
> >                                 return keyCode.pressedKey.match
> (/[0-9]/);
> >                         } else if(maskKey == 'L'){
> >                                 // only allow uppercase letters at
> specified slot (convert if necessary)
> >                                 return (keyCode.pressedKey.match(/[A-Za-z]/))?
> keyCode.pressedKey.toUpperCase(): null;
> >                         } else if(maskKey == 'l'){
> >                                 // only allow lowercase letters at
> specified slot (convert if necessary)
> >                                 return (keyCode.pressedKey.match(/[A-Za-z]/))?
> keyCode.pressedKey.toLowerCase(): null;
> >                         } else {
> >                                 if(maskKey == 'A'){
> >                                         // only allow alpha-numeric
> values at the specified slot
> >                                         return keyCode.pressedKey.match
> (/[A-Za-z0-9]/);
> >                                 } else {
> >                                         // only allow values that are
> verified by the specified regexp at the specified slot
> >                                         return (this.maskArray[
> cursorPosition.start].length > 1)? keyCode.pressedKey.match(new
> RegExp(maskKey)): null;
> >                                 }
> >                         }
> >                 };
> >                 this.removeValueWhenInvalid = function(){
> >                         // removes value from the input element when the
> mask is incomplete
> >                         if(this.inputTextElement.value.indexOf('_') >
> -1){
> >                                 this.inputTextElement.value = '';
> >                         }
> >                 };
> >                 this.processMaskFormatting = function(e) {
> >                         // capture event (should be the keydown event)
> >                         var onKeyDownEvent = InputTextMask.getEvent(e);
> >                         // create the key code from the event.
> >                         var keyCode = new InputTextMask.KeyCode
> (onKeyDownEvent);
> >                         if(InputTextMask.handleEventBubble(onKeyDownEvent,
> keyCode)){
> >                                 // the pressed key is allowed to
> propagate- no mask injection required
> >                                 return true;
> >                         }
> >                         var v = this.inputTextElement.value;
> >                         if(v.length === 0){
> >                                 // when the input value is empty
> populate it with the viewing mask
> >                                 this.inputTextElement.value =
> this.viewMask;
> >                         }
> >                         var cursorPos = InputTextMask.getCursorPosition(
> this.inputTextElement, v);
> >                         if(cursorPos.end ==
> cursorPos.previousValue.length && !keyCode.isBackspace){
> >                                 // input cursor position is at the end
> of the mask- do not allow any more characters to be keyed
> >                                 return false;
> >                         }
> >                         // move the cursor position to the next slot
> that does not contain a mask character
> >                         while(
> this.inputTextElement.mask.specialChars.match(RegExp.escape(
> cursorPos.previousValue.charAt(((keyCode.isBackspace)? cursorPos.start-1:
> cursorPos.start))))){
> >                                 if(keyCode.isBackspace) {
> >                                         // backspace needs to move the
> cursor backwards
> >                                         cursorPos.decStart();
> >                                 } else {
> >                                         // still moving cursor one space
> to the right
> >                                         cursorPos.incStart();
> >                                 }
> >                                 if(cursorPos.start >=
> cursorPos.previousValue.length || cursorPos.start < 0){
> >                                         // end of the mask- no more keys
> should be keyed
> >                                         return false;
> >                                 }
> >                         }
> >                         if(keyCode.isBackspace){
> >                                 // need to go back one space to the left
> >                                 cursorPos.decStart();
> >                         }
> >                         // inject the key that was pressed into the
> input value mask
> >                         if(InputTextMask.injectValue(
> this.inputTextElement, keyCode, cursorPos)){
> >                                 // when the injection is sucessful move
> the cursor to the next slot to the right of the injected key
> >                                 InputTextMask.moveCursorToPosition(
> this.inputTextElement, keyCode, cursorPos);
> >                         }
> >                         // because the pressed key is being injected we
> always need to return false to prevent duplicate
> >                         // key injection
> >                         return false;
> >                 };
> >         },
> >         KeyCode: function(onKeyDownEvent) {
> >                 this.onKeyDownEvent = onKeyDownEvent;
> >                 // get the unicode value from the key event
> >                 this.unicode = onKeyDownEvent.which?
> onKeyDownEvent.which: (onKeyDownEvent.keyCode? onKeyDownEvent.keyCode: (
> onKeyDownEvent.charCode? onKeyDownEvent.charCode: 0));
> >                 this.isShiftPressed = onKeyDownEvent.shiftKey == false
> || onKeyDownEvent.shiftKey == true? onKeyDownEvent.shiftKey: (
> onKeyDownEvent.modifiers && (onKeyDownEvent.modifiers & 4)); //bitWise AND
> >                 // TODO : need to get cap lock capture for onkeydown
> event
> >                 //this.isCapLock = ((!this.isShiftPressed &&
> this.unicode >= 65 && this.unicode <= 90) || (this.unicode >= 97 &&
> this.unicode <= 122 && this.isShiftPressed));
> >                 if(this.unicode >= 96 && this.unicode <= 105) {
> >                         this.unicode -= 48; // handle number keypad
> >                 }
> >                 if(this.unicode >= 65 && this.unicode <= 90 &&
> !this.isShiftPressed){
> >                         this.unicode += 32; // handle uppercase
> >                 }
> >                 this.isTab = (this.unicode == 9)? true: false;
> >                 this.isBackspace = (this.unicode == 8)? true: false;
> >                 this.isLeftOrRightArrow = (this.unicode == 37 ||
> this.unicode == 39)? true: false;
> >                 // capture the actual key for the passed key code
> >                 this.pressedKey = String.fromCharCode(this.unicode);
> >         },
> >         CursorPosition: function(start, end, range, previousValue) {
> >                 // holds the cursor position values
> >                 this.start = isNaN(start)? 0: start;
> >                 this.end = isNaN(end)? 0: end;
> >                 this.range = range;
> >                 this.previousValue = previousValue;
> >                 this.incStart = function(){
> >                         this.start++;
> >                 };
> >                 this.decStart = function(){
> >                         this.start--;
> >                 };
> >         }
> > };
> > // Add escape prototype feature to RegExp object
> > // text.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$0');
> > // text.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g, '\\$1');
> > if(!RegExp.escape) {
> >         RegExp.escape = function(text){
> >                 var sp;
> >                 if(!arguments.callee.sRE){
> >
> sp=['/','.','*','+','?','|','(',')','[',']','{','}','\\'];
> >                         arguments.callee.sRE = new RegExp('(\\' +
> sp.join('|\\') + ')','g');
> >                 }
> >                 return text.replace(arguments.callee.sRE, '\\$1');
> >         };
> > }
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Input Text Mask?

Posted by Johan Compagner <jc...@gmail.com>.
I think such a thing in extentions would also be nice.

johan


On 10/18/07, Igor Vaynberg <ig...@gmail.com> wrote:
>
> would you be interested in making this a subclass of textfield and
> throwing it into wicketstuff-minis project which is in wicket-stuff?
>
> -igor
>
>
> On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> > Is anyone interested in using the mask script (below) to a component in
> a Wicket extension? The script prevents invalid input in a text field as the
> user types (similar to the Atlas version:
> http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx). I didn't see a
> component in Wicket that would accomplish this out-of-the-box and thought it
> would be a cool addition to Wicket.
> >
> > For example to force the input to mask a phone number:
> > <input type="text" onfocus="InputTextMask.processMaskFocus(this,
> "(999)999-9999", true);" />
> >
> > /**
> >  * InputTextMask script used for mask/regexp operations.
> >  * Mask Individual Character Usage:
> >  * 9 - designates only numeric values
> >  * L - designates only uppercase letter values
> >  * l - designates only lowercase letter values
> >  * A - designates only alphanumeric values
> >  * X - denotes that a custom client script regular expression is
> specified</li>
> >  * All other characters are assumed to be "special" characters used to
> mask
> >  * the input component
> >  * Example 1:
> >  * (999)999-9999 <LiveCall:(999)999-9999> only numeric values can be
> entered where the the character
> >  * position value is 9. Parenthesis and dash are non-editable/mask
> characters.
> >  * Example 2:
> >  * 99L-ll-X[^A-C]X only numeric values for the first two characters,
> >  * uppercase values for the third character, lowercase letters for the
> >  * fifth/sixth characters, and the last character X[^A-C]X together
> counts
> >  * as the eighth character regular expression that would allow all
> characters
> >  * but "A", "B", and "C". Dashes outside the regular expression are
> >  * non-editable/mask characters.
> >  */
> > var InputTextMask = {
> >         processMaskFocus: function(input, mask, clearWhenInvalid){
> >                 // create an input mask and register it on the specified
> input (if it hasnt already been added by a previous call
> >                 InputTextMask.createInputMask(input, mask,
> clearWhenInvalid);
> >                 if(input.value.length == 0){
> >                         // when the input value is empty populate it
> with the viewing mask and move the cursor to the
> >                         // beginning of the input field
> >                         var cursorPos = InputTextMask.getCursorPosition(input,
> input.value);
> >                         input.value = input.mask.viewMask;
> >                         InputTextMask.moveCursorToPosition(input, null,
> cursorPos);
> >                 }
> >         },
> >         getEvent: function(e) {
> >                 // get the event either from the window or from the
> passed event
> >                 return (typeof event != 'undefined')? event: e;
> >         },
> >         handleEventBubble: function(keyEvent, keyCode){
> >                 // this method ensures that the key enterned by the user
> is not propagated unless it is a tab or arrow key
> >                 try {
> >                         if(keyCode && (keyCode.isTab ||
> keyCode.isLeftOrRightArrow)){
> >                                 // allow all tab/arrow keys by returning
> true- no further action required
> >                                 return true;
> >                         }
> >                         keyEvent.cancelBubble = true;
> >                         if(keyEvent.stopPropagation){
> >                                 // prevent other event triggers
> >                                 keyEvent.stopPropagation();
> >                         }
> >                         if(keyEvent.preventDefault){
> >                                 // prevent the default event from
> firing. in this case it is propagation of the keyed input
> >                                 keyEvent.preventDefault();
> >                         }
> >                         return false;
> >                 } catch(e) {
> >                         alert(e.message);
> >                 }
> >         },
> >         createInputMask: function(input, mask, clearWhenInvalid) {
> >                 // if this input hasnt already registered its mask go
> ahead and do so now. This only needs to be performed the
> >                 // first time the input is encountered when it gains
> focus. It will attach the MaskType object to the input object
> >                 // add add all of the appropriate event listeners to
> ensure that the mask is applied
> >                 if(!input.mask || input.mask.rawMask != mask){
> >                         input.mask = new InputTextMask.MaskType(input,
> mask, clearWhenInvalid);
> >                         // add the event listeners that will ensure that
> when the input contains an incomplete mask it will be remove.
> >                         // Also, make sure that the keydown event is
> fired from this point forward thus invoking the mask format.
> >                         if(input.addEventListener){
> >                                 // most doms
> >                                 input.addEventListener('blur',
> function(){input.mask.removeValueWhenInvalid();}, false);
> >                                 input.addEventListener('keydown',
> function(e){return input.mask.processMaskFormatting(e);}, false);
> >                                 if(window.opera){
> >                                         // in opera- need to ensure that
> the keypress event isnt interfering with this input mask
> >                                         input.addEventListener('keypress',
> function(e){return InputTextMask.handleEventBubble(InputTextMask.getEvent(e),
> null);}, false);
> >                                 }
> >                         } else if(input.attachEvent) {
> >                                 // ie
> >                                 input.attachEvent('onblur', function(){
> input.mask.removeValueWhenInvalid();});
> >                                 input.attachEvent('onkeydown',
> function(e){return input.mask.processMaskFormatting(e);});
> >                         } else {
> >                                 // other browsers that do not support
> dynamic event propagations
> >                                 input.onBlur = function(){
> input.mask.removeValueWhenInvalid();};
> >                                 input.onKeyDown = function(e){
> input.mask.processMaskFormatting(e)};
> >                         }
> >                 }
> >         },
> >         getCursorPosition: function(input, previousValue) {
> >                 // gets the current cursor position (s=start, e=end) and
> creates/returns a new CursorPosition instance
> >                 var s, e, r;
> >                 if(input.createTextRange){
> >                         // ie- need to capture the start/end cursor
> positions
> >                         r = document.selection.createRange
> ().duplicate();
> >                         r.moveEnd('character', previousValue.length);
> >                         if(r.text === ''){
> >                                 s = previousValue.length;
> >                         } else {
> >                                 s = previousValue.lastIndexOf(r.text);
> >                         }
> >                         r = document.selection.createRange
> ().duplicate();
> >                         r.moveStart('character', -previousValue.length);
> >                         e = r.text.length;
> >                 } else {
> >                         // other browsers
> >                         s = input.selectionStart;
> >                         e = input.selectionEnd;
> >                 }
> >                 return new InputTextMask.CursorPosition(s, e, r,
> previousValue);
> >         },
> >         moveCursorToPosition: function(input, keyCode, cursorPosition) {
> >                 // moves a cursor position for the passed input element
> to the specified cursor position- because the
> >                 // range cursor position is 1 indexed we add an
> additional space (unless the pressed key is a backspace)
> >                 var p = (!keyCode || (keyCode && keyCode.isBackspace))?
> cursorPosition.start: cursorPosition.start + 1;
> >                 if(input.createTextRange){
> >                         // ie move- cursor to the index p
> >                         cursorPosition.range.move('character', p);
> >                         cursorPosition.range.select();
> >                 } else {
> >                         // other browser- move cursor to the index p
> >                         input.selectionStart = p;
> >                         input.selectionEnd = p;
> >                 }
> >         },
> >         injectValue: function(input, keyCode, cursorPosition) {
> >                 // inject the validated key into the input mask at the
> specified cursor position and return true on success
> >                 var key = (keyCode.isBackspace)? '_':
> input.mask.getValidatedKey(keyCode, cursorPosition);
> >                 if(key){
> >                         input.value =
> cursorPosition.previousValue.substring(0, cursorPosition.start) + key +
> cursorPosition.previousValue.substring(cursorPosition.start + 1,
> cursorPosition.previousValue.length);
> >                         return true;
> >                 }
> >                 // invalid key
> >                 return false;
> >         },
> >         MaskType: function(inputTextElement, mask, clearWhenInvalid) {
> >                 // this object instance is holds relative mask
> properties for a specified input element
> >                 this.inputTextElement = inputTextElement;
> >                 // designates whether or not the input value is cleared
> when its mask is incomplete and a blur event is triggered
> >                 this.clearWhenInvalid = clearWhenInvalid;
> >                 // holds the last validated key code
> >                 this.lastValidatedKeyCode = null;
> >                 // the mask value used to validate/mask valid input
> >                 this.rawMask = mask;
> >                 // the mask displayed in the input
> >                 this.viewMask = '';
> >                 // the string array of all the raw mask values (some
> indexes contain more than one char so we need to track this)
> >                 this.maskArray = new Array();
> >                 var mai = 0;
> >                 var regexp = '';
> >                 // cycle through the raw mask and perform view mask
> conversions
> >                 for(var i=0; i<mask.length; i++){
> >                         if(regexp){
> >                                 if(regexp == 'X'){
> >                                         // end of current regexp slot
> >                                         regexp = '';
> >                                 }
> >                                 if(mask.charAt(i) == 'X'){
> >                                         // current mask array index
> contains the complete regexp so we need to store it in the array
> >                                         this.maskArray[mai] = regexp;
> >                                         mai++;
> >                                         regexp = null;
> >                                 } else {
> >                                         // still in the middle of the
> regexp keep adding the current character to the regexp
> >                                         regexp += mask.charAt(i);
> >                                 }
> >                         } else if(mask.charAt(i) == 'X'){
> >                                 // current slot is a regexp
> >                                 regexp += 'X';
> >                                 this.viewMask += '_';
> >                         } else if(mask.charAt(i) == '9' || mask.charAt(i)
> == 'L' || mask.charAt(i) == 'l' || mask.charAt(i) == 'A') {
> >                                 // the current mask character is one of
> the predefined/reserved characters
> >                                 this.viewMask += '_';
> >                                 this.maskArray[mai] = mask.charAt(i);
> >                                 mai++;
> >                         } else {
> >                                 // just a regular char
> >                                 this.viewMask += mask.charAt(i);
> >                                 this.maskArray[mai] = mask.charAt(i);
> >                                 mai++;
> >                         }
> >                 }
> >                 // the predefined/reserved characters need to be
> replaced with the viewing mask char that desigantes an editable value
> (underscore)
> >                 this.specialChars = this.viewMask.replace
> (/(L|l|9|A|_|X)/g,'');
> >                 this.getValidatedKey = function(keyCode, cursorPosition)
> {
> >                         // validates if the passed key code is valid for
> the specified cursor position and returns the value if it is. otherwise,
> return false
> >                         var maskKey = this.maskArray[
> cursorPosition.start];
> >                         if(maskKey == '9'){
> >                                 // only allow numbers at the specified
> slot
> >                                 return keyCode.pressedKey.match
> (/[0-9]/);
> >                         } else if(maskKey == 'L'){
> >                                 // only allow uppercase letters at
> specified slot (convert if necessary)
> >                                 return (keyCode.pressedKey.match(/[A-Za-z]/))?
> keyCode.pressedKey.toUpperCase(): null;
> >                         } else if(maskKey == 'l'){
> >                                 // only allow lowercase letters at
> specified slot (convert if necessary)
> >                                 return (keyCode.pressedKey.match(/[A-Za-z]/))?
> keyCode.pressedKey.toLowerCase(): null;
> >                         } else {
> >                                 if(maskKey == 'A'){
> >                                         // only allow alpha-numeric
> values at the specified slot
> >                                         return keyCode.pressedKey.match
> (/[A-Za-z0-9]/);
> >                                 } else {
> >                                         // only allow values that are
> verified by the specified regexp at the specified slot
> >                                         return (this.maskArray[
> cursorPosition.start].length > 1)? keyCode.pressedKey.match(new
> RegExp(maskKey)): null;
> >                                 }
> >                         }
> >                 };
> >                 this.removeValueWhenInvalid = function(){
> >                         // removes value from the input element when the
> mask is incomplete
> >                         if(this.inputTextElement.value.indexOf('_') >
> -1){
> >                                 this.inputTextElement.value = '';
> >                         }
> >                 };
> >                 this.processMaskFormatting = function(e) {
> >                         // capture event (should be the keydown event)
> >                         var onKeyDownEvent = InputTextMask.getEvent(e);
> >                         // create the key code from the event.
> >                         var keyCode = new InputTextMask.KeyCode
> (onKeyDownEvent);
> >                         if(InputTextMask.handleEventBubble(onKeyDownEvent,
> keyCode)){
> >                                 // the pressed key is allowed to
> propagate- no mask injection required
> >                                 return true;
> >                         }
> >                         var v = this.inputTextElement.value;
> >                         if(v.length === 0){
> >                                 // when the input value is empty
> populate it with the viewing mask
> >                                 this.inputTextElement.value =
> this.viewMask;
> >                         }
> >                         var cursorPos = InputTextMask.getCursorPosition(
> this.inputTextElement, v);
> >                         if(cursorPos.end ==
> cursorPos.previousValue.length && !keyCode.isBackspace){
> >                                 // input cursor position is at the end
> of the mask- do not allow any more characters to be keyed
> >                                 return false;
> >                         }
> >                         // move the cursor position to the next slot
> that does not contain a mask character
> >                         while(
> this.inputTextElement.mask.specialChars.match(RegExp.escape(
> cursorPos.previousValue.charAt(((keyCode.isBackspace)? cursorPos.start-1:
> cursorPos.start))))){
> >                                 if(keyCode.isBackspace) {
> >                                         // backspace needs to move the
> cursor backwards
> >                                         cursorPos.decStart();
> >                                 } else {
> >                                         // still moving cursor one space
> to the right
> >                                         cursorPos.incStart();
> >                                 }
> >                                 if(cursorPos.start >=
> cursorPos.previousValue.length || cursorPos.start < 0){
> >                                         // end of the mask- no more keys
> should be keyed
> >                                         return false;
> >                                 }
> >                         }
> >                         if(keyCode.isBackspace){
> >                                 // need to go back one space to the left
> >                                 cursorPos.decStart();
> >                         }
> >                         // inject the key that was pressed into the
> input value mask
> >                         if(InputTextMask.injectValue(
> this.inputTextElement, keyCode, cursorPos)){
> >                                 // when the injection is sucessful move
> the cursor to the next slot to the right of the injected key
> >                                 InputTextMask.moveCursorToPosition(
> this.inputTextElement, keyCode, cursorPos);
> >                         }
> >                         // because the pressed key is being injected we
> always need to return false to prevent duplicate
> >                         // key injection
> >                         return false;
> >                 };
> >         },
> >         KeyCode: function(onKeyDownEvent) {
> >                 this.onKeyDownEvent = onKeyDownEvent;
> >                 // get the unicode value from the key event
> >                 this.unicode = onKeyDownEvent.which?
> onKeyDownEvent.which: (onKeyDownEvent.keyCode? onKeyDownEvent.keyCode: (
> onKeyDownEvent.charCode? onKeyDownEvent.charCode: 0));
> >                 this.isShiftPressed = onKeyDownEvent.shiftKey == false
> || onKeyDownEvent.shiftKey == true? onKeyDownEvent.shiftKey: (
> onKeyDownEvent.modifiers && (onKeyDownEvent.modifiers & 4)); //bitWise AND
> >                 // TODO : need to get cap lock capture for onkeydown
> event
> >                 //this.isCapLock = ((!this.isShiftPressed &&
> this.unicode >= 65 && this.unicode <= 90) || (this.unicode >= 97 &&
> this.unicode <= 122 && this.isShiftPressed));
> >                 if(this.unicode >= 96 && this.unicode <= 105) {
> >                         this.unicode -= 48; // handle number keypad
> >                 }
> >                 if(this.unicode >= 65 && this.unicode <= 90 &&
> !this.isShiftPressed){
> >                         this.unicode += 32; // handle uppercase
> >                 }
> >                 this.isTab = (this.unicode == 9)? true: false;
> >                 this.isBackspace = (this.unicode == 8)? true: false;
> >                 this.isLeftOrRightArrow = (this.unicode == 37 ||
> this.unicode == 39)? true: false;
> >                 // capture the actual key for the passed key code
> >                 this.pressedKey = String.fromCharCode(this.unicode);
> >         },
> >         CursorPosition: function(start, end, range, previousValue) {
> >                 // holds the cursor position values
> >                 this.start = isNaN(start)? 0: start;
> >                 this.end = isNaN(end)? 0: end;
> >                 this.range = range;
> >                 this.previousValue = previousValue;
> >                 this.incStart = function(){
> >                         this.start++;
> >                 };
> >                 this.decStart = function(){
> >                         this.start--;
> >                 };
> >         }
> > };
> > // Add escape prototype feature to RegExp object
> > // text.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$0');
> > // text.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g, '\\$1');
> > if(!RegExp.escape) {
> >         RegExp.escape = function(text){
> >                 var sp;
> >                 if(!arguments.callee.sRE){
> >
> sp=['/','.','*','+','?','|','(',')','[',']','{','}','\\'];
> >                         arguments.callee.sRE = new RegExp('(\\' +
> sp.join('|\\') + ')','g');
> >                 }
> >                 return text.replace(arguments.callee.sRE, '\\$1');
> >         };
> > }
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

RE: Input Text Mask?

Posted by William Hoover <wh...@nemours.org>.
Sure. How would I go about doing so?

-----Original Message-----
From: Igor Vaynberg [mailto:igor.vaynberg@gmail.com]
Sent: Thursday, October 18, 2007 1:11 PM
To: users@wicket.apache.org
Subject: Re: Input Text Mask?


would you be interested in making this a subclass of textfield and
throwing it into wicketstuff-minis project which is in wicket-stuff?

-igor


On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> Is anyone interested in using the mask script (below) to a component in a Wicket extension? The script prevents invalid input in a text field as the user types (similar to the Atlas version: http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx). I didn't see a component in Wicket that would accomplish this out-of-the-box and thought it would be a cool addition to Wicket.
>
> For example to force the input to mask a phone number:
> <input type="text" onfocus="InputTextMask.processMaskFocus(this, "(999)999-9999", true);" />
>
> /**
>  * InputTextMask script used for mask/regexp operations.
>  * Mask Individual Character Usage:
>  * 9 - designates only numeric values
>  * L - designates only uppercase letter values
>  * l - designates only lowercase letter values
>  * A - designates only alphanumeric values
>  * X - denotes that a custom client script regular expression is specified</li>
>  * All other characters are assumed to be "special" characters used to mask
>  * the input component
>  * Example 1:
>  * (999)999-9999 only numeric values can be entered where the the character
>  * position value is 9. Parenthesis and dash are non-editable/mask characters.
>  * Example 2:
>  * 99L-ll-X[^A-C]X only numeric values for the first two characters,
>  * uppercase values for the third character, lowercase letters for the
>  * fifth/sixth characters, and the last character X[^A-C]X together counts
>  * as the eighth character regular expression that would allow all characters
>  * but "A", "B", and "C". Dashes outside the regular expression are
>  * non-editable/mask characters.
>  */
> var InputTextMask = {
>         processMaskFocus: function(input, mask, clearWhenInvalid){
>                 // create an input mask and register it on the specified input (if it hasnt already been added by a previous call
>                 InputTextMask.createInputMask(input, mask, clearWhenInvalid);
>                 if(input.value.length == 0){
>                         // when the input value is empty populate it with the viewing mask and move the cursor to the
>                         // beginning of the input field
>                         var cursorPos = InputTextMask.getCursorPosition(input, input.value);
>                         input.value = input.mask.viewMask;
>                         InputTextMask.moveCursorToPosition(input, null, cursorPos);
>                 }
>         },
>         getEvent: function(e) {
>                 // get the event either from the window or from the passed event
>                 return (typeof event != 'undefined')? event: e;
>         },
>         handleEventBubble: function(keyEvent, keyCode){
>                 // this method ensures that the key enterned by the user is not propagated unless it is a tab or arrow key
>                 try {
>                         if(keyCode && (keyCode.isTab || keyCode.isLeftOrRightArrow)){
>                                 // allow all tab/arrow keys by returning true- no further action required
>                                 return true;
>                         }
>                         keyEvent.cancelBubble = true;
>                         if(keyEvent.stopPropagation){
>                                 // prevent other event triggers
>                                 keyEvent.stopPropagation();
>                         }
>                         if(keyEvent.preventDefault){
>                                 // prevent the default event from firing. in this case it is propagation of the keyed input
>                                 keyEvent.preventDefault();
>                         }
>                         return false;
>                 } catch(e) {
>                         alert(e.message);
>                 }
>         },
>         createInputMask: function(input, mask, clearWhenInvalid) {
>                 // if this input hasnt already registered its mask go ahead and do so now. This only needs to be performed the
>                 // first time the input is encountered when it gains focus. It will attach the MaskType object to the input object
>                 // add add all of the appropriate event listeners to ensure that the mask is applied
>                 if(!input.mask || input.mask.rawMask != mask){
>                         input.mask = new InputTextMask.MaskType(input, mask, clearWhenInvalid);
>                         // add the event listeners that will ensure that when the input contains an incomplete mask it will be remove.
>                         // Also, make sure that the keydown event is fired from this point forward thus invoking the mask format.
>                         if(input.addEventListener){
>                                 // most doms
>                                 input.addEventListener('blur', function(){input.mask.removeValueWhenInvalid();}, false);
>                                 input.addEventListener('keydown', function(e){return input.mask.processMaskFormatting(e);}, false);
>                                 if(window.opera){
>                                         // in opera- need to ensure that the keypress event isnt interfering with this input mask
>                                         input.addEventListener('keypress', function(e){return InputTextMask.handleEventBubble(InputTextMask.getEvent(e), null);}, false);
>                                 }
>                         } else if(input.attachEvent) {
>                                 // ie
>                                 input.attachEvent('onblur', function(){input.mask.removeValueWhenInvalid();});
>                                 input.attachEvent('onkeydown', function(e){return input.mask.processMaskFormatting(e);});
>                         } else {
>                                 // other browsers that do not support dynamic event propagations
>                                 input.onBlur = function(){input.mask.removeValueWhenInvalid();};
>                                 input.onKeyDown = function(e){input.mask.processMaskFormatting(e)};
>                         }
>                 }
>         },
>         getCursorPosition: function(input, previousValue) {
>                 // gets the current cursor position (s=start, e=end) and creates/returns a new CursorPosition instance
>                 var s, e, r;
>                 if(input.createTextRange){
>                         // ie- need to capture the start/end cursor positions
>                         r = document.selection.createRange().duplicate();
>                         r.moveEnd('character', previousValue.length);
>                         if(r.text === ''){
>                                 s = previousValue.length;
>                         } else {
>                                 s = previousValue.lastIndexOf(r.text);
>                         }
>                         r = document.selection.createRange().duplicate();
>                         r.moveStart('character', -previousValue.length);
>                         e = r.text.length;
>                 } else {
>                         // other browsers
>                         s = input.selectionStart;
>                         e = input.selectionEnd;
>                 }
>                 return new InputTextMask.CursorPosition(s, e, r, previousValue);
>         },
>         moveCursorToPosition: function(input, keyCode, cursorPosition) {
>                 // moves a cursor position for the passed input element to the specified cursor position- because the
>                 // range cursor position is 1 indexed we add an additional space (unless the pressed key is a backspace)
>                 var p = (!keyCode || (keyCode && keyCode.isBackspace))? cursorPosition.start: cursorPosition.start + 1;
>                 if(input.createTextRange){
>                         // ie move- cursor to the index p
>                         cursorPosition.range.move('character', p);
>                         cursorPosition.range.select();
>                 } else {
>                         // other browser- move cursor to the index p
>                         input.selectionStart = p;
>                         input.selectionEnd = p;
>                 }
>         },
>         injectValue: function(input, keyCode, cursorPosition) {
>                 // inject the validated key into the input mask at the specified cursor position and return true on success
>                 var key = (keyCode.isBackspace)? '_': input.mask.getValidatedKey(keyCode, cursorPosition);
>                 if(key){
>                         input.value = cursorPosition.previousValue.substring(0, cursorPosition.start) + key + cursorPosition.previousValue.substring(cursorPosition.start + 1, cursorPosition.previousValue.length);
>                         return true;
>                 }
>                 // invalid key
>                 return false;
>         },
>         MaskType: function(inputTextElement, mask, clearWhenInvalid) {
>                 // this object instance is holds relative mask properties for a specified input element
>                 this.inputTextElement = inputTextElement;
>                 // designates whether or not the input value is cleared when its mask is incomplete and a blur event is triggered
>                 this.clearWhenInvalid = clearWhenInvalid;
>                 // holds the last validated key code
>                 this.lastValidatedKeyCode = null;
>                 // the mask value used to validate/mask valid input
>                 this.rawMask = mask;
>                 // the mask displayed in the input
>                 this.viewMask = '';
>                 // the string array of all the raw mask values (some indexes contain more than one char so we need to track this)
>                 this.maskArray = new Array();
>                 var mai = 0;
>                 var regexp = '';
>                 // cycle through the raw mask and perform view mask conversions
>                 for(var i=0; i<mask.length; i++){
>                         if(regexp){
>                                 if(regexp == 'X'){
>                                         // end of current regexp slot
>                                         regexp = '';
>                                 }
>                                 if(mask.charAt(i) == 'X'){
>                                         // current mask array index contains the complete regexp so we need to store it in the array
>                                         this.maskArray[mai] = regexp;
>                                         mai++;
>                                         regexp = null;
>                                 } else {
>                                         // still in the middle of the regexp keep adding the current character to the regexp
>                                         regexp += mask.charAt(i);
>                                 }
>                         } else if(mask.charAt(i) == 'X'){
>                                 // current slot is a regexp
>                                 regexp += 'X';
>                                 this.viewMask += '_';
>                         } else if(mask.charAt(i) == '9' || mask.charAt(i) == 'L' || mask.charAt(i) == 'l' || mask.charAt(i) == 'A') {
>                                 // the current mask character is one of the predefined/reserved characters
>                                 this.viewMask += '_';
>                                 this.maskArray[mai] = mask.charAt(i);
>                                 mai++;
>                         } else {
>                                 // just a regular char
>                                 this.viewMask += mask.charAt(i);
>                                 this.maskArray[mai] = mask.charAt(i);
>                                 mai++;
>                         }
>                 }
>                 // the predefined/reserved characters need to be replaced with the viewing mask char that desigantes an editable value (underscore)
>                 this.specialChars = this.viewMask.replace(/(L|l|9|A|_|X)/g,'');
>                 this.getValidatedKey = function(keyCode, cursorPosition) {
>                         // validates if the passed key code is valid for the specified cursor position and returns the value if it is. otherwise, return false
>                         var maskKey = this.maskArray[cursorPosition.start];
>                         if(maskKey == '9'){
>                                 // only allow numbers at the specified slot
>                                 return keyCode.pressedKey.match(/[0-9]/);
>                         } else if(maskKey == 'L'){
>                                 // only allow uppercase letters at specified slot (convert if necessary)
>                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toUpperCase(): null;
>                         } else if(maskKey == 'l'){
>                                 // only allow lowercase letters at specified slot (convert if necessary)
>                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toLowerCase(): null;
>                         } else {
>                                 if(maskKey == 'A'){
>                                         // only allow alpha-numeric values at the specified slot
>                                         return keyCode.pressedKey.match(/[A-Za-z0-9]/);
>                                 } else {
>                                         // only allow values that are verified by the specified regexp at the specified slot
>                                         return (this.maskArray[cursorPosition.start].length > 1)? keyCode.pressedKey.match(new RegExp(maskKey)): null;
>                                 }
>                         }
>                 };
>                 this.removeValueWhenInvalid = function(){
>                         // removes value from the input element when the mask is incomplete
>                         if(this.inputTextElement.value.indexOf('_') > -1){
>                                 this.inputTextElement.value = '';
>                         }
>                 };
>                 this.processMaskFormatting = function(e) {
>                         // capture event (should be the keydown event)
>                         var onKeyDownEvent = InputTextMask.getEvent(e);
>                         // create the key code from the event.
>                         var keyCode = new InputTextMask.KeyCode(onKeyDownEvent);
>                         if(InputTextMask.handleEventBubble(onKeyDownEvent, keyCode)){
>                                 // the pressed key is allowed to propagate- no mask injection required
>                                 return true;
>                         }
>                         var v = this.inputTextElement.value;
>                         if(v.length === 0){
>                                 // when the input value is empty populate it with the viewing mask
>                                 this.inputTextElement.value = this.viewMask;
>                         }
>                         var cursorPos = InputTextMask.getCursorPosition(this.inputTextElement, v);
>                         if(cursorPos.end == cursorPos.previousValue.length && !keyCode.isBackspace){
>                                 // input cursor position is at the end of the mask- do not allow any more characters to be keyed
>                                 return false;
>                         }
>                         // move the cursor position to the next slot that does not contain a mask character
>                         while(this.inputTextElement.mask.specialChars.match(RegExp.escape(cursorPos.previousValue.charAt(((keyCode.isBackspace)? cursorPos.start-1: cursorPos.start))))){
>                                 if(keyCode.isBackspace) {
>                                         // backspace needs to move the cursor backwards
>                                         cursorPos.decStart();
>                                 } else {
>                                         // still moving cursor one space to the right
>                                         cursorPos.incStart();
>                                 }
>                                 if(cursorPos.start >= cursorPos.previousValue.length || cursorPos.start < 0){
>                                         // end of the mask- no more keys should be keyed
>                                         return false;
>                                 }
>                         }
>                         if(keyCode.isBackspace){
>                                 // need to go back one space to the left
>                                 cursorPos.decStart();
>                         }
>                         // inject the key that was pressed into the input value mask
>                         if(InputTextMask.injectValue(this.inputTextElement, keyCode, cursorPos)){
>                                 // when the injection is sucessful move the cursor to the next slot to the right of the injected key
>                                 InputTextMask.moveCursorToPosition(this.inputTextElement, keyCode, cursorPos);
>                         }
>                         // because the pressed key is being injected we always need to return false to prevent duplicate
>                         // key injection
>                         return false;
>                 };
>         },
>         KeyCode: function(onKeyDownEvent) {
>                 this.onKeyDownEvent = onKeyDownEvent;
>                 // get the unicode value from the key event
>                 this.unicode = onKeyDownEvent.which? onKeyDownEvent.which: (onKeyDownEvent.keyCode? onKeyDownEvent.keyCode: (onKeyDownEvent.charCode? onKeyDownEvent.charCode: 0));
>                 this.isShiftPressed = onKeyDownEvent.shiftKey == false || onKeyDownEvent.shiftKey == true? onKeyDownEvent.shiftKey: (onKeyDownEvent.modifiers && (onKeyDownEvent.modifiers & 4)); //bitWise AND
>                 // TODO : need to get cap lock capture for onkeydown event
>                 //this.isCapLock = ((!this.isShiftPressed && this.unicode >= 65 && this.unicode <= 90) || (this.unicode >= 97 && this.unicode <= 122 && this.isShiftPressed));
>                 if(this.unicode >= 96 && this.unicode <= 105) {
>                         this.unicode -= 48; // handle number keypad
>                 }
>                 if(this.unicode >= 65 && this.unicode <= 90 && !this.isShiftPressed){
>                         this.unicode += 32; // handle uppercase
>                 }
>                 this.isTab = (this.unicode == 9)? true: false;
>                 this.isBackspace = (this.unicode == 8)? true: false;
>                 this.isLeftOrRightArrow = (this.unicode == 37 || this.unicode == 39)? true: false;
>                 // capture the actual key for the passed key code
>                 this.pressedKey = String.fromCharCode(this.unicode);
>         },
>         CursorPosition: function(start, end, range, previousValue) {
>                 // holds the cursor position values
>                 this.start = isNaN(start)? 0: start;
>                 this.end = isNaN(end)? 0: end;
>                 this.range = range;
>                 this.previousValue = previousValue;
>                 this.incStart = function(){
>                         this.start++;
>                 };
>                 this.decStart = function(){
>                         this.start--;
>                 };
>         }
> };
> // Add escape prototype feature to RegExp object
> // text.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$0');
> // text.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g, '\\$1');
> if(!RegExp.escape) {
>         RegExp.escape = function(text){
>                 var sp;
>                 if(!arguments.callee.sRE){
>                         sp=['/','.','*','+','?','|','(',')','[',']','{','}','\\'];
>                         arguments.callee.sRE = new RegExp('(\\' + sp.join('|\\') + ')','g');
>                 }
>                 return text.replace(arguments.callee.sRE, '\\$1');
>         };
> }
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Input Text Mask?

Posted by Igor Vaynberg <ig...@gmail.com>.
would you be interested in making this a subclass of textfield and
throwing it into wicketstuff-minis project which is in wicket-stuff?

-igor


On 10/18/07, William Hoover <wh...@nemours.org> wrote:
> Is anyone interested in using the mask script (below) to a component in a Wicket extension? The script prevents invalid input in a text field as the user types (similar to the Atlas version: http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx). I didn't see a component in Wicket that would accomplish this out-of-the-box and thought it would be a cool addition to Wicket.
>
> For example to force the input to mask a phone number:
> <input type="text" onfocus="InputTextMask.processMaskFocus(this, "(999)999-9999", true);" />
>
> /**
>  * InputTextMask script used for mask/regexp operations.
>  * Mask Individual Character Usage:
>  * 9 - designates only numeric values
>  * L - designates only uppercase letter values
>  * l - designates only lowercase letter values
>  * A - designates only alphanumeric values
>  * X - denotes that a custom client script regular expression is specified</li>
>  * All other characters are assumed to be "special" characters used to mask
>  * the input component
>  * Example 1:
>  * (999)999-9999 only numeric values can be entered where the the character
>  * position value is 9. Parenthesis and dash are non-editable/mask characters.
>  * Example 2:
>  * 99L-ll-X[^A-C]X only numeric values for the first two characters,
>  * uppercase values for the third character, lowercase letters for the
>  * fifth/sixth characters, and the last character X[^A-C]X together counts
>  * as the eighth character regular expression that would allow all characters
>  * but "A", "B", and "C". Dashes outside the regular expression are
>  * non-editable/mask characters.
>  */
> var InputTextMask = {
>         processMaskFocus: function(input, mask, clearWhenInvalid){
>                 // create an input mask and register it on the specified input (if it hasnt already been added by a previous call
>                 InputTextMask.createInputMask(input, mask, clearWhenInvalid);
>                 if(input.value.length == 0){
>                         // when the input value is empty populate it with the viewing mask and move the cursor to the
>                         // beginning of the input field
>                         var cursorPos = InputTextMask.getCursorPosition(input, input.value);
>                         input.value = input.mask.viewMask;
>                         InputTextMask.moveCursorToPosition(input, null, cursorPos);
>                 }
>         },
>         getEvent: function(e) {
>                 // get the event either from the window or from the passed event
>                 return (typeof event != 'undefined')? event: e;
>         },
>         handleEventBubble: function(keyEvent, keyCode){
>                 // this method ensures that the key enterned by the user is not propagated unless it is a tab or arrow key
>                 try {
>                         if(keyCode && (keyCode.isTab || keyCode.isLeftOrRightArrow)){
>                                 // allow all tab/arrow keys by returning true- no further action required
>                                 return true;
>                         }
>                         keyEvent.cancelBubble = true;
>                         if(keyEvent.stopPropagation){
>                                 // prevent other event triggers
>                                 keyEvent.stopPropagation();
>                         }
>                         if(keyEvent.preventDefault){
>                                 // prevent the default event from firing. in this case it is propagation of the keyed input
>                                 keyEvent.preventDefault();
>                         }
>                         return false;
>                 } catch(e) {
>                         alert(e.message);
>                 }
>         },
>         createInputMask: function(input, mask, clearWhenInvalid) {
>                 // if this input hasnt already registered its mask go ahead and do so now. This only needs to be performed the
>                 // first time the input is encountered when it gains focus. It will attach the MaskType object to the input object
>                 // add add all of the appropriate event listeners to ensure that the mask is applied
>                 if(!input.mask || input.mask.rawMask != mask){
>                         input.mask = new InputTextMask.MaskType(input, mask, clearWhenInvalid);
>                         // add the event listeners that will ensure that when the input contains an incomplete mask it will be remove.
>                         // Also, make sure that the keydown event is fired from this point forward thus invoking the mask format.
>                         if(input.addEventListener){
>                                 // most doms
>                                 input.addEventListener('blur', function(){input.mask.removeValueWhenInvalid();}, false);
>                                 input.addEventListener('keydown', function(e){return input.mask.processMaskFormatting(e);}, false);
>                                 if(window.opera){
>                                         // in opera- need to ensure that the keypress event isnt interfering with this input mask
>                                         input.addEventListener('keypress', function(e){return InputTextMask.handleEventBubble(InputTextMask.getEvent(e), null);}, false);
>                                 }
>                         } else if(input.attachEvent) {
>                                 // ie
>                                 input.attachEvent('onblur', function(){input.mask.removeValueWhenInvalid();});
>                                 input.attachEvent('onkeydown', function(e){return input.mask.processMaskFormatting(e);});
>                         } else {
>                                 // other browsers that do not support dynamic event propagations
>                                 input.onBlur = function(){input.mask.removeValueWhenInvalid();};
>                                 input.onKeyDown = function(e){input.mask.processMaskFormatting(e)};
>                         }
>                 }
>         },
>         getCursorPosition: function(input, previousValue) {
>                 // gets the current cursor position (s=start, e=end) and creates/returns a new CursorPosition instance
>                 var s, e, r;
>                 if(input.createTextRange){
>                         // ie- need to capture the start/end cursor positions
>                         r = document.selection.createRange().duplicate();
>                         r.moveEnd('character', previousValue.length);
>                         if(r.text === ''){
>                                 s = previousValue.length;
>                         } else {
>                                 s = previousValue.lastIndexOf(r.text);
>                         }
>                         r = document.selection.createRange().duplicate();
>                         r.moveStart('character', -previousValue.length);
>                         e = r.text.length;
>                 } else {
>                         // other browsers
>                         s = input.selectionStart;
>                         e = input.selectionEnd;
>                 }
>                 return new InputTextMask.CursorPosition(s, e, r, previousValue);
>         },
>         moveCursorToPosition: function(input, keyCode, cursorPosition) {
>                 // moves a cursor position for the passed input element to the specified cursor position- because the
>                 // range cursor position is 1 indexed we add an additional space (unless the pressed key is a backspace)
>                 var p = (!keyCode || (keyCode && keyCode.isBackspace))? cursorPosition.start: cursorPosition.start + 1;
>                 if(input.createTextRange){
>                         // ie move- cursor to the index p
>                         cursorPosition.range.move('character', p);
>                         cursorPosition.range.select();
>                 } else {
>                         // other browser- move cursor to the index p
>                         input.selectionStart = p;
>                         input.selectionEnd = p;
>                 }
>         },
>         injectValue: function(input, keyCode, cursorPosition) {
>                 // inject the validated key into the input mask at the specified cursor position and return true on success
>                 var key = (keyCode.isBackspace)? '_': input.mask.getValidatedKey(keyCode, cursorPosition);
>                 if(key){
>                         input.value = cursorPosition.previousValue.substring(0, cursorPosition.start) + key + cursorPosition.previousValue.substring(cursorPosition.start + 1, cursorPosition.previousValue.length);
>                         return true;
>                 }
>                 // invalid key
>                 return false;
>         },
>         MaskType: function(inputTextElement, mask, clearWhenInvalid) {
>                 // this object instance is holds relative mask properties for a specified input element
>                 this.inputTextElement = inputTextElement;
>                 // designates whether or not the input value is cleared when its mask is incomplete and a blur event is triggered
>                 this.clearWhenInvalid = clearWhenInvalid;
>                 // holds the last validated key code
>                 this.lastValidatedKeyCode = null;
>                 // the mask value used to validate/mask valid input
>                 this.rawMask = mask;
>                 // the mask displayed in the input
>                 this.viewMask = '';
>                 // the string array of all the raw mask values (some indexes contain more than one char so we need to track this)
>                 this.maskArray = new Array();
>                 var mai = 0;
>                 var regexp = '';
>                 // cycle through the raw mask and perform view mask conversions
>                 for(var i=0; i<mask.length; i++){
>                         if(regexp){
>                                 if(regexp == 'X'){
>                                         // end of current regexp slot
>                                         regexp = '';
>                                 }
>                                 if(mask.charAt(i) == 'X'){
>                                         // current mask array index contains the complete regexp so we need to store it in the array
>                                         this.maskArray[mai] = regexp;
>                                         mai++;
>                                         regexp = null;
>                                 } else {
>                                         // still in the middle of the regexp keep adding the current character to the regexp
>                                         regexp += mask.charAt(i);
>                                 }
>                         } else if(mask.charAt(i) == 'X'){
>                                 // current slot is a regexp
>                                 regexp += 'X';
>                                 this.viewMask += '_';
>                         } else if(mask.charAt(i) == '9' || mask.charAt(i) == 'L' || mask.charAt(i) == 'l' || mask.charAt(i) == 'A') {
>                                 // the current mask character is one of the predefined/reserved characters
>                                 this.viewMask += '_';
>                                 this.maskArray[mai] = mask.charAt(i);
>                                 mai++;
>                         } else {
>                                 // just a regular char
>                                 this.viewMask += mask.charAt(i);
>                                 this.maskArray[mai] = mask.charAt(i);
>                                 mai++;
>                         }
>                 }
>                 // the predefined/reserved characters need to be replaced with the viewing mask char that desigantes an editable value (underscore)
>                 this.specialChars = this.viewMask.replace(/(L|l|9|A|_|X)/g,'');
>                 this.getValidatedKey = function(keyCode, cursorPosition) {
>                         // validates if the passed key code is valid for the specified cursor position and returns the value if it is. otherwise, return false
>                         var maskKey = this.maskArray[cursorPosition.start];
>                         if(maskKey == '9'){
>                                 // only allow numbers at the specified slot
>                                 return keyCode.pressedKey.match(/[0-9]/);
>                         } else if(maskKey == 'L'){
>                                 // only allow uppercase letters at specified slot (convert if necessary)
>                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toUpperCase(): null;
>                         } else if(maskKey == 'l'){
>                                 // only allow lowercase letters at specified slot (convert if necessary)
>                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toLowerCase(): null;
>                         } else {
>                                 if(maskKey == 'A'){
>                                         // only allow alpha-numeric values at the specified slot
>                                         return keyCode.pressedKey.match(/[A-Za-z0-9]/);
>                                 } else {
>                                         // only allow values that are verified by the specified regexp at the specified slot
>                                         return (this.maskArray[cursorPosition.start].length > 1)? keyCode.pressedKey.match(new RegExp(maskKey)): null;
>                                 }
>                         }
>                 };
>                 this.removeValueWhenInvalid = function(){
>                         // removes value from the input element when the mask is incomplete
>                         if(this.inputTextElement.value.indexOf('_') > -1){
>                                 this.inputTextElement.value = '';
>                         }
>                 };
>                 this.processMaskFormatting = function(e) {
>                         // capture event (should be the keydown event)
>                         var onKeyDownEvent = InputTextMask.getEvent(e);
>                         // create the key code from the event.
>                         var keyCode = new InputTextMask.KeyCode(onKeyDownEvent);
>                         if(InputTextMask.handleEventBubble(onKeyDownEvent, keyCode)){
>                                 // the pressed key is allowed to propagate- no mask injection required
>                                 return true;
>                         }
>                         var v = this.inputTextElement.value;
>                         if(v.length === 0){
>                                 // when the input value is empty populate it with the viewing mask
>                                 this.inputTextElement.value = this.viewMask;
>                         }
>                         var cursorPos = InputTextMask.getCursorPosition(this.inputTextElement, v);
>                         if(cursorPos.end == cursorPos.previousValue.length && !keyCode.isBackspace){
>                                 // input cursor position is at the end of the mask- do not allow any more characters to be keyed
>                                 return false;
>                         }
>                         // move the cursor position to the next slot that does not contain a mask character
>                         while(this.inputTextElement.mask.specialChars.match(RegExp.escape(cursorPos.previousValue.charAt(((keyCode.isBackspace)? cursorPos.start-1: cursorPos.start))))){
>                                 if(keyCode.isBackspace) {
>                                         // backspace needs to move the cursor backwards
>                                         cursorPos.decStart();
>                                 } else {
>                                         // still moving cursor one space to the right
>                                         cursorPos.incStart();
>                                 }
>                                 if(cursorPos.start >= cursorPos.previousValue.length || cursorPos.start < 0){
>                                         // end of the mask- no more keys should be keyed
>                                         return false;
>                                 }
>                         }
>                         if(keyCode.isBackspace){
>                                 // need to go back one space to the left
>                                 cursorPos.decStart();
>                         }
>                         // inject the key that was pressed into the input value mask
>                         if(InputTextMask.injectValue(this.inputTextElement, keyCode, cursorPos)){
>                                 // when the injection is sucessful move the cursor to the next slot to the right of the injected key
>                                 InputTextMask.moveCursorToPosition(this.inputTextElement, keyCode, cursorPos);
>                         }
>                         // because the pressed key is being injected we always need to return false to prevent duplicate
>                         // key injection
>                         return false;
>                 };
>         },
>         KeyCode: function(onKeyDownEvent) {
>                 this.onKeyDownEvent = onKeyDownEvent;
>                 // get the unicode value from the key event
>                 this.unicode = onKeyDownEvent.which? onKeyDownEvent.which: (onKeyDownEvent.keyCode? onKeyDownEvent.keyCode: (onKeyDownEvent.charCode? onKeyDownEvent.charCode: 0));
>                 this.isShiftPressed = onKeyDownEvent.shiftKey == false || onKeyDownEvent.shiftKey == true? onKeyDownEvent.shiftKey: (onKeyDownEvent.modifiers && (onKeyDownEvent.modifiers & 4)); //bitWise AND
>                 // TODO : need to get cap lock capture for onkeydown event
>                 //this.isCapLock = ((!this.isShiftPressed && this.unicode >= 65 && this.unicode <= 90) || (this.unicode >= 97 && this.unicode <= 122 && this.isShiftPressed));
>                 if(this.unicode >= 96 && this.unicode <= 105) {
>                         this.unicode -= 48; // handle number keypad
>                 }
>                 if(this.unicode >= 65 && this.unicode <= 90 && !this.isShiftPressed){
>                         this.unicode += 32; // handle uppercase
>                 }
>                 this.isTab = (this.unicode == 9)? true: false;
>                 this.isBackspace = (this.unicode == 8)? true: false;
>                 this.isLeftOrRightArrow = (this.unicode == 37 || this.unicode == 39)? true: false;
>                 // capture the actual key for the passed key code
>                 this.pressedKey = String.fromCharCode(this.unicode);
>         },
>         CursorPosition: function(start, end, range, previousValue) {
>                 // holds the cursor position values
>                 this.start = isNaN(start)? 0: start;
>                 this.end = isNaN(end)? 0: end;
>                 this.range = range;
>                 this.previousValue = previousValue;
>                 this.incStart = function(){
>                         this.start++;
>                 };
>                 this.decStart = function(){
>                         this.start--;
>                 };
>         }
> };
> // Add escape prototype feature to RegExp object
> // text.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$0');
> // text.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g, '\\$1');
> if(!RegExp.escape) {
>         RegExp.escape = function(text){
>                 var sp;
>                 if(!arguments.callee.sRE){
>                         sp=['/','.','*','+','?','|','(',')','[',']','{','}','\\'];
>                         arguments.callee.sRE = new RegExp('(\\' + sp.join('|\\') + ')','g');
>                 }
>                 return text.replace(arguments.callee.sRE, '\\$1');
>         };
> }
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org