Created
January 24, 2013 11:18
-
-
Save sepulchered/4620207 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Original source is taken from http://www.sencha.com/forum/showthread.php?136002-Mask-for-TextField | |
* This code was created by sencha forum user http://www.sencha.com/forum/member.php?257343-FrankXP | |
* all rights to this code belong to him. | |
* | |
* Usage example: | |
* { | |
* xtype: 'textfield', | |
* mask: { text: '(999) 999-9999', placeholder:'#', includeInValue: false } | |
* } | |
* | |
* includeInValue will include/exclude the mask when getValue() is called. (default: true) | |
*/ | |
Ext.form.MaskDefinitions = { | |
'9': '[0-9]', | |
'a': '[A-Za-z]', | |
'*': '[A-Za-z0-9]' | |
}; | |
Ext.applyIf(Array.prototype, { | |
map: function (fn, scope) { | |
var r = [], | |
i = 0, | |
len = this.length, | |
v; | |
for (; i < len; i++) { | |
v = fn.call(scope, this[i], i, this); | |
if (v != null) | |
r.push(v); | |
} | |
return r; | |
} | |
}); | |
(function () { | |
var _initComponent = Ext.form.TextField.prototype.initComponent, | |
_initEvents = Ext.form.TextField.prototype.initEvents, | |
_getValue = Ext.form.TextField.prototype.getValue, | |
_setValue = Ext.form.TextField.prototype.setValue, | |
_preFocus = Ext.form.TextField.prototype.preFocus; | |
Ext.override(Ext.form.TextField, { | |
initComponent: function () { | |
if (this.initMask()) { | |
Ext.apply(this, { | |
disableKeyFilter: true, | |
maskRe: null | |
}); | |
this.addEvents('maskComplete'); | |
} | |
_initComponent.apply(this); | |
}, | |
initEvents: function () { | |
_initEvents.apply(this); | |
if (this.mask) { | |
if (!this.enableKeyEvents && this.mask) { | |
this.mon(this.el, { | |
scope: this, | |
keydown: this.onKeyDown, | |
keypress: this.onKeyPress | |
}); | |
} | |
this.mon(this.el, 'paste', this.onPaste, this); | |
} | |
}, | |
initMask: function () { | |
if (!Ext.isDefined(this.mask)) { | |
return false; | |
} | |
this.mask = Ext.isString(this.mask) ? { text: this.mask} : this.mask; | |
Ext.applyIf(this.mask, { placeholder: '_', includeInValue: true }); | |
if (!this.mask.text) { | |
return false; | |
} | |
Ext.apply(this.mask, { | |
regexp: [], | |
partialPosition: this.mask.text.length, | |
firstNonMaskPos: null, | |
length: this.mask.text.length, | |
buffer: this.mask.text.split('').map(function (c) { | |
return (c === '?') ? null : Ext.form.MaskDefinitions[c] ? this.mask.placeholder : c; | |
}, this), | |
seekNext: function (pos) { | |
while (++pos <= this.length && !this.regexp[pos]); | |
return pos; | |
}, | |
seekPrev: function (pos) { | |
while (--pos >= 0 && !this.regexp[pos]); | |
return pos; | |
}, | |
shiftL: function (start, end) { | |
if (start < 0) { | |
return; | |
} | |
for (var i = start, j = this.seekNext(end); i < this.length; i++) { | |
if (this.regexp[i]) { | |
if (j < this.length && this.regexp[i].test(this.buffer[j])) { | |
this.buffer[i] = this.buffer[j]; | |
this.buffer[j] = this.placeholder; | |
} else { | |
break; | |
} | |
j = this.seekNext(j); | |
} | |
} | |
}, | |
shiftR: function (pos) { | |
for (var i = pos, c = this.placeholder; i < this.length; i++) { | |
if (this.regexp[i]) { | |
var j = this.seekNext(i); | |
var t = this.buffer[i]; | |
this.buffer[i] = c; | |
if (j < this.length && this.regexp[j].test(t)) { | |
c = t; | |
} | |
else { | |
break; | |
} | |
} | |
} | |
}, | |
clearBuffer: function (start, end) { | |
for (var i = start; i < end && i < this.length; i++) { | |
if (this.regexp[i]) { | |
this.buffer[i] = this.placeholder; | |
} | |
} | |
}, | |
getBufferValue: function (removeMask) { | |
return removeMask ? | |
this.buffer.map(function (c, i) { | |
return (this.regexp[i] && c != this.placeholder) ? c : null; | |
}, this).join('') : | |
this.buffer.join(''); | |
} | |
}); | |
Ext.each(this.mask.text.split(''), function (c, i) { | |
if (c === '?') { | |
this.mask.length--; | |
this.mask.partialPosition = i; | |
} else if (Ext.form.MaskDefinitions[c]) { | |
this.mask.regexp.push(new RegExp(Ext.form.MaskDefinitions[c])); | |
if (this.mask.firstNonMaskPos == null) { | |
this.mask.firstNonMaskPos = this.mask.regexp.length - 1; | |
} | |
} else { | |
this.mask.regexp.push(null); | |
} | |
}, this); | |
return true; | |
}, | |
//private | |
_cursor: function (start, end) { | |
var s, e, r, d = this.el.dom; | |
if (typeof start == 'number') { | |
end = (typeof end == 'number') ? end : start; | |
if (d.setSelectionRange) { | |
d.setSelectionRange(start, end); | |
} else if (d.createTextRange) { | |
r = d.createTextRange(); | |
r.collapse(true); | |
r.moveEnd('character', end); | |
r.moveStart('character', start); | |
r.select(); | |
} | |
} | |
else { | |
if (d.setSelectionRange) { | |
s = d.selectionStart; | |
e = d.selectionEnd; | |
} | |
else if (document.selection && document.selection.createRange) { | |
r = document.selection.createRange(); | |
s = 0 - r.duplicate().moveStart('character', -d.value.length); | |
e = s + r.text.length; | |
} | |
return { start: isNaN(s) ? 0 : s, end: isNaN(e) ? 0 : e }; | |
} | |
}, | |
_checkValueMask: function (allow) { | |
var test = this.getRawValue(); | |
var lastMatch = -1; | |
for (var i = 0, pos = 0; i < this.mask.length; i++) { | |
if (this.mask.regexp[i]) { | |
this.mask.buffer[i] = this.mask.placeholder; | |
while (pos++ < test.length) { | |
var c = test.charAt(pos - 1); | |
if (this.mask.regexp[i].test(c)) { | |
this.mask.buffer[i] = c; | |
lastMatch = i; | |
break; | |
} | |
} | |
if (pos > test.length) | |
break; | |
} else if (this.mask.buffer[i] == test.charAt(pos) && i != this.mask.partialPosition) { | |
pos++; | |
lastMatch = i; | |
} | |
} | |
if (!allow && lastMatch + 1 < this.mask.partialPosition) { | |
this.setRawValue(''); | |
this.mask.clearBuffer(0, this.mask.length); | |
} else if (allow || lastMatch + 1 >= this.mask.partialPosition) { | |
this._writeMaskBuffer(); | |
if (!allow) this.setRawValue(this.getRawValue().substring(0, lastMatch + 1)); | |
} | |
return (this.mask.partialPosition ? i : this.mask.firstNonMaskPos); | |
}, | |
_writeMaskBuffer: function () { | |
this.setRawValue(this.mask.getBufferValue()); | |
}, | |
//public | |
getValue: function () { | |
var v = _getValue.apply(this); | |
if (this.mask && !Ext.isEmpty(v)) { | |
v = this.mask.includeInValue ? v.replace(this.mask.placeholder,'') : this.mask.getBufferValue(true); | |
} | |
return v; | |
}, | |
setValue: function (v) { | |
_setValue.call(this, v); | |
if (this.mask && !Ext.isEmpty(v)) { | |
this._checkValueMask(); | |
} | |
}, | |
//protected | |
preFocus: function () { | |
_preFocus.apply(this); | |
if (this.mask && !this.hasFocus) { | |
this.startValue = this.getValue(); | |
var pos = this._checkValueMask(); | |
this._writeMaskBuffer(); | |
(function () { | |
if (pos == this.mask.length) { | |
this._cursor(0, pos); | |
} | |
else { | |
this._cursor(pos); | |
} | |
}).defer(0, this); | |
} | |
}, | |
beforeBlur: function () { | |
if (this.mask && !this.readOnly) { | |
this._checkValueMask(); | |
} | |
}, | |
onKeyDown: function (e) { | |
this.fireEvent('keydown', this, e); | |
if (this.mask && !this.readOnly) { | |
var k = e.getKey(); | |
if (k == e.BACKSPACE || k == e.DELETE) { | |
var pos = this._cursor(), | |
start = pos.start, | |
end = pos.end; | |
if (end - start == 0) { | |
start = k != e.DELETE ? this.mask.seekPrev(start) : (end = this.mask.seekNext(start - 1)); | |
end = k == e.DELETE ? this.mask.seekNext(end) : end; | |
} | |
this.mask.clearBuffer(start, end); | |
this.mask.shiftL(start, end - 1); | |
this._writeMaskBuffer(); | |
this._cursor(Math.max(this.mask.firstNonMaskPos, start)); | |
e.stopEvent(); | |
} else if (k == e.ESC) { | |
this.setValue(this.startValue); | |
this._cursor(0, this._checkValueMask()); | |
e.stopEvent(); | |
} | |
} | |
}, | |
onKeyPress: function (e) { | |
this.fireEvent('keypress', this, e); | |
if (this.mask && !this.readOnly) { | |
var k = e.getKey(), | |
pos = this._cursor(), | |
start = pos.start, | |
end = pos.end; | |
if (!e.ctrlKey && !e.altKey && !e.isNavKeyPress() && k != e.CONTEXT_MENU && k >= 32) { | |
if (end - start != 0) { | |
this.mask.clearBuffer(start, end); | |
this.mask.shiftL(start, end - 1); | |
this._writeMaskBuffer(); | |
this._cursor(Math.max(this.mask.firstNonMaskPos, start)); | |
} | |
var p = this.mask.seekNext(start - 1); | |
if (p < this.mask.length) { | |
var c = String.fromCharCode(e.getCharCode()); | |
if (this.mask.regexp[p].test(c)) { | |
this.mask.shiftR(p); | |
this.mask.buffer[p] = c; | |
this._writeMaskBuffer(); | |
var next = this.mask.seekNext(p); | |
this._cursor(next); | |
if (next >= this.mask.length) { | |
this.fireEvent('maskComplete', this, this.mask); | |
} | |
} | |
} | |
e.stopEvent(); | |
} | |
} | |
}, | |
onPaste: function (e) { | |
if (this.mask && !this.readOnly) { | |
(function () { this._cursor(this._checkValueMask(true)); }).defer(10, this); | |
} | |
} | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can apply this code to triggerfield, but modifications needed.