PDA

View Full Version : [0.5] Ext.ux.form.MaskFormatter - a mask formatter for form fields



daniel.rochetti
2 Aug 2007, 9:00 AM
Hey you all!

I've implemented a mask formatter for input fields based on the existing class of the Java Language called javax.swing.text.MaskFormatter (http://java.sun.com/javase/6/docs/api/javax/swing/text/MaskFormatter.html)

This is the first version of the code so I'd suggest a lot of testing and plase, send me feedback.
There is already a TODO list:
- support other features of the Java's MaskFormatter as: upper/lower case characters, validCharacters, hex characters;
- better documentation of the code
- testing, testing, testing, testing, on and on... (tested only on Firefox 2 and IE 6)
- better example demo (there is a demo on the attached zip file, but it's poor. Attention, it doesn't include the ext library cause it exceeds the attachement size limit, include it yourself. I'm using the 1.1 version)

I lot of people have been asking for a feature like this. I agree with them, the client (the user) loves masking of field, they always ask for it, so I brought here a simple way of doing it, hope you like it!

regards,

see yaaaa!

code:

Ext.namespace("Ext.ux.form");

/**
* @class Ext.ux.form.MaskFormatter
* @constructor
*
* MaskFormatter is used to format and edit strings in form fields.
*
* @param {Object} config Configuration options
*/
Ext.ux.form.MaskFormatter = function(config) {

var mask = config["mask"];
var placeholder = config["placeholder"] || "_";
var validCharacters = config["validCharacters"];
var field = null;

// private final
var KEY_RANGES = {
numeric: [48, 57],
padnum: [96, 105],
characters: [65, 90],
all: [0, 255]
};

// private
var isInRange = function(charCode, range) {
return charCode >= range[0] && charCode <= range[1];
};

// private
// TODO: support other wildcards, like: A (char or number), U (uppercase char), L (lowercase char), ' (escape)
var getRange = function(wildcard) {
switch (wildcard) {
case '#': return [KEY_RANGES["numeric"]];
case '?': return [KEY_RANGES["characters"]];
case '*': return [KEY_RANGES["all"]];
}
return null;
};

// private
var isMaskChar = function(chr) {
return getRange(chr) != null;
};

// private
var getDefaultString = function() {
var str = "";
var mask = config["mask"];
for(var i = 0; i < mask.length; i++) {
var chr = mask.charAt(i);
str += isMaskChar(chr) ? placeholder : chr;
}
return str;
};

// private
var doBackspace = function() {
doDelete();
moveCaret(-1);
};

// private
var doDelete = function() {
var position = getCaretPosition().left;

var left = field.dom.value.substr(0, position);
var right = field.dom.value.substr(position + 1, field.dom.value.length - 1);

field.dom.value = left + placeholder + right;
setSelection(position);
};

// private
var getCaretPosition = function() {
var left, right;

if (!field.dom) {
// unexpected
return null;
}

var fieldEl = field.dom;
if (fieldEl.createTextRange) {
var range = document.selection.createRange().duplicate();
range.moveEnd("character", fieldEl.value.length);

if (!range.text) {
left = fieldEl.value.length;
} else {
left = fieldEl.value.lastIndexOf(range.text);
}

range = document.selection.createRange().duplicate();
range.moveStart("character", -(fieldEl.value.length));

right = range.text.length;
} else {
left = fieldEl.selectionStart;
right = fieldEl.selectionEnd;
}

return {left: left, right: right};
};

// private
var setSelection = function(leftPos, rightPos) {
var left = leftPos;
var right = rightPos || left + 1;

if (field.dom.createTextRange) {
var range = field.dom.createTextRange();
range.moveStart("character", left);
range.moveEnd("character", right - field.dom.value.length);
range.select();
} else {
field.dom.setSelectionRange(left, right);
}
};

// private
var doMask = function(key) {
if (isInRange(key, KEY_RANGES["padnum"])) {
key -= 48;
}

var position = getCaretPosition().left;

var ranges = getRange(mask.charAt(position));
var valid = false;

for (var i = 0; i < ranges.length; i++) {
if (isInRange(key, ranges[i])) {
valid = true;
break;
}
}

if (valid) {
var fieldValue = field.dom.value;

var left = fieldValue.substr(0, position);
var right = fieldValue.substr((position + 1), (fieldValue.length - 1));

field.dom.value = left + String.fromCharCode(key) + right;

var previousPosition = position;

do {
position++;
} while(!(isMaskChar(mask.charAt(position))) && (position < fieldValue.length));

if (isMaskChar(mask.charAt(position))) {
setSelection(position);
} else {
setSelection(previousPosition);
}
}
};

// private
var mapKeyToBehavior = function(evt) {
var key = evt.getKey();
switch (key) {
case Ext.EventObject.BACKSPACE:
doBackspace();
break;
case Ext.EventObject.DELETE:
doDelete();
break;
case Ext.EventObject.HOME:
setSelection(0);
break;
case Ext.EventObject.END:
setSelection(field.dom.value.length - 1);
break;
case Ext.EventObject.RIGHT:
moveCaret(1);
break;
case Ext.EventObject.LEFT:
moveCaret(-1);
break;
case Ext.EventObject.TAB:
case Ext.EventObject.ENTER:
return;
default:
doMask(key);
}
evt.stopEvent();
};

// private
var doSelection = function(evt) {
var pos = getCaretPosition().left;

if(pos == field.dom.value.length) {
pos--;
}

if(!isMaskChar(mask.charAt(pos))) {
if (!moveCaret(1)) {
moveCaret(-1);
}
} else {
setSelection(pos);
}
};

// private
var moveCaret = function(step, left) {
var position = left || getCaretPosition().left;

if (step == 0) {
return false;
}

if (position == 0 && step < 0) {
return false;
}

if ((position >= (field.dom.value.length - 1)) && (step > 0)) {
return false;
}

do {
position += step;
} while(!(isMaskChar(mask.charAt(position))) && (position > 0) && (position < field.dom.value.length));

if (!(isMaskChar(mask.charAt(position)))) {
return false;
}

setSelection(position);
return true;
};

return {

/**
* @cfg {String}
*/
mask: mask,

/**
* @cfg {String}
*/
placeholder: placeholder,

/**
* @cfg {String}
*/
validCharacters: validCharacters,

/**
* @param {String/HTMLElement/Element} el The id of the form field,
* a form field HTML reference or an existing form field Element
*/
applyTo: function(element) {
var el = Ext.get(element);
field = el;

var stopEventFunction = function(evt) {
evt.stopEvent();
};

el.on("keydown", mapKeyToBehavior);
el.on("keypress", stopEventFunction);
el.on("keyup", stopEventFunction);
el.on("focus", doSelection);
el.on("click", doSelection);

el.dom["autocomplete"] = "off";
if (!el.dom.value) {
el.dom.value = getDefaultString();
}
}

};

};

daniel.rochetti
2 Aug 2007, 9:03 AM
oh, I forgot something.
Ok, I agree with the ux package for user extension, but we have to keep it organized. I think we should include subpackages inside the ux packages too, or we'll mess the ux package up. Imagine the situation, a lot of things like, widgets, layout things, utilities things, form things, everithing mixed together inside one package, the ux package.
Think about that people. Let's keep it organized and well documented! :)

brian.moeskau
2 Aug 2007, 9:41 AM
Hi Daniel,

Thanks for the contribution! Please add a project page here so more people will find it: http://extjs.com/learn/Ext_Extensions

daniel.rochetti
2 Aug 2007, 10:01 AM
Hi Daniel,

Thanks for the contribution! Please add a project page here so more people will find it: http://extjs.com/learn/Ext_Extensions

Hi!

Ok, I'll do this as soon as I get home later this day. I'm at work right now.
Hmm, here's a simple usage example:


<html>
<body>
<form>
<input type="text" id="isbn" name="isbn" />
</form>
<script type="text/javascript">
Ext.onReady(function() {
var isbnMask = new Ext.ux.form.MaskFormatter({mask: "###-#-####-####-#"});
isbnMask.applyTo("isbn");
});
</script>
</body>
</html>

devnull
2 Aug 2007, 11:24 AM
This is very cool, I would love to use it to format phone numbers.
One problem I have though, would it be possible to tie this into an Ext.form's validation functions, such that the field is only marked as valid if all placeholder characters have been filled in with real characters?
I would also find it desirable to have it select the first editable character upon field focus, but i think that modification is within my abilities.

galdaka
2 Aug 2007, 11:46 AM
Thanks Daniel!!!!

Live example? is good for testing ;)

