Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

I always forget to include new files :S. This is the last commit befo…

…re the new fixed mask behavior.

Ill create a tag to mark this, since i may want to get the old behavior back.
  • Loading branch information...
commit df8044d0877e93c39a5840e8c10cdfd8d1d16d51 1 parent 7d48360
Fabio M. Costa authored
View
27 docs/todo.txt
@@ -1,11 +1,18 @@
Things i don't like about it (will change till version 2.0):
-
+* Watch for a better fix on maxLength (try to avoid that maxLength == -1).
+** OK, i've overwritten the maxlength Property, now its cleaner.
* Some crazy if's - This will need a total rewrite from the plugin;
-* Mask types should have in some way, different options for each of them, i mean, they should be threated separately, each of theyres event. It's being done right now... but i feel that it can be even better;
+** Its becoming better every commit.
+* Mask types should have, in some way, different options for each of them, i mean, they should be threated separately, each of theyre's event. It's being done right now... but i feel that it can be even better;
+** It can always be better but im happy right now.
* Try not to polute the native objects with crazy and unusefull methods;
+** I won't sir! I promice.
+* Try to add a placeholder option, not that necessary but it would be nice;
+** IT IS STILL THERE! And working like a charm
* Make a cool and correct unmaskedVal function;
* Work correctly with float and integer numbers, i mean like... if 90 is the value of the input it will mask to 90.00 not 0.90;
+* Change the way signed masks work! That's so not pretty!;
* New mask type that works like this:
mask='9-9' and maxlength=5
'22' -> '2-2'
@@ -13,21 +20,27 @@ Things i don't like about it (will change till version 2.0):
'2222' -> '222-2'
Till it gets to 5.
* RegexMask should be included too, it is still here at the mootools version, but with the paste bug, that will be easily fixed with the maxLength option, that will not be optional (can't force it but it will break paste if not present);
-* Try to add a placeholder option, not that necessary but it would be nice; IT IS STILL THERE!
-* Change the way signed masks work! That's so not pretty!;
-* Watch for a better fix on maxLength (try to avoid that maxLength == -1).
+
IDEAS FOR 2.0:
* Set defaultValue when the mask is applyed to fix the reset buton of the form; OK
* Option that will set the size attribute of the input based on the mask; OK
* As seen on the benchmarks i did, i should consider using a string of characters instead of a regular expression; OK
-* Add a callback to rules so that it can get uppercased or lowercased after inputting the char, this will allow a char being dependent of a preceding char (like on hours you dont want the user to input chars bigger than 3 if the first is 2)
-* Option to force the completition of the value of the mask.
+* Option to force the completition of the value of the mask. OK, removeIfInvalid
+* Add a callback to rules so that it can get uppercased or lowercased after inputting the char, this will allow a char being dependent of a preceding char (like on hours you dont want the user to input chars bigger than 3 if the first is 2)
+
+Fixed Masks Behavior
+====================
+
+I've just seen how fixed masks works on netbeans. I'll implement it exactly the same way, i liked it.
+The code will be smaller and i think more consistent.
+O course the code will always be here, i think ill create a tag for this.
New Structure
=============
+
Everything will be classes now. I'll have to give some credit for zilenCe here, he made an inputMask plugin that i loved the structured he used, in fact it was i was looking for. I don't like the structure used on MeioMask right now, but zilenCe found a better one.
First class is Meio just to namespace my own classes. Next comes our Mask class, Meio.Mask. Next is the mask type, like Meio.Mask.Fixed, that will extends from Meio.Mask and finally the mask name, like Date or Time. We end up with something like Meio.Mask.Fixed.Date.
View
276 source/moo.meio.mask.Mask.Fixed.js
@@ -0,0 +1,276 @@
+
+Meio.Mask.Fixed = new Class({
+
+ Extends: Meio.Mask,
+
+ options: {
+ placeHolder: '_',
+ setSize: false,
+ removeIfInvalid: false // removes the value onblur if the input is not valid
+ },
+
+ initialize: function(mask, options){
+ this.parent(mask, options);
+ this.maskMold = this.options.mask.replace(Meio.Mask.rulesRegex, this.options.placeHolder);
+ this.maskMoldArray = this.maskMold.split('');
+ this.validIndexes = [];
+ if(this.options.setSize) this.setSize();
+ this.maskArray.each(function(c, i){
+ if(Meio.Mask.matchRules.contains(c)) this.validIndexes.push(i);
+ }, this);
+ },
+
+ _paste: function(e, o){
+ var retApply = this._applyMask(this.element.get('value'), o.range.start);
+ this.maskMoldArray = retApply.value;
+
+ this.element.set('value', this.maskMoldArray.join(''))
+ .setRange(retApply.rangeStart + 1);
+
+ return false;
+ },
+
+ _applyMask: function(elementValue, newRangeStart){
+ var elementValueArray = elementValue.split(''),
+ maskArray = this.maskArray,
+ maskMold = this.maskMold,
+ eli = 0;
+
+ while(eli < maskMold.length){
+ if(!elementValueArray[eli]){
+ elementValueArray[eli] = maskMold[eli];
+ }
+ else if(Meio.Mask.rules[maskArray[eli]]){
+ if(!this.testEntry(eli, elementValueArray[eli])){
+ elementValueArray.splice(eli, 1);
+ continue;
+ }
+ newStartRange = eli;
+ }
+ else if(maskArray[eli] != elementValueArray[eli]){
+ elementValueArray.splice(eli, 0, maskMold[eli]);
+ }
+ else{
+ elementValueArray[eli] = maskMold[eli];
+ }
+ eli++;
+ }
+
+ // makes sure the value is not bigger than the mask definition
+ return {value: elementValueArray.slice(0, this.maskMold.length), rangeStart: newRangeStart};
+ },
+
+ _focus: function(e, o){
+ this.element.set('value', this.maskMoldArray.join(''))
+ .store('meiomask:focusvalue', this.element.get('value'));
+ this.parent(e, o);
+ return true;
+ },
+
+ _blur: function(e, o){
+ var elementValue = this.element.get('value'),
+ i = elementValue.length - 1, truncateIndex = 0, cont;
+
+ // fires change event if the value on focus != from value on blur
+ if(this.element.retrieve('meiomask:focusvalue') != elementValue){
+ this.element.fireEvent('change');
+ }
+
+ if(this.options.removeIfInvalid){
+ if(elementValue.contains(this.options.placeHolder)){
+ // remove if invalid option
+ this.maskMoldArray = this.maskMold.split('');
+ this.element.set('value', '');
+ }
+ return true;
+ }
+
+ if(elementValue == this.maskMold){
+ // if no char inputed
+ this.element.set('value', '');
+ }
+ else{
+ // removes incorrect chars at the end of the string
+ while(i >= 0){
+ cont = false;
+ while(!Meio.Mask.matchRules.contains(elementValue.charAt(i)) && elementValue.charAt(i) != this.options.placeHolder){
+ cont = true;
+ i--;
+ }
+ if(cont){
+ while(elementValue.charAt(i) == this.options.placeHolder){
+ truncateIndex = i;
+ i--;
+ }
+ }
+ else{
+ break;
+ }
+ }
+ if(truncateIndex) this.element.set('value', elementValue.substring(0, truncateIndex));
+ }
+ return true;
+ },
+
+ _keypress: function(e, o){
+ if(this.ignore || e.control || e.meta || e.alt) return true;
+
+ var c = String.fromCharCode(e.code),
+ maskArray = this.maskArray,
+ start, i;
+
+ if(!o.isSelection){
+ // no text selected
+ if(o.isRemoveKey){
+ if(o.isDelKey){
+ do{
+ start = this.validIndexes.indexOf(o.range.start++);
+ }while(start == -1 && o.range.start < maskArray.length);
+ }
+ else{
+ do{
+ start = this.validIndexes.indexOf(--o.range.start);
+ }while(start == -1 && o.range.start >= 0);
+ }
+
+ if(start == -1) return false;
+
+ var auxi = start,
+ i_1 = this.validIndexes[auxi+1];
+
+ i = this.validIndexes[auxi];
+
+ if(!this.testEvents(i, c, e.code, o.isRemoveKey)) return false;
+
+ while(auxi <= this.validIndexes.length && i_1 && this.testEntry(i, this.maskMoldArray[i_1])){
+ this.maskMoldArray[i] = this.maskMoldArray[i_1];
+ i = this.validIndexes[auxi];
+ i_1 = this.validIndexes[++auxi];
+ }
+ this.maskMoldArray[i] = this.options.placeHolder;
+
+ this.element.set('value', this.maskMoldArray.join(''))
+ .setRange(this.validIndexes[start]);
+ }
+ else{
+ // gets start index, if it is not on the validIndexes it will try to get the next
+ do{
+ start = this.validIndexes.indexOf(o.range.start++);
+ }while(start==-1 && o.range.start < maskArray.length);
+
+ i = this.validIndexes[start];
+
+ if(!this.testEvents(i, c, e.code, o.isRemoveKey)) return false;
+
+ var queue = [this.maskMoldArray[i]];
+
+ // apply the char that just passed the test
+ this.maskMoldArray[i] = c;
+
+ auxi = start + 1;
+ i = this.validIndexes[auxi];
+
+ while(auxi < this.validIndexes.length && this.testEntry(i, queue[0])){
+ queue.unshift(this.maskMoldArray[i]);
+ this.maskMoldArray[i] = queue.pop();
+ i = this.validIndexes[++auxi];
+ }
+
+ this.element.set('value', this.maskMoldArray.join(''));
+ if(this.validIndexes[start + 1]) this.element.setRange(this.validIndexes[start + 1]);
+ }
+ }
+ else{
+
+ var rstart = o.range.start;
+ var rend = o.range.end;
+
+ // text selected
+ do{
+ start = this.validIndexes.indexOf(o.range.start++);
+ }while(start==-1 && o.range.start < maskArray.length);
+ do{
+ end = this.validIndexes.indexOf(o.range.end++);
+ }while(end==-1 && o.range.end < maskArray.length);
+ //if(end==-1) end = maskArray.length;
+
+ var delta = end-start;
+
+ if(delta == 0) return false;
+
+ // removes all the chars into the range
+ for(i=rstart; i<rend; i++){
+ this.maskMoldArray[i] = this.maskMold.charAt(i);
+ }
+ // removes all the chars into the range
+
+ if(!o.isRemoveKey){
+ i = this.validIndexes[start];
+ if(!this.testEvents(i, c, e.code, o.isRemoveKey)) return false;
+ this.maskMoldArray[i] = c;
+ start++;
+ }
+
+ delta = end - start;
+
+ if(delta == 0){
+ this.element.set('value', this.maskMoldArray.join(''));
+ this.element.setRange(this.validIndexes[start]);
+ return false;
+ }
+
+ auxi = end;
+
+ var canMove = true, i_delta;
+ while((i = this.validIndexes[auxi]) && (this.maskMoldArray[i] != this.options.placeHolder)){
+ i_delta = this.validIndexes[auxi-delta];
+ if(!this.testEntry(i_delta, this.maskMoldArray[i])){
+ canMove = false;
+ break;
+ }
+ auxi++;
+ }
+
+ if(canMove){
+ auxi = end;
+ while((i = this.validIndexes[auxi])){
+ i_delta = this.validIndexes[auxi-delta];
+ this.maskMoldArray[i_delta] = this.maskMoldArray[i];
+ this.maskMoldArray[i] = this.options.placeHolder;
+ auxi++;
+ }
+ }
+
+ this.element.set('value', this.maskMoldArray.join(''));
+ this.element.setRange(this.validIndexes[start]);
+ }
+ return false;
+ },
+
+ mask: function(str){
+ return this._applyMask(str).value;
+ }
+
+});
+
+Meio.Mask.createMasks('Fixed', {
+ 'Time' : { mask: '2h:59'},
+ 'Phone' : { mask: '(99) 9999-9999)' },
+ 'PhoneUS' : { mask: '(999) 999-9999' },
+ 'CPF' : { mask: '999.999.999-99' },
+ 'CNPJ' : { mask: '99.999.999/9999-99' },
+ 'Date' : { mask: '39/19/9999' },
+ 'DateUS' : { mask: '19/39/9999' },
+ 'Cep' : { mask: '99999-999' },
+ 'Time' : { mask: '2h:59' },
+ 'CC' : { mask: '9999 9999 9999 9999' }
+});
+
+/*
+Meio.Mask.Fixed.Time = new Class({
+ Extends: Meio.Mask.Fixed,
+ options: {
+ mask: '2h:59'
+ }
+});
+*/
View
41 source/moo.meio.mask.Mask.Regexp.js
@@ -0,0 +1,41 @@
+ Meio.Mask.Regexp = new Class({
+
+ Extends : Meio.Mask,
+
+ initialize : function(mask){
+ this.parent(mask);
+ this.regExp = new RegExp(this.mask.options.mask);
+ },
+
+ _keyup : function(e,o){
+ return true;
+ },
+
+ _paste : function(e,o){
+ //for(var i=0 , newValue=''; i < o.value.length; i++) if( this.regExp.test( o.value.charAt(i) ) )
+ //newValue += o.value.charAt(i);
+ this.$el.set('value', this.regExp.test(o.value) ? o.value : '' );
+ return true;
+ },
+
+ _keypress: function(e,o){
+ if( this.ignore || e.control || e.meta || e.alt ) return true;
+ var c = String.fromCharCode(e.code),
+ rawValue = o.value,
+ // the input value from the range start to the value start
+ valueStart = rawValue.substr(0,o.range.start),
+ // the input value from the range end to the value end
+ valueEnd = rawValue.substr(o.range.end,rawValue.length);
+ rawValue = (valueStart+c+valueEnd);
+ // its a little hard to detect the overflow :s
+ if( this.regExp.test( rawValue ) ){
+ this.mask.fireEvent('valid',[this.$el,c,e.code]);
+ return true;
+ }
+ else{
+ this.mask.fireEvent('invalid',[this.$el,c,e.code]);
+ return false;
+ }
+ }
+
+ });
View
24 source/moo.meio.mask.Mask.Repeat.js
@@ -0,0 +1,24 @@
+ Meio.Mask.Repeat = new Class({
+
+ Extends : Meio.Mask,
+
+ _keyup : function(e,o){
+ return true;
+ },
+
+ _paste : function(e,o){
+ this.$el.set('value', this.__mask(o.valueArray, this.globals, this.mask.options));
+ return true;
+ },
+
+ _keypress: function(e,o){
+ if(this.ignore || e.control || e.meta || e.alt) return true;
+ var c = String.fromCharCode(e.code),
+ maskArray = this.mask.options.maskArray,
+ valueArray = o.value.replace(this.globals.fixedCharsRegG, '').split('');
+ if(!this.testEvents(maskArray, 0, c, e.code)) return false;
+ this.$el.set('value', valueArray.join(''));
+ return true;
+ }
+
+ });
View
74 source/moo.meio.mask.Mask.Reverse.js
@@ -0,0 +1,74 @@
+ Meio.Mask.Reverse = new Class({
+
+ Extends: Meio.Mask,
+
+ options: {
+ alignText: true,
+ decimal: true
+ //signal: false
+ },
+
+ initialize: function(mask){
+ this.parent(mask);
+ if(mask){
+ $extend(this.mask.options, this.options);
+ this.mask.options.maskArray.reverse();
+ if(this.mask.options.alignText) this.element.setStyle('text-align', 'right');
+ //if(this.$el.get('value') == '') this.$el.set('value', .mask(this.mask.options));
+ }
+ },
+
+ _paste: function(e,o){
+ this.$el.set('value', this.__mask(o.valueArray , this.globals , this.mask.options));
+ return true;
+ },
+
+ _keypress: function(e,o){
+
+ if(this.ignore || e.control || e.meta || e.alt) return true;
+
+ var c = String.fromCharCode(e.code),
+ rangeStart = o.range.start,
+ rawValue = o.value,
+ opt = this.mask.options,
+ maskArray = opt.maskArray,
+ // the input value from the range start to the value start
+ valueStart = rawValue.substr(0, rangeStart),
+ // the input value from the range end to the value end
+ valueEnd = rawValue.substr(o.range.end, rawValue.length);
+
+ rawValue = (valueStart + c + valueEnd);
+
+ var valueArray = rawValue.replace(opt.fixedCharsRegG, '').split(''),
+ // searches for fixed chars begining from the range start position, till it finds a non fixed
+ extraPos = maskArray.__extraPositionsTill(rangeStart, opt.fixedCharsReg);
+
+ o.rsEp = rangeStart + extraPos;
+ if(!this.testEvents(maskArray, o.rsEp, c, e.code)) return false;
+ this.$el.set('value', this.__mask(valueArray, this.globals, opt));
+
+ //fix for ie
+ //this bug was pointed by Pedro Martins
+ //it fixes a strange behavior that ie was having after a char was inputted in a text input that
+ //had its content selected by any range
+ if(Browser.Engine.trident && ((rangeStart==0 && o.range.end==0) || rangeStart != o.range.end))
+ this.$el.setRange(o.value.length);
+
+ return false;
+ },
+
+ __mask: function(valueArray, globals, o, extraPos){
+ valueArray.reverse();
+ var newValue = valueArray.__mask(globals, o).reverse();
+ return newValue.join('').substring(newValue.length - o.maskArray.length);
+ }
+
+ });
+
+ /*
+ masks: {
+ 'integer' : { mask: '999.999.999.999', type: 'reverse', decimal: false },
+ 'decimal' : { mask: '999.999.999.999,99', type: 'reverse' },
+ 'decimal-us' : { mask: '999,999,999,999.99', type: 'reverse' }
+ }
+ */
View
9 source/moo.meio.mask.Mask.js
@@ -5,8 +5,10 @@
eventsToBind: ['focus', 'blur', 'keydown', 'keypress', 'paste'],
options: {
+
selectOnFocus: true,
autoTab: false
+
//onInvalid: $empty,
//onValid: $empty,
//onOverflow: $empty
@@ -83,6 +85,10 @@
|| (Meio.Mask.onlyKeyDownRepeat && o.isRemoveKey)
)? this._keypress(e, o): true;
},
+
+ _focus: function(e, o){
+ if(this.options.selectOnFocus) this.element.select();
+ },
testEntry: function(index, _char){
var maskArray = this.maskArray,
@@ -205,7 +211,8 @@
'*': {regex: /[0-9a-zA-Z]/},
'@': {regex: /[0-9a-zA-ZçÇáàãâéèêíìóòõôúùü]/},
//its included just to exemplify how to use it, its used on the time mask
- 'h': {regex: /[0-9]/, check: function(value, index, _char){if(value.charAt(index-1)==2) return (_char<=3); return true;}}
+ 'h': {regex: /[0-9]/, check: function(value, index, _char){if(value.charAt(index-1)==2) return (_char<=3); return true;}},
+ 'U': {regex: /[a-z]/, check: function(value, index, _char){return _char.toUpperCase();}}
};
for(var i=0; i<=9; i++) rules[i] = {regex: new RegExp('[0-' + i + ']')};
return rules;
Please sign in to comment.
Something went wrong with that request. Please try again.