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

[Trinidad] Input Text Format That Uses A Mask

Hello all, 
I have created a Trinidad component that allows input text boxes to have a user defined mask for entries on the client (similar to Atlas MaskEdit <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I would like to know what the process/procedure is to commit this component to the sandbox?


RE: [Trinidad] Input Text Format That Uses A Mask

Posted by William Hoover <wh...@nemours.org>.
Thanks for the input Adam!

I updated the code snippet below with some comments and updates that dynamically attach the keydown/blur events. Could you elaborate on how to implement the inline hook and where to look in the code to do this? I would like to convert the component into a validator/converter and it looks like adding a hook would be better suited to do so.

-----Original Message-----
From: Adam Winer [mailto:awiner@gmail.com]
Sent: Thursday, June 07, 2007 11:32 AM
To: MyFaces Discussion
Subject: Re: [Trinidad] Input Text Format That Uses A Mask


On 6/7/07, William Hoover <wh...@nemours.org> wrote:
> Question: If it was to use a converter/validator at what point would it append onfocus (and any other events needed)? With a component it is appended when it is rendered. If it were a validator it would have to add events to the component its validating. Is this a good practice?

I was thinking we'd add a hook to the general client-side validation
framework that, during onload (and after PPR replacement, if new
fields are added or rewritten), would let  the validators have a pass
at the DOM.

There's a few big advantages to doing this in JS, instead of in rendering:
- There's no I/O cost of sending across the JS
- You're writing JS in JS, instead of writing Java that outputs JS,
which is always awkward IMO
- The Renderer doesn't need to change

> I'm in the process of implementing the previously suggested JS event attachments so the only event that has to be explicitly attached is the focus. Correct me if I'm wrong, but once the field gains focus it should dynamically attach the onkeydown/blur events to the passed input text element? Currently it attaches a "MaskType" object to the input text to keep track of input info such as the last cursor position, the raw mask, the parsed mask, the viewing mask, and the containing mask validator function. This makes it easier to validate the input content because the validating method is attached to the input element itself. It also prevents reparsing of code that isn't necessary. Here is the client script (does not yet have the dynamic event attachment mentioned above) Suggestions are welcomed!:

Dynamically attaching the onkeydown/blur when you receive the focus definitely
seems like a good idea.

I guess my first suggestion for the JS is that some comments would be nice!

-- Adam


// TODO : bug in Opera (doesnt allow backspace cancel). 
// TODO : needs tested on other OS platforms.
// TODO : need to add feature that will allow a mask that can have an infinate (or predifined) amount of validated values/characters at the end of the mask
/**
 * CoreInputTextForamt component 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 CoreInputTextFormat = {
	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
		CoreInputTextFormat.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 = CoreInputTextFormat.getCursorPosition(input, input.value);
			input.value = input.mask.viewMask;
			CoreInputTextFormat.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 CoreInputTextFormat.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 CoreInputTextFormat.handleEventBubble(CoreInputTextFormat.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 CoreInputTextFormat.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 = CoreInputTextFormat.getEvent(e);
			// create the key code from the event. 
			var keyCode = new CoreInputTextFormat.KeyCode(onKeyDownEvent);
			if(CoreInputTextFormat.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 = CoreInputTextFormat.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(CoreInputTextFormat.injectValue(this.inputTextElement, keyCode, cursorPos)){
				// when the injection is sucessful move the cursor to the next slot to the right of the injected key
				CoreInputTextFormat.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
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');
	};
}
>
> -----Original Message-----
> From: Adam Winer [mailto:awiner@gmail.com]
> Sent: Wednesday, June 06, 2007 8:26 PM
> To: MyFaces Discussion
> Subject: Re: [Trinidad] Input Text Format That Uses A Mask
>
>
> Trinidad already has a validateRegExp validator, FWIW,
> which attaches both client-side and server-side validation, but
> has no mask functionality.  The Tomahawk validator is just a Java
> JSF Validator, no client-side functionality, right?
>
> What this masking thing adds is:
> -  a simpler syntax for expressing masking.  For example,
>  to do a phone number in regexp, you'd have to write something
> like:
>   \(\d\d\d\)-\d\d\d-\d\d\d\d
> instead of:
>   (999)-999-9999
> - keydown/blur/focus handling so that the parts of the
>   mask that are "fixed" can automatically be inserted
>   and skipped over.
>
> onblur, I imagine, is responsible for reporting errors.
> That part of this should definitely be hooked into the
> existing Trinidad client-side validation - which isn't
> just alerts anymore thanks to Dan Robinson, but does
> need a final tweak to be onblur instead of onsubmit,
> at least for INLINE style.
>
> That leaves keydown/focus.  One way this might be
> implemented is having an optional method on the
> JS validator instances that, if present, will get called
> with the relevant DOM form element.  At that point,
> the validator could attach any keydown/blur/focus
> handling that it wants to.  The framework would handle
> blur in general, the mask validator would just need to
> attach keydown/focus.
>
> -- Adam
>
>
>
>
> On 6/6/07, Mike Kienenberger <mk...@gmail.com> wrote:
> > How does this compare to validateRegExpr in Tomahawk, particularly if
> > it becomes a validator instead of a component?
> >
> > http://myfaces.apache.org/tomahawk/validateRegExpr.html
> >
> > On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > > Point well taken! The component should extend UIXInput instead and renamed CoreInputMask. Are you are proposing to change this into a validator or converter instead of a component extension? If it was to use a converter/validator at what point would it append the JS event calls (onkeydown, onblur, onfocus)? As of yet it does not address server-side validation, but it would be fairly easy to implement. Currently, using the example of a (999)999-9999 mask, and an input of (415)555-1212 the bean would see exactly what the user input i.e. (415)555-1212 If a converter/validator was to be used it would be simple enough to strip the mask characters. I would assume that it would be best to have this as an option because it may be desirable to maintain the mask?
> > >
> > >
> > >
> > > -----Original Message-----
> > > From: Adam Winer [mailto:awiner@gmail.com]
> > > Sent: Wednesday, June 06, 2007 12:03 PM
> > > To: MyFaces Discussion
> > > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> > >
> > >
> > > A few and questions:
> > > - Generally speaking, we don't extend CoreInputText, we just
> > >   re-extend UIXInput.  The metadata system supports "includes"
> > >   for generation, so you don't have to cut-and-paste that much.
> > >   One good reason, in this case, is that I assume that this
> > >   component doesn't support <TEXTAREA>, just <INPUT> -
> > >   so you don't want "rows" or "wrap".
> > > - I'd love to see this as a converter or validator tag that can be
> > >   added to an ordinary af:inputText.  We'd need a bit of beefing
> > >   up of our client-side code JS framework for validators, but
> > >   that'd be worthwhile.
> > > - What's the server-side model look like?  E.g., when you
> > >    have (999)999-9999, does your bean see strings like
> > >    (415)555-1212, or do you get 4155551212?  Is there server-side
> > >    validation to double-check the mask was applied?
> > > - If this is a component, I think CoreInputTextMasked might
> > >   be clearer, if the property is named "mask".
> > >
> > > -- Adam
> > >
> > >
> > >
> > > On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > > > Thanks for the info Adam!
> > > >
> > > > The component (CoreInputTextFormat) logic is fairly simple and could be directly integrated into the CoreInputText, if desired. It extends CoreInputText and adds two extra PropertyKeys: "mask" and "clearWhenInvalid". The "mask" attribute designates the pattern for which will be used to prevent invalid characters at the specified slots. For Example, (999)999-9999 would be displayed as (___)___-____ allowing only numeric values to be entered where underscores are present (see examples below for a more detailed overview). The "clearWhenInvalid" is an option to clear the contents (onblur) of the input field when it does not meet the mask pattern requirements- default is currently true. The only other logic contained in the component is used to make the JS calls: onblur, onfocus, and onkeydown. The client script is contained in a namespace called "CoreInputTextFormat" so none of the functions will interfere with other Trinidad scripts (as you suggested in TRINIDAD-37 it would be nice if we had a Trinidad namespace that could register component level namespaces!). It does however add a prototype extension to RegExp to allow RegExp.escape(someText) preventing recompilation of the escape expression. That is it! I don't think there is a significant amount of code to warrant a CLA (client script under 200 lines, component logic is trivial). Let me know what your thoughts on all of this!
> > > >
> > > > Mask Individual Character Usage and Reserved Characters:
> > > > 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
> > > > All other characters are assumed to be "special" characters used to mask the input component
> > > >
> > > > Examples:
> > > > (999)999-9999
> > > >         only numeric values can be entered where the character position value is 9. Parenthesis and dash are non-editable/mask characters.
> > > > 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.
> > > >
> > > > -----Original Message-----
> > > > From: Adam Winer [mailto:awiner@gmail.com]
> > > > Sent: Tuesday, June 05, 2007 7:09 PM
> > > > To: MyFaces Discussion
> > > > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> > > >
> > > >
> > > > Roughly speaking, you:
> > > > - Create an issue on JIRA
> > > > - Attach a patch
> > > > - If it's a significant quantity of code, file a CLA
> > > >   http://www.apache.org/licenses/icla.txt
> > > >
> > > > It's also generally a good thing to talk over the
> > > > design first.  I'd thing it'd be great if this were part of
> > > > the client-side validation code, instead of just its
> > > > own code.  I think getting this issue fixed:
> > > > http://issues.apache.org/jira/browse/TRINIDAD-37
> > > > ... would be important for that.
> > > >
> > > > I'd love to see this functionality!
> > > >
> > > > -- Adam
> > > >
> > > >
> > > > On 6/5/07, William Hoover <wh...@nemours.org> wrote:
> > > > >
> > > > >
> > > > >
> > > > > Hello all,
> > > > > I have created a Trinidad component that allows input text boxes to have a
> > > > > user defined mask for entries on the client (similar to Atlas MaskEdit
> > > > > <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> > > > > would like to know what the process/procedure is to commit this component to
> > > > > the sandbox?
> > > >
> > > >
> > >
> > >
> >
>
>


Re: [Trinidad] Input Text Format That Uses A Mask

Posted by Adam Winer <aw...@gmail.com>.
On 6/7/07, William Hoover <wh...@nemours.org> wrote:
> Question: If it was to use a converter/validator at what point would it append onfocus (and any other events needed)? With a component it is appended when it is rendered. If it were a validator it would have to add events to the component its validating. Is this a good practice?

I was thinking we'd add a hook to the general client-side validation
framework that, during onload (and after PPR replacement, if new
fields are added or rewritten), would let  the validators have a pass
at the DOM.

There's a few big advantages to doing this in JS, instead of in rendering:
- There's no I/O cost of sending across the JS
- You're writing JS in JS, instead of writing Java that outputs JS,
which is always awkward IMO
- The Renderer doesn't need to change

> I'm in the process of implementing the previously suggested JS event attachments so the only event that has to be explicitly attached is the focus. Correct me if I'm wrong, but once the field gains focus it should dynamically attach the onkeydown/blur events to the passed input text element? Currently it attaches a "MaskType" object to the input text to keep track of input info such as the last cursor position, the raw mask, the parsed mask, the viewing mask, and the containing mask validator function. This makes it easier to validate the input content because the validating method is attached to the input element itself. It also prevents reparsing of code that isn't necessary. Here is the client script (does not yet have the dynamic event attachment mentioned above) Suggestions are welcomed!:

Dynamically attaching the onkeydown/blur when you receive the focus definitely
seems like a good idea.

I guess my first suggestion for the JS is that some comments would be nice!

-- Adam


> /**
> * CoreInputTextForamt component script used for mask/regexp operations
> */
> var CoreInputTextFormat = {
>         processMaskFocus: function(input, mask){
>                 CoreInputTextFormat.createInputMask(input, mask);
>                 if(input.value.length == 0){
>                         var cursorPos = CoreInputTextFormat.getCursorPosition(input, input.value);
>                         input.value = input.mask.viewMask;
>                         CoreInputTextFormat.moveCursorToPosition(input, null, cursorPos);
>                 }
>         },
>         processMaskBlur: function(input) {
>                 if(!input.mask.isValidValue(input)){
>                         input.value = '';
>                 }
>         },
>         processMaskKeyCode: function(input, onKeyDownEvent, mask) {
>                 CoreInputTextFormat.handleEventBubble(onKeyDownEvent);
>                 CoreInputTextFormat.createInputMask(input, mask);
>                 var keyCode = new CoreInputTextFormat.KeyCode(onKeyDownEvent);
>                 if(keyCode.isTab || keyCode.isLeftOrRightArrow){
>                         return true;
>                 }
>                 var v = input.value;
>                 if(v.length === 0){
>                         input.value = mask;
>                 }
>                 var cursorPos = CoreInputTextFormat.getCursorPosition(input, v);
>                 if(cursorPos.end == cursorPos.previousValue.length && !keyCode.isBackspace){
>                         return false;
>                 }
>                 while(input.mask.specialChars.match(RegExp.escape(cursorPos.previousValue.charAt(((keyCode.isBackspace)? cursorPos.start-1: cursorPos.start))))){
>                         if(keyCode.isBackspace) {
>                                 cursorPos.decStart();
>                         } else {
>                                 cursorPos.incStart();
>                         }
>                         if(cursorPos.start >= cursorPos.previousValue.length || cursorPos.start < 0){
>                                 return false;
>                         }
>                 }
>                 if(keyCode.isBackspace){
>                         cursorPos.decStart();
>                 }
>                 if(CoreInputTextFormat.injectValue(input, keyCode, cursorPos)){
>                         CoreInputTextFormat.moveCursorToPosition(input, keyCode, cursorPos);
>                 }
>                 return false;
>         },
>         handleEventBubble: function(onKeyDownEvent){
>                 try {
>                         onKeyDownEvent.cancelBubble = true;
>                         if(onKeyDownEvent.stopPropagation){
>                                 onKeyDownEvent.stopPropagation();
>                         }
>                 } catch(e) {
>                         alert(e.message);
>                 }
>         },
>         createInputMask: function(input, mask) {
>                 if(!input.mask || input.mask.rawMask != mask){
>                         input.mask = new CoreInputTextFormat.MaskType(mask);
>                 }
>         },
>         getCursorPosition: function(input, previousValue) {
>                 var s, e, r;
>                 if(input.createTextRange){
>                         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 {
>                         s = input.selectionStart;
>                         e = input.selectionEnd;
>                 }
>                 return new CoreInputTextFormat.CursorPosition(s, e, r, previousValue);
>         },
>         moveCursorToPosition: function(input, keyCode, cursorPosition) {
>                 var p = (!keyCode || (keyCode && keyCode.isBackspace))? cursorPosition.start: cursorPosition.start + 1;
>                 if(input.createTextRange){
>                         cursorPosition.range.move('character', p);
>                         cursorPosition.range.select();
>                 } else {
>                         input.selectionStart = p;
>                         input.selectionEnd = p;
>                 }
>         },
>         injectValue: function(input, keyCode, cursorPosition) {
>                 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;
>                 }
>                 return false;
>         },
>         MaskType: function(mask) {
>                 this.lastValidatedKeyCode = null;
>                 this.rawMask = mask;
>                 this.viewMask = '';
>                 this.maskArray = new Array();
>                 var mai = 0;
>                 var regexp = '';
>                 for(var i=0; i<mask.length; i++){
>                         if(regexp){
>                                 if(regexp == 'X'){
>                                         regexp = '';
>                                 }
>                                 if(mask.charAt(i) == 'X'){
>                                         this.maskArray[mai] = regexp;
>                                         mai++;
>                                         regexp = null;
>                                 } else {
>                                         regexp += mask.charAt(i);
>                                 }
>                         } else if(mask.charAt(i) == 'X'){
>                                 regexp += 'X';
>                                 this.viewMask += '_';
>                         } else if(mask.charAt(i) == '9' || mask.charAt(i) == 'L' || mask.charAt(i) == 'l' || mask.charAt(i) == 'A') {
>                                 this.viewMask += '_';
>                                 this.maskArray[mai] = mask.charAt(i);
>                                 mai++;
>                         } else {
>                                 this.viewMask += mask.charAt(i);
>                                 this.maskArray[mai] = mask.charAt(i);
>                                 mai++;
>                         }
>                 }
>                 this.specialChars = this.viewMask.replace(/(L|l|9|A|_|X)/g,'');
>                 this.getValidatedKey = function(keyCode, cursorPosition) {
>                         var maskKey = this.maskArray[cursorPosition.start];
>                         if(maskKey == '9'){
>                                 return keyCode.pressedKey.match(/[0-9]/);
>                         } else if(maskKey == 'L'){
>                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toUpperCase(): null;
>                         } else if(maskKey == 'l'){
>                                 return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toLowerCase(): null;
>                         } else {
>                                 if(maskKey == 'A'){
>                                         return keyCode.pressedKey.match(/[A-Za-z0-9]/);
>                                 } else {
>                                         return (this.maskArray[cursorPosition.start].length > 1)? keyCode.pressedKey.match(new RegExp(maskKey)): null;
>                                 }
>                         }
>                 };
>                 this.isValidValue = function(input){
>                         return input.value.indexOf('_') <= -1;
>                 };
>         },
>         KeyCode: function(onKeyDownEvent) {
>                 this.onKeyDownEvent = onKeyDownEvent;
>                 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;
>                 this.pressedKey = String.fromCharCode(this.unicode);
>         },
>         CursorPosition: function(start, end, range, previousValue) {
>                 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 feature to RegExp object
> 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');
>         };
> }
>
> -----Original Message-----
> From: Adam Winer [mailto:awiner@gmail.com]
> Sent: Wednesday, June 06, 2007 8:26 PM
> To: MyFaces Discussion
> Subject: Re: [Trinidad] Input Text Format That Uses A Mask
>
>
> Trinidad already has a validateRegExp validator, FWIW,
> which attaches both client-side and server-side validation, but
> has no mask functionality.  The Tomahawk validator is just a Java
> JSF Validator, no client-side functionality, right?
>
> What this masking thing adds is:
> -  a simpler syntax for expressing masking.  For example,
>  to do a phone number in regexp, you'd have to write something
> like:
>   \(\d\d\d\)-\d\d\d-\d\d\d\d
> instead of:
>   (999)-999-9999
> - keydown/blur/focus handling so that the parts of the
>   mask that are "fixed" can automatically be inserted
>   and skipped over.
>
> onblur, I imagine, is responsible for reporting errors.
> That part of this should definitely be hooked into the
> existing Trinidad client-side validation - which isn't
> just alerts anymore thanks to Dan Robinson, but does
> need a final tweak to be onblur instead of onsubmit,
> at least for INLINE style.
>
> That leaves keydown/focus.  One way this might be
> implemented is having an optional method on the
> JS validator instances that, if present, will get called
> with the relevant DOM form element.  At that point,
> the validator could attach any keydown/blur/focus
> handling that it wants to.  The framework would handle
> blur in general, the mask validator would just need to
> attach keydown/focus.
>
> -- Adam
>
>
>
>
> On 6/6/07, Mike Kienenberger <mk...@gmail.com> wrote:
> > How does this compare to validateRegExpr in Tomahawk, particularly if
> > it becomes a validator instead of a component?
> >
> > http://myfaces.apache.org/tomahawk/validateRegExpr.html
> >
> > On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > > Point well taken! The component should extend UIXInput instead and renamed CoreInputMask. Are you are proposing to change this into a validator or converter instead of a component extension? If it was to use a converter/validator at what point would it append the JS event calls (onkeydown, onblur, onfocus)? As of yet it does not address server-side validation, but it would be fairly easy to implement. Currently, using the example of a (999)999-9999 mask, and an input of (415)555-1212 the bean would see exactly what the user input i.e. (415)555-1212 If a converter/validator was to be used it would be simple enough to strip the mask characters. I would assume that it would be best to have this as an option because it may be desirable to maintain the mask?
> > >
> > >
> > >
> > > -----Original Message-----
> > > From: Adam Winer [mailto:awiner@gmail.com]
> > > Sent: Wednesday, June 06, 2007 12:03 PM
> > > To: MyFaces Discussion
> > > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> > >
> > >
> > > A few and questions:
> > > - Generally speaking, we don't extend CoreInputText, we just
> > >   re-extend UIXInput.  The metadata system supports "includes"
> > >   for generation, so you don't have to cut-and-paste that much.
> > >   One good reason, in this case, is that I assume that this
> > >   component doesn't support <TEXTAREA>, just <INPUT> -
> > >   so you don't want "rows" or "wrap".
> > > - I'd love to see this as a converter or validator tag that can be
> > >   added to an ordinary af:inputText.  We'd need a bit of beefing
> > >   up of our client-side code JS framework for validators, but
> > >   that'd be worthwhile.
> > > - What's the server-side model look like?  E.g., when you
> > >    have (999)999-9999, does your bean see strings like
> > >    (415)555-1212, or do you get 4155551212?  Is there server-side
> > >    validation to double-check the mask was applied?
> > > - If this is a component, I think CoreInputTextMasked might
> > >   be clearer, if the property is named "mask".
> > >
> > > -- Adam
> > >
> > >
> > >
> > > On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > > > Thanks for the info Adam!
> > > >
> > > > The component (CoreInputTextFormat) logic is fairly simple and could be directly integrated into the CoreInputText, if desired. It extends CoreInputText and adds two extra PropertyKeys: "mask" and "clearWhenInvalid". The "mask" attribute designates the pattern for which will be used to prevent invalid characters at the specified slots. For Example, (999)999-9999 would be displayed as (___)___-____ allowing only numeric values to be entered where underscores are present (see examples below for a more detailed overview). The "clearWhenInvalid" is an option to clear the contents (onblur) of the input field when it does not meet the mask pattern requirements- default is currently true. The only other logic contained in the component is used to make the JS calls: onblur, onfocus, and onkeydown. The client script is contained in a namespace called "CoreInputTextFormat" so none of the functions will interfere with other Trinidad scripts (as you suggested in TRINIDAD-37 it would be nice if we had a Trinidad namespace that could register component level namespaces!). It does however add a prototype extension to RegExp to allow RegExp.escape(someText) preventing recompilation of the escape expression. That is it! I don't think there is a significant amount of code to warrant a CLA (client script under 200 lines, component logic is trivial). Let me know what your thoughts on all of this!
> > > >
> > > > Mask Individual Character Usage and Reserved Characters:
> > > > 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
> > > > All other characters are assumed to be "special" characters used to mask the input component
> > > >
> > > > Examples:
> > > > (999)999-9999
> > > >         only numeric values can be entered where the character position value is 9. Parenthesis and dash are non-editable/mask characters.
> > > > 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.
> > > >
> > > > -----Original Message-----
> > > > From: Adam Winer [mailto:awiner@gmail.com]
> > > > Sent: Tuesday, June 05, 2007 7:09 PM
> > > > To: MyFaces Discussion
> > > > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> > > >
> > > >
> > > > Roughly speaking, you:
> > > > - Create an issue on JIRA
> > > > - Attach a patch
> > > > - If it's a significant quantity of code, file a CLA
> > > >   http://www.apache.org/licenses/icla.txt
> > > >
> > > > It's also generally a good thing to talk over the
> > > > design first.  I'd thing it'd be great if this were part of
> > > > the client-side validation code, instead of just its
> > > > own code.  I think getting this issue fixed:
> > > > http://issues.apache.org/jira/browse/TRINIDAD-37
> > > > ... would be important for that.
> > > >
> > > > I'd love to see this functionality!
> > > >
> > > > -- Adam
> > > >
> > > >
> > > > On 6/5/07, William Hoover <wh...@nemours.org> wrote:
> > > > >
> > > > >
> > > > >
> > > > > Hello all,
> > > > > I have created a Trinidad component that allows input text boxes to have a
> > > > > user defined mask for entries on the client (similar to Atlas MaskEdit
> > > > > <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> > > > > would like to know what the process/procedure is to commit this component to
> > > > > the sandbox?
> > > >
> > > >
> > >
> > >
> >
>
>

RE: [Trinidad] Input Text Format That Uses A Mask

Posted by William Hoover <wh...@nemours.org>.
Question: If it was to use a converter/validator at what point would it append onfocus (and any other events needed)? With a component it is appended when it is rendered. If it were a validator it would have to add events to the component its validating. Is this a good practice?

I'm in the process of implementing the previously suggested JS event attachments so the only event that has to be explicitly attached is the focus. Correct me if I'm wrong, but once the field gains focus it should dynamically attach the onkeydown/blur events to the passed input text element? Currently it attaches a "MaskType" object to the input text to keep track of input info such as the last cursor position, the raw mask, the parsed mask, the viewing mask, and the containing mask validator function. This makes it easier to validate the input content because the validating method is attached to the input element itself. It also prevents reparsing of code that isn't necessary. Here is the client script (does not yet have the dynamic event attachment mentioned above) Suggestions are welcomed!:

/**
* CoreInputTextForamt component script used for mask/regexp operations
*/
var CoreInputTextFormat = {
	processMaskFocus: function(input, mask){
		CoreInputTextFormat.createInputMask(input, mask);
		if(input.value.length == 0){
			var cursorPos = CoreInputTextFormat.getCursorPosition(input, input.value);
			input.value = input.mask.viewMask;
			CoreInputTextFormat.moveCursorToPosition(input, null, cursorPos);
		}
	},
	processMaskBlur: function(input) {
		if(!input.mask.isValidValue(input)){
			input.value = '';
		}
	},
	processMaskKeyCode: function(input, onKeyDownEvent, mask) {
		CoreInputTextFormat.handleEventBubble(onKeyDownEvent);
		CoreInputTextFormat.createInputMask(input, mask);
		var keyCode = new CoreInputTextFormat.KeyCode(onKeyDownEvent);
		if(keyCode.isTab || keyCode.isLeftOrRightArrow){
			return true;
		}
		var v = input.value;
		if(v.length === 0){
			input.value = mask;
		}
		var cursorPos = CoreInputTextFormat.getCursorPosition(input, v);
		if(cursorPos.end == cursorPos.previousValue.length && !keyCode.isBackspace){
			return false;
		}
		while(input.mask.specialChars.match(RegExp.escape(cursorPos.previousValue.charAt(((keyCode.isBackspace)? cursorPos.start-1: cursorPos.start))))){
			if(keyCode.isBackspace) {
				cursorPos.decStart();
			} else {
				cursorPos.incStart();
			}
			if(cursorPos.start >= cursorPos.previousValue.length || cursorPos.start < 0){
				return false;
			}
		}
		if(keyCode.isBackspace){
			cursorPos.decStart();
		}
		if(CoreInputTextFormat.injectValue(input, keyCode, cursorPos)){
			CoreInputTextFormat.moveCursorToPosition(input, keyCode, cursorPos);
		}
		return false;
	},
	handleEventBubble: function(onKeyDownEvent){
		try {
			onKeyDownEvent.cancelBubble = true;
			if(onKeyDownEvent.stopPropagation){
				onKeyDownEvent.stopPropagation();
			}
		} catch(e) {
			alert(e.message);
		}
	},
	createInputMask: function(input, mask) {
		if(!input.mask || input.mask.rawMask != mask){
			input.mask = new CoreInputTextFormat.MaskType(mask);
		}
	},
	getCursorPosition: function(input, previousValue) {
		var s, e, r;
		if(input.createTextRange){
			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 {
			s = input.selectionStart;
			e = input.selectionEnd;
		}
		return new CoreInputTextFormat.CursorPosition(s, e, r, previousValue);
	},
	moveCursorToPosition: function(input, keyCode, cursorPosition) {
		var p = (!keyCode || (keyCode && keyCode.isBackspace))? cursorPosition.start: cursorPosition.start + 1;
		if(input.createTextRange){
			cursorPosition.range.move('character', p);
			cursorPosition.range.select();
		} else {
			input.selectionStart = p;
			input.selectionEnd = p;
		}
	},
	injectValue: function(input, keyCode, cursorPosition) {
		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;
		}
		return false;
	},
	MaskType: function(mask) {
		this.lastValidatedKeyCode = null;
		this.rawMask = mask;
		this.viewMask = '';
		this.maskArray = new Array();
		var mai = 0;
		var regexp = '';
		for(var i=0; i<mask.length; i++){
			if(regexp){
				if(regexp == 'X'){
					regexp = '';
				}
				if(mask.charAt(i) == 'X'){
					this.maskArray[mai] = regexp;
					mai++;
					regexp = null;
				} else {
					regexp += mask.charAt(i);
				}
			} else if(mask.charAt(i) == 'X'){
				regexp += 'X';
				this.viewMask += '_';
			} else if(mask.charAt(i) == '9' || mask.charAt(i) == 'L' || mask.charAt(i) == 'l' || mask.charAt(i) == 'A') {
				this.viewMask += '_';
				this.maskArray[mai] = mask.charAt(i);
				mai++;
			} else {
				this.viewMask += mask.charAt(i);
				this.maskArray[mai] = mask.charAt(i);
				mai++;
			}
		}
		this.specialChars = this.viewMask.replace(/(L|l|9|A|_|X)/g,'');
		this.getValidatedKey = function(keyCode, cursorPosition) {
			var maskKey = this.maskArray[cursorPosition.start];
			if(maskKey == '9'){
				return keyCode.pressedKey.match(/[0-9]/);
			} else if(maskKey == 'L'){
				return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toUpperCase(): null;
			} else if(maskKey == 'l'){
				return (keyCode.pressedKey.match(/[A-Za-z]/))? keyCode.pressedKey.toLowerCase(): null;
			} else {
				if(maskKey == 'A'){
					return keyCode.pressedKey.match(/[A-Za-z0-9]/);
				} else {
					return (this.maskArray[cursorPosition.start].length > 1)? keyCode.pressedKey.match(new RegExp(maskKey)): null;
				}
			}
		};
		this.isValidValue = function(input){
			return input.value.indexOf('_') <= -1;
		};
	},
	KeyCode: function(onKeyDownEvent) {
		this.onKeyDownEvent = onKeyDownEvent;
		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;
		this.pressedKey = String.fromCharCode(this.unicode);
	},
	CursorPosition: function(start, end, range, previousValue) {
		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 feature to RegExp object
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');
	};
}

-----Original Message-----
From: Adam Winer [mailto:awiner@gmail.com]
Sent: Wednesday, June 06, 2007 8:26 PM
To: MyFaces Discussion
Subject: Re: [Trinidad] Input Text Format That Uses A Mask


Trinidad already has a validateRegExp validator, FWIW,
which attaches both client-side and server-side validation, but
has no mask functionality.  The Tomahawk validator is just a Java
JSF Validator, no client-side functionality, right?

What this masking thing adds is:
-  a simpler syntax for expressing masking.  For example,
 to do a phone number in regexp, you'd have to write something
like:
  \(\d\d\d\)-\d\d\d-\d\d\d\d
instead of:
  (999)-999-9999
- keydown/blur/focus handling so that the parts of the
  mask that are "fixed" can automatically be inserted
  and skipped over.

onblur, I imagine, is responsible for reporting errors.
That part of this should definitely be hooked into the
existing Trinidad client-side validation - which isn't
just alerts anymore thanks to Dan Robinson, but does
need a final tweak to be onblur instead of onsubmit,
at least for INLINE style.

That leaves keydown/focus.  One way this might be
implemented is having an optional method on the
JS validator instances that, if present, will get called
with the relevant DOM form element.  At that point,
the validator could attach any keydown/blur/focus
handling that it wants to.  The framework would handle
blur in general, the mask validator would just need to
attach keydown/focus.

-- Adam




On 6/6/07, Mike Kienenberger <mk...@gmail.com> wrote:
> How does this compare to validateRegExpr in Tomahawk, particularly if
> it becomes a validator instead of a component?
>
> http://myfaces.apache.org/tomahawk/validateRegExpr.html
>
> On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > Point well taken! The component should extend UIXInput instead and renamed CoreInputMask. Are you are proposing to change this into a validator or converter instead of a component extension? If it was to use a converter/validator at what point would it append the JS event calls (onkeydown, onblur, onfocus)? As of yet it does not address server-side validation, but it would be fairly easy to implement. Currently, using the example of a (999)999-9999 mask, and an input of (415)555-1212 the bean would see exactly what the user input i.e. (415)555-1212 If a converter/validator was to be used it would be simple enough to strip the mask characters. I would assume that it would be best to have this as an option because it may be desirable to maintain the mask?
> >
> >
> >
> > -----Original Message-----
> > From: Adam Winer [mailto:awiner@gmail.com]
> > Sent: Wednesday, June 06, 2007 12:03 PM
> > To: MyFaces Discussion
> > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> >
> >
> > A few and questions:
> > - Generally speaking, we don't extend CoreInputText, we just
> >   re-extend UIXInput.  The metadata system supports "includes"
> >   for generation, so you don't have to cut-and-paste that much.
> >   One good reason, in this case, is that I assume that this
> >   component doesn't support <TEXTAREA>, just <INPUT> -
> >   so you don't want "rows" or "wrap".
> > - I'd love to see this as a converter or validator tag that can be
> >   added to an ordinary af:inputText.  We'd need a bit of beefing
> >   up of our client-side code JS framework for validators, but
> >   that'd be worthwhile.
> > - What's the server-side model look like?  E.g., when you
> >    have (999)999-9999, does your bean see strings like
> >    (415)555-1212, or do you get 4155551212?  Is there server-side
> >    validation to double-check the mask was applied?
> > - If this is a component, I think CoreInputTextMasked might
> >   be clearer, if the property is named "mask".
> >
> > -- Adam
> >
> >
> >
> > On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > > Thanks for the info Adam!
> > >
> > > The component (CoreInputTextFormat) logic is fairly simple and could be directly integrated into the CoreInputText, if desired. It extends CoreInputText and adds two extra PropertyKeys: "mask" and "clearWhenInvalid". The "mask" attribute designates the pattern for which will be used to prevent invalid characters at the specified slots. For Example, (999)999-9999 would be displayed as (___)___-____ allowing only numeric values to be entered where underscores are present (see examples below for a more detailed overview). The "clearWhenInvalid" is an option to clear the contents (onblur) of the input field when it does not meet the mask pattern requirements- default is currently true. The only other logic contained in the component is used to make the JS calls: onblur, onfocus, and onkeydown. The client script is contained in a namespace called "CoreInputTextFormat" so none of the functions will interfere with other Trinidad scripts (as you suggested in TRINIDAD-37 it would be nice if we had a Trinidad namespace that could register component level namespaces!). It does however add a prototype extension to RegExp to allow RegExp.escape(someText) preventing recompilation of the escape expression. That is it! I don't think there is a significant amount of code to warrant a CLA (client script under 200 lines, component logic is trivial). Let me know what your thoughts on all of this!
> > >
> > > Mask Individual Character Usage and Reserved Characters:
> > > 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
> > > All other characters are assumed to be "special" characters used to mask the input component
> > >
> > > Examples:
> > > (999)999-9999
> > >         only numeric values can be entered where the character position value is 9. Parenthesis and dash are non-editable/mask characters.
> > > 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.
> > >
> > > -----Original Message-----
> > > From: Adam Winer [mailto:awiner@gmail.com]
> > > Sent: Tuesday, June 05, 2007 7:09 PM
> > > To: MyFaces Discussion
> > > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> > >
> > >
> > > Roughly speaking, you:
> > > - Create an issue on JIRA
> > > - Attach a patch
> > > - If it's a significant quantity of code, file a CLA
> > >   http://www.apache.org/licenses/icla.txt
> > >
> > > It's also generally a good thing to talk over the
> > > design first.  I'd thing it'd be great if this were part of
> > > the client-side validation code, instead of just its
> > > own code.  I think getting this issue fixed:
> > > http://issues.apache.org/jira/browse/TRINIDAD-37
> > > ... would be important for that.
> > >
> > > I'd love to see this functionality!
> > >
> > > -- Adam
> > >
> > >
> > > On 6/5/07, William Hoover <wh...@nemours.org> wrote:
> > > >
> > > >
> > > >
> > > > Hello all,
> > > > I have created a Trinidad component that allows input text boxes to have a
> > > > user defined mask for entries on the client (similar to Atlas MaskEdit
> > > > <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> > > > would like to know what the process/procedure is to commit this component to
> > > > the sandbox?
> > >
> > >
> >
> >
>


Re: [Trinidad] Input Text Format That Uses A Mask

Posted by Adam Winer <aw...@gmail.com>.
Trinidad already has a validateRegExp validator, FWIW,
which attaches both client-side and server-side validation, but
has no mask functionality.  The Tomahawk validator is just a Java
JSF Validator, no client-side functionality, right?

What this masking thing adds is:
-  a simpler syntax for expressing masking.  For example,
 to do a phone number in regexp, you'd have to write something
like:
  \(\d\d\d\)-\d\d\d-\d\d\d\d
instead of:
  (999)-999-9999
- keydown/blur/focus handling so that the parts of the
  mask that are "fixed" can automatically be inserted
  and skipped over.

onblur, I imagine, is responsible for reporting errors.
That part of this should definitely be hooked into the
existing Trinidad client-side validation - which isn't
just alerts anymore thanks to Dan Robinson, but does
need a final tweak to be onblur instead of onsubmit,
at least for INLINE style.

That leaves keydown/focus.  One way this might be
implemented is having an optional method on the
JS validator instances that, if present, will get called
with the relevant DOM form element.  At that point,
the validator could attach any keydown/blur/focus
handling that it wants to.  The framework would handle
blur in general, the mask validator would just need to
attach keydown/focus.

-- Adam




On 6/6/07, Mike Kienenberger <mk...@gmail.com> wrote:
> How does this compare to validateRegExpr in Tomahawk, particularly if
> it becomes a validator instead of a component?
>
> http://myfaces.apache.org/tomahawk/validateRegExpr.html
>
> On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > Point well taken! The component should extend UIXInput instead and renamed CoreInputMask. Are you are proposing to change this into a validator or converter instead of a component extension? If it was to use a converter/validator at what point would it append the JS event calls (onkeydown, onblur, onfocus)? As of yet it does not address server-side validation, but it would be fairly easy to implement. Currently, using the example of a (999)999-9999 mask, and an input of (415)555-1212 the bean would see exactly what the user input i.e. (415)555-1212 If a converter/validator was to be used it would be simple enough to strip the mask characters. I would assume that it would be best to have this as an option because it may be desirable to maintain the mask?
> >
> >
> >
> > -----Original Message-----
> > From: Adam Winer [mailto:awiner@gmail.com]
> > Sent: Wednesday, June 06, 2007 12:03 PM
> > To: MyFaces Discussion
> > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> >
> >
> > A few and questions:
> > - Generally speaking, we don't extend CoreInputText, we just
> >   re-extend UIXInput.  The metadata system supports "includes"
> >   for generation, so you don't have to cut-and-paste that much.
> >   One good reason, in this case, is that I assume that this
> >   component doesn't support <TEXTAREA>, just <INPUT> -
> >   so you don't want "rows" or "wrap".
> > - I'd love to see this as a converter or validator tag that can be
> >   added to an ordinary af:inputText.  We'd need a bit of beefing
> >   up of our client-side code JS framework for validators, but
> >   that'd be worthwhile.
> > - What's the server-side model look like?  E.g., when you
> >    have (999)999-9999, does your bean see strings like
> >    (415)555-1212, or do you get 4155551212?  Is there server-side
> >    validation to double-check the mask was applied?
> > - If this is a component, I think CoreInputTextMasked might
> >   be clearer, if the property is named "mask".
> >
> > -- Adam
> >
> >
> >
> > On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > > Thanks for the info Adam!
> > >
> > > The component (CoreInputTextFormat) logic is fairly simple and could be directly integrated into the CoreInputText, if desired. It extends CoreInputText and adds two extra PropertyKeys: "mask" and "clearWhenInvalid". The "mask" attribute designates the pattern for which will be used to prevent invalid characters at the specified slots. For Example, (999)999-9999 would be displayed as (___)___-____ allowing only numeric values to be entered where underscores are present (see examples below for a more detailed overview). The "clearWhenInvalid" is an option to clear the contents (onblur) of the input field when it does not meet the mask pattern requirements- default is currently true. The only other logic contained in the component is used to make the JS calls: onblur, onfocus, and onkeydown. The client script is contained in a namespace called "CoreInputTextFormat" so none of the functions will interfere with other Trinidad scripts (as you suggested in TRINIDAD-37 it would be nice if we had a Trinidad namespace that could register component level namespaces!). It does however add a prototype extension to RegExp to allow RegExp.escape(someText) preventing recompilation of the escape expression. That is it! I don't think there is a significant amount of code to warrant a CLA (client script under 200 lines, component logic is trivial). Let me know what your thoughts on all of this!
> > >
> > > Mask Individual Character Usage and Reserved Characters:
> > > 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
> > > All other characters are assumed to be "special" characters used to mask the input component
> > >
> > > Examples:
> > > (999)999-9999
> > >         only numeric values can be entered where the character position value is 9. Parenthesis and dash are non-editable/mask characters.
> > > 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.
> > >
> > > -----Original Message-----
> > > From: Adam Winer [mailto:awiner@gmail.com]
> > > Sent: Tuesday, June 05, 2007 7:09 PM
> > > To: MyFaces Discussion
> > > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> > >
> > >
> > > Roughly speaking, you:
> > > - Create an issue on JIRA
> > > - Attach a patch
> > > - If it's a significant quantity of code, file a CLA
> > >   http://www.apache.org/licenses/icla.txt
> > >
> > > It's also generally a good thing to talk over the
> > > design first.  I'd thing it'd be great if this were part of
> > > the client-side validation code, instead of just its
> > > own code.  I think getting this issue fixed:
> > > http://issues.apache.org/jira/browse/TRINIDAD-37
> > > ... would be important for that.
> > >
> > > I'd love to see this functionality!
> > >
> > > -- Adam
> > >
> > >
> > > On 6/5/07, William Hoover <wh...@nemours.org> wrote:
> > > >
> > > >
> > > >
> > > > Hello all,
> > > > I have created a Trinidad component that allows input text boxes to have a
> > > > user defined mask for entries on the client (similar to Atlas MaskEdit
> > > > <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> > > > would like to know what the process/procedure is to commit this component to
> > > > the sandbox?
> > >
> > >
> >
> >
>

RE: [Trinidad] Input Text Format That Uses A Mask

Posted by William Hoover <wh...@nemours.org>.
Very similar, except this validator would have to add JS calls to the onkeydown event of the component its validating. I'm not sure if this is a good idea? 

Atlas Example: <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>

-----Original Message-----
From: Mike Kienenberger [mailto:mkienenb@gmail.com]
Sent: Wednesday, June 06, 2007 2:40 PM
To: MyFaces Discussion
Subject: Re: [Trinidad] Input Text Format That Uses A Mask


How does this compare to validateRegExpr in Tomahawk, particularly if
it becomes a validator instead of a component?

http://myfaces.apache.org/tomahawk/validateRegExpr.html

On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> Point well taken! The component should extend UIXInput instead and renamed CoreInputMask. Are you are proposing to change this into a validator or converter instead of a component extension? If it was to use a converter/validator at what point would it append the JS event calls (onkeydown, onblur, onfocus)? As of yet it does not address server-side validation, but it would be fairly easy to implement. Currently, using the example of a (999)999-9999 mask, and an input of (415)555-1212 the bean would see exactly what the user input i.e. (415)555-1212 If a converter/validator was to be used it would be simple enough to strip the mask characters. I would assume that it would be best to have this as an option because it may be desirable to maintain the mask?
>
>
>
> -----Original Message-----
> From: Adam Winer [mailto:awiner@gmail.com]
> Sent: Wednesday, June 06, 2007 12:03 PM
> To: MyFaces Discussion
> Subject: Re: [Trinidad] Input Text Format That Uses A Mask
>
>
> A few and questions:
> - Generally speaking, we don't extend CoreInputText, we just
>   re-extend UIXInput.  The metadata system supports "includes"
>   for generation, so you don't have to cut-and-paste that much.
>   One good reason, in this case, is that I assume that this
>   component doesn't support <TEXTAREA>, just <INPUT> -
>   so you don't want "rows" or "wrap".
> - I'd love to see this as a converter or validator tag that can be
>   added to an ordinary af:inputText.  We'd need a bit of beefing
>   up of our client-side code JS framework for validators, but
>   that'd be worthwhile.
> - What's the server-side model look like?  E.g., when you
>    have (999)999-9999, does your bean see strings like
>    (415)555-1212, or do you get 4155551212?  Is there server-side
>    validation to double-check the mask was applied?
> - If this is a component, I think CoreInputTextMasked might
>   be clearer, if the property is named "mask".
>
> -- Adam
>
>
>
> On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > Thanks for the info Adam!
> >
> > The component (CoreInputTextFormat) logic is fairly simple and could be directly integrated into the CoreInputText, if desired. It extends CoreInputText and adds two extra PropertyKeys: "mask" and "clearWhenInvalid". The "mask" attribute designates the pattern for which will be used to prevent invalid characters at the specified slots. For Example, (999)999-9999 would be displayed as (___)___-____ allowing only numeric values to be entered where underscores are present (see examples below for a more detailed overview). The "clearWhenInvalid" is an option to clear the contents (onblur) of the input field when it does not meet the mask pattern requirements- default is currently true. The only other logic contained in the component is used to make the JS calls: onblur, onfocus, and onkeydown. The client script is contained in a namespace called "CoreInputTextFormat" so none of the functions will interfere with other Trinidad scripts (as you suggested in TRINIDAD-37 it would be nice if we had a Trinidad namespace that could register component level namespaces!). It does however add a prototype extension to RegExp to allow RegExp.escape(someText) preventing recompilation of the escape expression. That is it! I don't think there is a significant amount of code to warrant a CLA (client script under 200 lines, component logic is trivial). Let me know what your thoughts on all of this!
> >
> > Mask Individual Character Usage and Reserved Characters:
> > 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
> > All other characters are assumed to be "special" characters used to mask the input component
> >
> > Examples:
> > (999)999-9999
> >         only numeric values can be entered where the character position value is 9. Parenthesis and dash are non-editable/mask characters.
> > 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.
> >
> > -----Original Message-----
> > From: Adam Winer [mailto:awiner@gmail.com]
> > Sent: Tuesday, June 05, 2007 7:09 PM
> > To: MyFaces Discussion
> > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> >
> >
> > Roughly speaking, you:
> > - Create an issue on JIRA
> > - Attach a patch
> > - If it's a significant quantity of code, file a CLA
> >   http://www.apache.org/licenses/icla.txt
> >
> > It's also generally a good thing to talk over the
> > design first.  I'd thing it'd be great if this were part of
> > the client-side validation code, instead of just its
> > own code.  I think getting this issue fixed:
> > http://issues.apache.org/jira/browse/TRINIDAD-37
> > ... would be important for that.
> >
> > I'd love to see this functionality!
> >
> > -- Adam
> >
> >
> > On 6/5/07, William Hoover <wh...@nemours.org> wrote:
> > >
> > >
> > >
> > > Hello all,
> > > I have created a Trinidad component that allows input text boxes to have a
> > > user defined mask for entries on the client (similar to Atlas MaskEdit
> > > <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> > > would like to know what the process/procedure is to commit this component to
> > > the sandbox?
> >
> >
>
>


Re: [Trinidad] Input Text Format That Uses A Mask

Posted by Mike Kienenberger <mk...@gmail.com>.
How does this compare to validateRegExpr in Tomahawk, particularly if
it becomes a validator instead of a component?

http://myfaces.apache.org/tomahawk/validateRegExpr.html

On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> Point well taken! The component should extend UIXInput instead and renamed CoreInputMask. Are you are proposing to change this into a validator or converter instead of a component extension? If it was to use a converter/validator at what point would it append the JS event calls (onkeydown, onblur, onfocus)? As of yet it does not address server-side validation, but it would be fairly easy to implement. Currently, using the example of a (999)999-9999 mask, and an input of (415)555-1212 the bean would see exactly what the user input i.e. (415)555-1212 If a converter/validator was to be used it would be simple enough to strip the mask characters. I would assume that it would be best to have this as an option because it may be desirable to maintain the mask?
>
>
>
> -----Original Message-----
> From: Adam Winer [mailto:awiner@gmail.com]
> Sent: Wednesday, June 06, 2007 12:03 PM
> To: MyFaces Discussion
> Subject: Re: [Trinidad] Input Text Format That Uses A Mask
>
>
> A few and questions:
> - Generally speaking, we don't extend CoreInputText, we just
>   re-extend UIXInput.  The metadata system supports "includes"
>   for generation, so you don't have to cut-and-paste that much.
>   One good reason, in this case, is that I assume that this
>   component doesn't support <TEXTAREA>, just <INPUT> -
>   so you don't want "rows" or "wrap".
> - I'd love to see this as a converter or validator tag that can be
>   added to an ordinary af:inputText.  We'd need a bit of beefing
>   up of our client-side code JS framework for validators, but
>   that'd be worthwhile.
> - What's the server-side model look like?  E.g., when you
>    have (999)999-9999, does your bean see strings like
>    (415)555-1212, or do you get 4155551212?  Is there server-side
>    validation to double-check the mask was applied?
> - If this is a component, I think CoreInputTextMasked might
>   be clearer, if the property is named "mask".
>
> -- Adam
>
>
>
> On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> > Thanks for the info Adam!
> >
> > The component (CoreInputTextFormat) logic is fairly simple and could be directly integrated into the CoreInputText, if desired. It extends CoreInputText and adds two extra PropertyKeys: "mask" and "clearWhenInvalid". The "mask" attribute designates the pattern for which will be used to prevent invalid characters at the specified slots. For Example, (999)999-9999 would be displayed as (___)___-____ allowing only numeric values to be entered where underscores are present (see examples below for a more detailed overview). The "clearWhenInvalid" is an option to clear the contents (onblur) of the input field when it does not meet the mask pattern requirements- default is currently true. The only other logic contained in the component is used to make the JS calls: onblur, onfocus, and onkeydown. The client script is contained in a namespace called "CoreInputTextFormat" so none of the functions will interfere with other Trinidad scripts (as you suggested in TRINIDAD-37 it would be nice if we had a Trinidad namespace that could register component level namespaces!). It does however add a prototype extension to RegExp to allow RegExp.escape(someText) preventing recompilation of the escape expression. That is it! I don't think there is a significant amount of code to warrant a CLA (client script under 200 lines, component logic is trivial). Let me know what your thoughts on all of this!
> >
> > Mask Individual Character Usage and Reserved Characters:
> > 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
> > All other characters are assumed to be "special" characters used to mask the input component
> >
> > Examples:
> > (999)999-9999
> >         only numeric values can be entered where the character position value is 9. Parenthesis and dash are non-editable/mask characters.
> > 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.
> >
> > -----Original Message-----
> > From: Adam Winer [mailto:awiner@gmail.com]
> > Sent: Tuesday, June 05, 2007 7:09 PM
> > To: MyFaces Discussion
> > Subject: Re: [Trinidad] Input Text Format That Uses A Mask
> >
> >
> > Roughly speaking, you:
> > - Create an issue on JIRA
> > - Attach a patch
> > - If it's a significant quantity of code, file a CLA
> >   http://www.apache.org/licenses/icla.txt
> >
> > It's also generally a good thing to talk over the
> > design first.  I'd thing it'd be great if this were part of
> > the client-side validation code, instead of just its
> > own code.  I think getting this issue fixed:
> > http://issues.apache.org/jira/browse/TRINIDAD-37
> > ... would be important for that.
> >
> > I'd love to see this functionality!
> >
> > -- Adam
> >
> >
> > On 6/5/07, William Hoover <wh...@nemours.org> wrote:
> > >
> > >
> > >
> > > Hello all,
> > > I have created a Trinidad component that allows input text boxes to have a
> > > user defined mask for entries on the client (similar to Atlas MaskEdit
> > > <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> > > would like to know what the process/procedure is to commit this component to
> > > the sandbox?
> >
> >
>
>

RE: [Trinidad] Input Text Format That Uses A Mask

Posted by William Hoover <wh...@nemours.org>.
Point well taken! The component should extend UIXInput instead and renamed CoreInputMask. Are you are proposing to change this into a validator or converter instead of a component extension? If it was to use a converter/validator at what point would it append the JS event calls (onkeydown, onblur, onfocus)? As of yet it does not address server-side validation, but it would be fairly easy to implement. Currently, using the example of a (999)999-9999 mask, and an input of (415)555-1212 the bean would see exactly what the user input i.e. (415)555-1212 If a converter/validator was to be used it would be simple enough to strip the mask characters. I would assume that it would be best to have this as an option because it may be desirable to maintain the mask?



-----Original Message-----
From: Adam Winer [mailto:awiner@gmail.com]
Sent: Wednesday, June 06, 2007 12:03 PM
To: MyFaces Discussion
Subject: Re: [Trinidad] Input Text Format That Uses A Mask


A few and questions:
- Generally speaking, we don't extend CoreInputText, we just
  re-extend UIXInput.  The metadata system supports "includes"
  for generation, so you don't have to cut-and-paste that much.
  One good reason, in this case, is that I assume that this
  component doesn't support <TEXTAREA>, just <INPUT> -
  so you don't want "rows" or "wrap".
- I'd love to see this as a converter or validator tag that can be
  added to an ordinary af:inputText.  We'd need a bit of beefing
  up of our client-side code JS framework for validators, but
  that'd be worthwhile.
- What's the server-side model look like?  E.g., when you
   have (999)999-9999, does your bean see strings like
   (415)555-1212, or do you get 4155551212?  Is there server-side
   validation to double-check the mask was applied?
- If this is a component, I think CoreInputTextMasked might
  be clearer, if the property is named "mask".

-- Adam



On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> Thanks for the info Adam!
>
> The component (CoreInputTextFormat) logic is fairly simple and could be directly integrated into the CoreInputText, if desired. It extends CoreInputText and adds two extra PropertyKeys: "mask" and "clearWhenInvalid". The "mask" attribute designates the pattern for which will be used to prevent invalid characters at the specified slots. For Example, (999)999-9999 would be displayed as (___)___-____ allowing only numeric values to be entered where underscores are present (see examples below for a more detailed overview). The "clearWhenInvalid" is an option to clear the contents (onblur) of the input field when it does not meet the mask pattern requirements- default is currently true. The only other logic contained in the component is used to make the JS calls: onblur, onfocus, and onkeydown. The client script is contained in a namespace called "CoreInputTextFormat" so none of the functions will interfere with other Trinidad scripts (as you suggested in TRINIDAD-37 it would be nice if we had a Trinidad namespace that could register component level namespaces!). It does however add a prototype extension to RegExp to allow RegExp.escape(someText) preventing recompilation of the escape expression. That is it! I don't think there is a significant amount of code to warrant a CLA (client script under 200 lines, component logic is trivial). Let me know what your thoughts on all of this!
>
> Mask Individual Character Usage and Reserved Characters:
> 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
> All other characters are assumed to be "special" characters used to mask the input component
>
> Examples:
> (999)999-9999
>         only numeric values can be entered where the character position value is 9. Parenthesis and dash are non-editable/mask characters.
> 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.
>
> -----Original Message-----
> From: Adam Winer [mailto:awiner@gmail.com]
> Sent: Tuesday, June 05, 2007 7:09 PM
> To: MyFaces Discussion
> Subject: Re: [Trinidad] Input Text Format That Uses A Mask
>
>
> Roughly speaking, you:
> - Create an issue on JIRA
> - Attach a patch
> - If it's a significant quantity of code, file a CLA
>   http://www.apache.org/licenses/icla.txt
>
> It's also generally a good thing to talk over the
> design first.  I'd thing it'd be great if this were part of
> the client-side validation code, instead of just its
> own code.  I think getting this issue fixed:
> http://issues.apache.org/jira/browse/TRINIDAD-37
> ... would be important for that.
>
> I'd love to see this functionality!
>
> -- Adam
>
>
> On 6/5/07, William Hoover <wh...@nemours.org> wrote:
> >
> >
> >
> > Hello all,
> > I have created a Trinidad component that allows input text boxes to have a
> > user defined mask for entries on the client (similar to Atlas MaskEdit
> > <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> > would like to know what the process/procedure is to commit this component to
> > the sandbox?
>
>


Re: [Trinidad] Input Text Format That Uses A Mask

Posted by Adam Winer <aw...@gmail.com>.
A few and questions:
- Generally speaking, we don't extend CoreInputText, we just
  re-extend UIXInput.  The metadata system supports "includes"
  for generation, so you don't have to cut-and-paste that much.
  One good reason, in this case, is that I assume that this
  component doesn't support <TEXTAREA>, just <INPUT> -
  so you don't want "rows" or "wrap".
- I'd love to see this as a converter or validator tag that can be
  added to an ordinary af:inputText.  We'd need a bit of beefing
  up of our client-side code JS framework for validators, but
  that'd be worthwhile.
- What's the server-side model look like?  E.g., when you
   have (999)999-9999, does your bean see strings like
   (415)555-1212, or do you get 4155551212?  Is there server-side
   validation to double-check the mask was applied?
- If this is a component, I think CoreInputTextMasked might
  be clearer, if the property is named "mask".

-- Adam



On 6/6/07, William Hoover <wh...@nemours.org> wrote:
> Thanks for the info Adam!
>
> The component (CoreInputTextFormat) logic is fairly simple and could be directly integrated into the CoreInputText, if desired. It extends CoreInputText and adds two extra PropertyKeys: "mask" and "clearWhenInvalid". The "mask" attribute designates the pattern for which will be used to prevent invalid characters at the specified slots. For Example, (999)999-9999 would be displayed as (___)___-____ allowing only numeric values to be entered where underscores are present (see examples below for a more detailed overview). The "clearWhenInvalid" is an option to clear the contents (onblur) of the input field when it does not meet the mask pattern requirements- default is currently true. The only other logic contained in the component is used to make the JS calls: onblur, onfocus, and onkeydown. The client script is contained in a namespace called "CoreInputTextFormat" so none of the functions will interfere with other Trinidad scripts (as you suggested in TRINIDAD-37 it would be nice if we had a Trinidad namespace that could register component level namespaces!). It does however add a prototype extension to RegExp to allow RegExp.escape(someText) preventing recompilation of the escape expression. That is it! I don't think there is a significant amount of code to warrant a CLA (client script under 200 lines, component logic is trivial). Let me know what your thoughts on all of this!
>
> Mask Individual Character Usage and Reserved Characters:
> 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
> All other characters are assumed to be "special" characters used to mask the input component
>
> Examples:
> (999)999-9999
>         only numeric values can be entered where the character position value is 9. Parenthesis and dash are non-editable/mask characters.
> 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.
>
> -----Original Message-----
> From: Adam Winer [mailto:awiner@gmail.com]
> Sent: Tuesday, June 05, 2007 7:09 PM
> To: MyFaces Discussion
> Subject: Re: [Trinidad] Input Text Format That Uses A Mask
>
>
> Roughly speaking, you:
> - Create an issue on JIRA
> - Attach a patch
> - If it's a significant quantity of code, file a CLA
>   http://www.apache.org/licenses/icla.txt
>
> It's also generally a good thing to talk over the
> design first.  I'd thing it'd be great if this were part of
> the client-side validation code, instead of just its
> own code.  I think getting this issue fixed:
> http://issues.apache.org/jira/browse/TRINIDAD-37
> ... would be important for that.
>
> I'd love to see this functionality!
>
> -- Adam
>
>
> On 6/5/07, William Hoover <wh...@nemours.org> wrote:
> >
> >
> >
> > Hello all,
> > I have created a Trinidad component that allows input text boxes to have a
> > user defined mask for entries on the client (similar to Atlas MaskEdit
> > <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> > would like to know what the process/procedure is to commit this component to
> > the sandbox?
>
>

RE: [Trinidad] Input Text Format That Uses A Mask

Posted by William Hoover <wh...@nemours.org>.
Thanks for the info Adam!

The component (CoreInputTextFormat) logic is fairly simple and could be directly integrated into the CoreInputText, if desired. It extends CoreInputText and adds two extra PropertyKeys: "mask" and "clearWhenInvalid". The "mask" attribute designates the pattern for which will be used to prevent invalid characters at the specified slots. For Example, (999)999-9999 would be displayed as (___)___-____ allowing only numeric values to be entered where underscores are present (see examples below for a more detailed overview). The "clearWhenInvalid" is an option to clear the contents (onblur) of the input field when it does not meet the mask pattern requirements- default is currently true. The only other logic contained in the component is used to make the JS calls: onblur, onfocus, and onkeydown. The client script is contained in a namespace called "CoreInputTextFormat" so none of the functions will interfere with other Trinidad scripts (as you suggested in TRINIDAD-37 it would be nice if we had a Trinidad namespace that could register component level namespaces!). It does however add a prototype extension to RegExp to allow RegExp.escape(someText) preventing recompilation of the escape expression. That is it! I don't think there is a significant amount of code to warrant a CLA (client script under 200 lines, component logic is trivial). Let me know what your thoughts on all of this!

Mask Individual Character Usage and Reserved Characters:
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
All other characters are assumed to be "special" characters used to mask the input component

Examples:
(999)999-9999 
	only numeric values can be entered where the character position value is 9. Parenthesis and dash are non-editable/mask characters.
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.

-----Original Message-----
From: Adam Winer [mailto:awiner@gmail.com]
Sent: Tuesday, June 05, 2007 7:09 PM
To: MyFaces Discussion
Subject: Re: [Trinidad] Input Text Format That Uses A Mask


Roughly speaking, you:
- Create an issue on JIRA
- Attach a patch
- If it's a significant quantity of code, file a CLA
  http://www.apache.org/licenses/icla.txt

It's also generally a good thing to talk over the
design first.  I'd thing it'd be great if this were part of
the client-side validation code, instead of just its
own code.  I think getting this issue fixed:
http://issues.apache.org/jira/browse/TRINIDAD-37
... would be important for that.

I'd love to see this functionality!

-- Adam


On 6/5/07, William Hoover <wh...@nemours.org> wrote:
>
>
>
> Hello all,
> I have created a Trinidad component that allows input text boxes to have a
> user defined mask for entries on the client (similar to Atlas MaskEdit
> <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> would like to know what the process/procedure is to commit this component to
> the sandbox?


Re: [Trinidad] Input Text Format That Uses A Mask

Posted by Adam Winer <aw...@gmail.com>.
Roughly speaking, you:
- Create an issue on JIRA
- Attach a patch
- If it's a significant quantity of code, file a CLA
  http://www.apache.org/licenses/icla.txt

It's also generally a good thing to talk over the
design first.  I'd thing it'd be great if this were part of
the client-side validation code, instead of just its
own code.  I think getting this issue fixed:
http://issues.apache.org/jira/browse/TRINIDAD-37
... would be important for that.

I'd love to see this functionality!

-- Adam


On 6/5/07, William Hoover <wh...@nemours.org> wrote:
>
>
>
> Hello all,
> I have created a Trinidad component that allows input text boxes to have a
> user defined mask for entries on the client (similar to Atlas MaskEdit
> <http://www.fci.com.br/maskedit/MaskEdit/MaskEdit.aspx>). I
> would like to know what the process/procedure is to commit this component to
> the sandbox?