Thanks in advance,

daniel.rochetti
2 Aug 2007, 11:49 AM
This is very cool, I would love to use it to format phone numbers.
One problem I have though, would it be possible to tie this into an Ext.form's validation functions, such that the field is only marked as valid if all placeholder characters have been filled in with real characters?
I would also find it desirable to have it select the first editable character upon field focus, but i think that modification is within my abilities.

hey dude, hows it goin?
hhhmmm i think that is possible to tie the validation to the masking, just need to think a little to figure out the best way to implement it.
to select the first editable char on focus is quite easy but its not implemented yet. As i said, the code still incomplete yet, but thanks for your feedback!
btw, i think that we should have something like this (masking) inside the ext core, not as a user extension, my extension is a way and suggestion of how to implement it.

devnull
2 Aug 2007, 12:26 PM
the validation may just require using a custom vtype for the field, i will keep looking into that.
Mostly I wanted to pass along an error I am able to replicate, tho its somewhat hard to do. I am able to select all the text in the field if i do it carefully, and if i type anything while the whole lot is selected, firebug pukes this out:


ranges has no properties Ext.ux.form.MaskF... (line 133)
doMask(49)
mapKeyToBehavior(Object browserEvent=Event keydown button=48 type=keydown)Ext.ux.form.MaskF... (line 188)
h(Object browserEvent=Event keydown button=48 type=keydown)ext-all-debug.js (line 1484)
getViewWidth(keydown charCode=0, keyCode=49)ext-base.js (line 12)
[Break on this error] for (var i = 0; i < ranges.length; i++) {

thought it might be helpfull to you B)

daniel.rochetti
2 Aug 2007, 12:37 PM
the validation may just require using a custom vtype for the field, i will keep looking into that.
Mostly I wanted to pass along an error I am able to replicate, tho its somewhat hard to do. I am able to select all the text in the field if i do it carefully, and if i type anything while the whole lot is selected, firebug pukes this out:


ranges has no properties Ext.ux.form.MaskF... (line 133)
doMask(49)
mapKeyToBehavior(Object browserEvent=Event keydown button=48 type=keydown)Ext.ux.form.MaskF... (line 188)
h(Object browserEvent=Event keydown button=48 type=keydown)ext-all-debug.js (line 1484)
getViewWidth(keydown charCode=0, keyCode=49)ext-base.js (line 12)
[Break on this error] for (var i = 0; i < ranges.length; i++) {

thought it might be helpfull to you B)

yeah, im using custom vtypes in my system, now ill try to figure some way out to generate the vtype based on the mask automagically! :)
hhhmmmm the TAB is working on IE6 and the focus is working ok (selecting the first editable char), but its not on Firefox.
The error youve reported is very hard to replicate indeed. I can select all the content in IE using the mouse and when i type no error occurs. In firefox im not able to select all, but ill keep trying!
thanks for the feedback!

daniel.rochetti
2 Aug 2007, 12:43 PM
i just found a bug. if you press the HOME key and the first char is not a mask char (an editable char) it selects the first char anyway, not the first editable char. ill fix this later. i think the same occurs with the END key.
Try using the following mask:
(##) ####-####

galdaka
2 Aug 2007, 1:26 PM
Sorry for my English.

Works fine combined with examples\form\forms.html in Ext 1.0.1 in IE6. See image.

Would be good combine this feature in Ext.form.field like this:



var alpha = new Ext.form.TextField({
vtype:'alpha',
mask:'###.###.###-##'
});
alpha.applyTo('alpha');

ethraza
3 Aug 2007, 10:06 AM
I think that maybe it can be more usefull if it can handle this way to be called:

var alpha = new Ext.form.TextField({
vtype:'alpha',
validator: MaskFormatter(value,'###.###.###-##',this)
});

But extend the field component to accept a mask config option wold be great!

daniel.rochetti
3 Aug 2007, 10:14 AM
I think that maybe it can be more usefull if it can handle this way to be called:

var alpha = new Ext.form.TextField({
vtype:'alpha',
validator: MaskFormatter(value,'###.###.###-##',this)
});

i think that most of us thinbk that way, that masking should be integrated into the form field (in the ext core, take a look at the poll). :)
while we dont have the ideal situation heres a way of handle masking without edit the ext source. Compatible with any version of ext, including ordinary html fields.
i think that the ideal usage would be something like this:


var tf = new Ext.form.TextField({
mask: new Ext.form.MaskFormatter({mask: "(###) ###-####", placeholder: "_"})
});

galdaka
5 Aug 2007, 7:08 AM
Are you working for in future versions will posible this:


mask: new Ext.form.MaskFormatter({mask: "(###) ###-####", placeholder: "_"})

Thanks in advance,

devnull
6 Aug 2007, 10:38 AM
A bit of a bug report here;
a form.reset causes the default string (ie (___)___-____) to no longer be displayed, causing an error when typing in any text after this.
I will look into it as much as i can, but i dont yet know much about extending Ext so i doubt i will get very far.

devnull
8 Aug 2007, 2:39 PM
I have turned the code into an extension of Ext.form.TextField, as well as fixed the bug i posted above and created some preliminary auto-vtype code.


Ext.form.MaskFormattedTextField = function(config){
var defConfig = {
placeholder: "_",
autocomplete: 'off',
mask: "(###)###-####", //default mask is a US 10 digit phone number
};
Ext.applyIf(config,defConfig);
Ext.form.MaskFormattedTextField.superclass.constructor.call(this, config);
};
Ext.extend(Ext.form.MaskFormattedTextField, Ext.form.TextField,{

initEvents : function(){
Ext.form.MaskFormattedTextField.superclass.initEvents.call(this);
this.el.on('keydown',this.mapKeyToBehavior,this);
this.el.on("keypress", this.stopEventFunction,this);
this.el.on("keyup", this.stopEventFunction,this);
//this.el.on("focus", this.doSelection,this); //seems to be ignored
//this.el.on("click", this.doSelection,this); //use this to highlight the first char
},

render: function(ct, position){
if (!this.vtype) {
var regexMask = this.mask.replace(/#/g,"\\d");
regexMask = regexMask.replace(/\(/,"\\(");
regexMask = regexMask.replace(/\)/,"\\)");
this.regex = eval('/^'+regexMask+'$/');
if (this.invalidMessage) {
this.regexText = this.invalidMessage;
} else {
this.regexText = "This field has a required format of " + this.mask;
}
}
Ext.form.MaskFormattedTextField.superclass.render.call(this,ct,position);
},

reset: function(ct, position){
Ext.form.MaskFormattedTextField.superclass.reset.call(this);
this.doSelection();
},

KEY_RANGES : {
numeric: [48, 57],
padnum: [96, 105],
characters: [65, 90],
all: [0, 255]
},

isInRange : function(charCode, range) {
return charCode >= range[0] && charCode <= range[1];
},

// TODO: support other wildcards, like: A (char or number), U (uppercase char), L (lowercase char), ' (escape)
getRange : function(wildcard) {
var temp = [];
switch (wildcard) {
case '#':
temp.push(this.KEY_RANGES["numeric"]);
break;
case '?':
temp.push(this.KEY_RANGES["characters"]);
break;
case '*':
temp.push(this.KEY_RANGES["all"]);
break;
default:
return null;
}
return temp;
},

isMaskChar : function(chr) {
return this.getRange(chr) != null;
},

getDefaultString : function() {
var str = "";
var mask = this.mask;
for(var i = 0; i < mask.length; i++) {
var chr = mask.charAt(i);
str += this.isMaskChar(chr) ? this.placeholder : chr;
}
return str;
},

doBackspace : function() {
this.doDelete();
this.moveCaret(-1);
},

doDelete : function() {
var position = this.getCaretPosition().left;

var left = this.el.dom.value.substr(0, position);
var right = this.el.dom.value.substr(position + 1, this.el.dom.value.length - 1);

this.el.dom.value = left + this.placeholder + right;
this.setSelection(position);
},

getCaretPosition : function() {
var left, right;

if (!this.el.dom) {
// unexpected
return null;
}

var fieldEl = this.el.dom;
if (fieldEl.createTextRange) {
var range = document.selection.createRange().duplicate();
range.moveEnd("character", fieldEl.value.length);

if (!range.text) {
left = fieldEl.value.length;
} else {
left = fieldEl.value.lastIndexOf(range.text);
}

range = document.selection.createRange().duplicate();
range.moveStart("character", -(fieldEl.value.length));

right = range.text.length;
} else {
left = fieldEl.selectionStart;
right = fieldEl.selectionEnd;
}

return {left: left, right: right};
},

setSelection : function(leftPos, rightPos) {
var left = leftPos;
var right = rightPos || left + 1;

if (this.el.dom.createTextRange) {
var range = field.dom.createTextRange();
range.moveStart("character", left);
range.moveEnd("character", right - this.el.dom.value.length);
range.select();
} else {
this.el.dom.setSelectionRange(left, right);
}
},

doMask : function(key) {
if (this.isInRange(key, this.KEY_RANGES["padnum"])) {
key -= 48;
}
var position = this.getCaretPosition().left;
//make sure a MaskChar is currently selected.
//Prevents a possible error if more than one char is selected (such as when tabbing into a field).
while(!(this.isMaskChar(this.mask.charAt(position))) && (position < this.mask.length)){
position++;
}
var ranges = this.getRange(this.mask.charAt(position));
var valid = false;
for (var i = 0; i < ranges.length; i++) {
if (this.isInRange(key, ranges[i])) {
valid = true;
break;
}
}

if (valid) {
var fieldValue = this.el.dom.value;

var left = fieldValue.substr(0, position);
var right = fieldValue.substr((position + 1), (fieldValue.length - 1));
this.el.dom.value = left + String.fromCharCode(key) + right;

var previousPosition = position;

do {
position++;
} while(!(this.isMaskChar(this.mask.charAt(position))) && (position < fieldValue.length));

if (this.isMaskChar(this.mask.charAt(position))) {
this.setSelection(position);
} else {
this.setSelection(previousPosition);
}
}
},

mapKeyToBehavior : function(evt) {
var key = evt.getKey();
switch (key) {
case Ext.EventObject.BACKSPACE:
this.doBackspace();
break;
case Ext.EventObject.DELETE:
this.doDelete();
break;
case Ext.EventObject.HOME:
this.setSelection(0);
break;
case Ext.EventObject.END:
this.setSelection(this.el.dom.value.length - 1);
break;
case Ext.EventObject.RIGHT:
this.moveCaret(1);
break;
case Ext.EventObject.LEFT:
this.moveCaret(-1);
break;
case Ext.EventObject.TAB:
case Ext.EventObject.ENTER:
return;
default:
this.doMask(key);
}
evt.stopEvent();
},

doSelection : function(evt) {
if (!this.el.dom.value) {
this.el.dom.value = this.getDefaultString();
}
var pos = 1;

if(pos == this.el.dom.value.length) {
pos--;
}

if(!this.isMaskChar(this.mask.charAt(pos))) {
if (!this.moveCaret(1)) {
this.moveCaret(-1);
}
} else {
this.setSelection(pos);
}
},

moveCaret : function(step, left) {
var position = left || this.getCaretPosition().left;

if (step == 0) {
return false;
}

if (position == 0 && step < 0) {
return false;
}

if ((position >= (this.el.dom.value.length - 1)) && (step > 0)) {
return false;
}

do {
position += step;
} while(!(this.isMaskChar(this.mask.charAt(position))) && (position > 0) && (position < this.el.dom.value.length));

if (!(this.isMaskChar(this.mask.charAt(position)))) {
return false;
}

this.setSelection(position);
return true;
},

stopEventFunction : function(evt) {
evt.stopEvent();
},

});

Usage:


new Ext.form.MaskFormattedTextField({
fieldLabel: 'Phone Number',
name: 'phone',
width:150
mask: "(###)###-####", //vtype is created out of the mask
//invalidMessage: "This field is invalid" //custom validation tooltips will override the generated tooltip
//vtype: 'phone' //can still set a custom vtype if you wish
})

galdaka
9 Aug 2007, 12:38 AM
Woooooooooooooooooooooo! Thanks!!

But don

ethraza
9 Aug 2007, 6:18 AM
Hey people...
What you think about put this component in ux space and put the projects at Commnutity Extensions area?
This project is becoming interesting and many peoples wold like to use it.
If you need a server to put the example(s) and the download, will be a pleasure to host it here in my ISP.

Very good project! =D>

devnull
9 Aug 2007, 8:08 AM
youre right, somehow left an extra comma in there.
the regex line is correct however.
i did neglect to test this in ie before i posted it, theres a couple other bugs i will work on today.
I also wanted to work on adding the additional wildcards for upper and lower case characters, but it appears that there is no way to tell in javascript what case the character was typed in.

galdaka
10 Aug 2007, 3:11 AM
youre right, somehow left an extra comma in there.
the regex line is correct however.
i did neglect to test this in ie before i posted it, theres a couple other bugs i will work on today.
I also wanted to work on adding the additional wildcards for upper and lower case characters, but it appears that there is no way to tell in javascript what case the character was typed in.


OK, good work!! Live example please for test!!! (See ethraza post)

Thanks in advance,

devnull
10 Aug 2007, 9:35 AM
Squashed a few more bugs, as well as puting it into the Ext.ux namespace.
Tested in: IE6, IE7, Firefox 2, Opera 9.
I am still not entirely happy with the behavior of how it highlights stuff, so give your ideas of how you think it could be improved.
Online demo: http://www.merkurboys.com/Ext-MaskFormatter/

ethraza
10 Aug 2007, 7:56 PM
Bug?
If you select all the text inside MFTF, or select some mask text (ie. "(" or "-") and press Backspace or Del, the mask text is deleted and the mask control goes away.


For future:
After that I think you can start to think about monetary mask that need a complete different aprouch. To start, a monetary masked field, is always better if the inputed numbers goes from left to right.
So if the mask is (###.###,##) and you type '02', it will become 2 cents ( . ,02), but if the field is accepting input from left to the rightm it will become (02 . , ), that wold be very strange.
What you think? It's possible with your actual code?

Here is a good example of currency mask: http://jsfromhell.com/forms/format-currency/example

Great job, any way! ;)

devnull
14 Aug 2007, 11:46 AM
Ok, found that bug and squashed it :)
Delete and backspace behavior have also been modified to be more consistent with what you would expect in a text editor.
It also no longer works in Opera, I am not yet sure if there will ever be a fix for that.
The monetary mask idea is interesting, but as you suspected is probably difficult to implement. I will think about ways to do it though.

nvbaalamurugan
16 Aug 2007, 1:33 PM
This is a very useful extension. Thanks!
Are you planning to allow select-all/copy/paste/delete function in it? Users might find it difficult without that feature :)

ethraza
17 Aug 2007, 11:44 AM
Hi devnull!
I'm impacient here, waiting... :D
I really need to ask... Have you reached something about the currency mask?

Thanks!

xsbr
18 Aug 2007, 11:43 AM
I put other solution on my form, look it at:
http://www.ricardosantos.com.br/extjs/example-form.php

Fields with mask:

- CPF/CNPJ (###.###.###-## and ##.###.###/####-##)
both are a brazilian ID (fiscal purpose)
- Telefone (Phonenumber) (##) ####-####
- CEP (Zipcode) #####-###

It's based on Restrict Class from Carlos Rodrigues
(http://jsfromhell.com/forms/restrict)

ethraza
18 Aug 2007, 5:01 PM
I don

Spirit
20 Aug 2007, 7:18 AM
Nice extension!
I

galdaka
29 Aug 2007, 11:15 AM
I have a error in MaskFormattedTextField.js:


....
var regexMask = this.mask.replace(/#/g,"\\d");
regexMask = regexMask.replace(/(/,"\\(");
regexMask = regexMask.replace(/)/,"\\)");
....

error: Missing ')'

When I try:


var alpha2 = new Ext.form.MaskFormattedTextField({
width:150,
mask: "###-####" //vtype is created out of the mask
});
alpha2.applyTo('alpha2');

galdaka
29 Aug 2007, 11:44 AM
I have a error in MaskFormattedTextField.js:


....
var regexMask = this.mask.replace(/#/g,"\\d");
regexMask = regexMask.replace(/(/,"\\(");
regexMask = regexMask.replace(/)/,"\\)");
....

error: Missing ')'

When I try:


var alpha2 = new Ext.form.MaskFormattedTextField({
width:150,
mask: "###-####" //vtype is created out of the mask
});
alpha2.applyTo('alpha2');


Sorry I

optimo
3 Sep 2007, 3:41 AM
youre right, somehow left an extra comma in there.
the regex line is correct however.
i did neglect to test this in ie before i posted it, theres a couple other bugs i will work on today.
I also wanted to work on adding the additional wildcards for upper and lower case characters, but it appears that there is no way to tell in javascript what case the character was typed in.

The ASCII value of a character can determine if a character is upper or lower case. Values between 65 through 90 are upper case and values 97 through 122 are lower case. The charCodeAt function could be used. Just a thought.

devnull
4 Sep 2007, 7:56 AM
thats what i thought too, but every test case i tried returned the same ascii code regardless of case. perhaps some other part of the event handler code is eating the modifier keys, who knows. i will revisit it at some point since i too had to stop using it for now because of not being able to paste. it became more important to finish the application than work on this extension for the time being.

ethraza
21 Sep 2007, 10:19 AM
One more reference to the future... this works with jQuery, but don't allow paste too
http://digitalbush.com/projects/masked-input-plugin

daviscabral
8 Oct 2007, 6:54 AM
To make "TAB" work, replace your "stopEventFunction" by this:


stopEventFunction : function(evt) {
var key = evt.getKey();
var ignore = false;

switch (key) {
case Ext.EventObject.BACKSPACE:
case Ext.EventObject.DELETE:
case Ext.EventObject.HOME:
case Ext.EventObject.END:
case Ext.EventObject.RIGHT:
case Ext.EventObject.LEFT:
ignore = true;
break;
}

if ( (ignore || ( key>=41 && key<=122 ) || key==32 || key>186) && (!evt.altKey && !evt.ctrlKey) ) {
evt.stopEvent();
}
}

daviscabral
8 Oct 2007, 12:21 PM
Hi devnull!
I'm impacient here, waiting... :D
I really need to ask... Have you reached something about the currency mask?

Thanks!

Hi,

See this: http://extjs.com/forum/showthread.php?p=71033#post71033

:-)

ethraza
9 Oct 2007, 2:46 PM
Oh thanks... I'll test for sure!
Vlw! ;)

6epcepk
23 Oct 2007, 7:41 AM
el has no properties
[Break on this error] el.on("keydown", mapKeyToBehavior);
Ext 2 beta 1. Any ideas? Thanks.

evilized
23 Oct 2007, 7:58 AM
this is like "an aswesome ext.ux".

nice work, and fully functional.

thx u for u job dude.

gkassyou
31 Oct 2007, 12:25 PM
two issues I found with the maskformattedText.

I'm using devnull's code to extend the form class.

1) If I choose to allowBlank: true, I get a formfield invalid error since the field's mask regex does not like to have an empty field.

2) If I read a phone number from the DB that is not in the (###) ###-#### format, it does not place the 555-123-1233 in the correct place holders and therefore I cannot delete the entries.

Any ideas?

gkassyou
6 Nov 2007, 6:25 AM
Anyone with ideas on these bugs?

daviscabral
7 Nov 2007, 10:09 AM
Overrides the method "setValue" to format your string if her cames without. :)

gkassyou
18 Dec 2007, 8:53 PM
a fix to the doDelete() in order to delete the entire entry as well as an issue with the cursor at the last location. The code I've used is based on the Ext.form.Masked....


doDelete : function() {
var position = this.getCaretPosition().left;

var left = this.el.dom.value.substr(0, position);
var right = this.el.dom.value.substr(position + 1, this.el.dom.value.length - 1);

if (this.el.dom.selectionStart == 0 && this.el.dom.selectionEnd == this.el.dom.value.length) {
this.reset();
return;
} else {
if (position == this.el.dom.value.length)
return; //handle cursor after last item.
this.el.dom.value = left + this.placeholder + right;
this.setSelection(position);
}
},

dawesi
16 Jan 2008, 4:06 PM
Is there a Ext 2.0 version of this?

daviscabral
16 Jan 2008, 4:17 PM
You can use the Ext.ux.InputTextMask plugin.
Here: http://extjs.com/forum/showthread.php?t=21040

UPDATE: This plugin has copy&paste feature! ;-)

fother
22 Jan 2008, 4:28 AM
works fine

http://extjs.com/forum/showthread.php?t=23815

wom75
1 May 2008, 7:18 PM
What folder does this need to go into?

Thanks

sanjivank
20 May 2008, 11:54 AM
Can you please specify example as a plugins

I m trying to use like


plugins: [new Ext.ux.form.MaskFormatter (http://extjs.com/forum/showthread.php?p=51322#post51322)({mask: "(###) ####-####"})]


But does not work. Please assist me.