(function (factory){
if(typeof define==='function'&&define.amd){
define(['jquery'], factory);
}else if(typeof exports==='object'){
factory(require('jquery'));
}else{
factory(jQuery);
}}(function ($){
var ua=navigator.userAgent,
iPhone=/iphone/i.test(ua),
chrome=/chrome/i.test(ua),
android=/android/i.test(ua),
caretTimeoutId;
$.mask={
definitions: {
'9': "[0-9]",
'a': "[A-Za-z]",
'*': "[A-Za-z0-9]"
},
autoclear: true,
dataName: "rawMaskFn",
placeholder: '_'
};
$.fn.extend({
caret: function(begin, end){
var range;
if(this.length===0||this.is(":hidden")||this.get(0)!==document.activeElement){
return;
}
if(typeof begin=='number'){
end=(typeof end==='number') ? end:begin;
return this.each(function(){
if(this.setSelectionRange){
this.setSelectionRange(begin, end);
}else if(this.createTextRange){
range=this.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', begin);
range.select();
}});
}else{
if(this[0].setSelectionRange){
begin=this[0].selectionStart;
end=this[0].selectionEnd;
}else if(document.selection&&document.selection.createRange){
range=document.selection.createRange();
begin=0 - range.duplicate().moveStart('character', -100000);
end=begin + range.text.length;
}
return { begin: begin, end: end };}},
unmask: function(){
return this.trigger("unmask");
},
mask: function(mask, settings){
var input,
defs,
tests,
partialPosition,
firstNonMaskPos,
lastRequiredNonMaskPos,
len,
oldVal;
if(!mask&&this.length > 0){
input=$(this[0]);
var fn=input.data($.mask.dataName)
return fn?fn():undefined;
}
settings=$.extend({
autoclear: $.mask.autoclear,
placeholder: $.mask.placeholder,
completed: null
}, settings);
defs=$.mask.definitions;
tests=[];
partialPosition=len=mask.length;
firstNonMaskPos=null;
mask=String(mask);
$.each(mask.split(""), function(i, c){
if(c=='?'){
len--;
partialPosition=i;
}else if(defs[c]){
tests.push(new RegExp(defs[c]));
if(firstNonMaskPos===null){
firstNonMaskPos=tests.length - 1;
}
if(i < partialPosition){
lastRequiredNonMaskPos=tests.length - 1;
}}else{
tests.push(null);
}});
return this.trigger("unmask").each(function(){
var input=$(this),
buffer=$.map(mask.split(""),
function(c, i){
if(c!='?'){
return defs[c] ? getPlaceholder(i):c;
}}),
defaultBuffer=buffer.join(''),
focusText=input.val();
function tryFireCompleted(){
if(!settings.completed){
return;
}
for (var i=firstNonMaskPos; i <=lastRequiredNonMaskPos; i++){
if(tests[i]&&buffer[i]===getPlaceholder(i)){
return;
}}
settings.completed.call(input);
}
function getPlaceholder(i){
if(i < settings.placeholder.length)
return settings.placeholder.charAt(i);
return settings.placeholder.charAt(0);
}
function seekNext(pos){
while (++pos < len&&!tests[pos]);
return pos;
}
function seekPrev(pos){
while (--pos >=0&&!tests[pos]);
return pos;
}
function shiftL(begin,end){
var i,
j;
if(begin<0){
return;
}
for (i=begin, j=seekNext(end); i < len; i++){
if(tests[i]){
if(j < len&&tests[i].test(buffer[j])){
buffer[i]=buffer[j];
buffer[j]=getPlaceholder(j);
}else{
break;
}
j=seekNext(j);
}}
writeBuffer();
input.caret(Math.max(firstNonMaskPos, begin));
}
function shiftR(pos){
var i,
c,
j,
t;
for (i=pos, c=getPlaceholder(pos); i < len; i++){
if(tests[i]){
j=seekNext(i);
t=buffer[i];
buffer[i]=c;
if(j < len&&tests[j].test(t)){
c=t;
}else{
break;
}}
}}
function androidInputEvent(e){
var curVal=input.val();
var pos=input.caret();
var proxy=function (){
$.proxy($.fn.caret, input, pos.begin, pos.begin)();
};
if(oldVal&&oldVal.length&&oldVal.length > curVal.length){
checkVal(true);
while (pos.begin > 0&&!tests[pos.begin-1])
pos.begin--;
if(pos.begin===0){
while (pos.begin < firstNonMaskPos&&!tests[pos.begin])
pos.begin++;
}
setTimeout(proxy, 0);
}else{
var pos2=checkVal(true);
var lastEnteredValue=curVal.charAt(pos.begin);
if(pos.begin < len){
if(!tests[pos.begin]){
pos.begin=pos2;
}else{
if(tests[pos.begin].test(lastEnteredValue)){
pos.begin++;
}}
}
setTimeout(proxy, 0);
}
tryFireCompleted();
}
function blurEvent(e){
checkVal();
if(input.val()!=focusText)
input.change();
}
function keydownEvent(e){
if(input.prop("readonly")){
return;
}
var k=e.which||e.keyCode,
pos,
begin,
end;
oldVal=input.val();
if(k===8||k===46||(iPhone&&k===127)){
pos=input.caret();
begin=pos.begin;
end=pos.end;
if(end - begin===0){
begin=k!==46?seekPrev(begin):(end=seekNext(begin-1));
end=k===46?seekNext(end):end;
}
clearBuffer(begin, end);
shiftL(begin, end - 1);
e.preventDefault();
}else if(k===13){
blurEvent.call(this, e);
}else if(k===27){
input.val(focusText);
input.caret(0, checkVal());
e.preventDefault();
}}
function keypressEvent(e){
if(input.prop("readonly")){
return;
}
var k=e.which||e.keyCode,
pos=input.caret(),
p,
c,
next;
if(e.ctrlKey||e.altKey||e.metaKey||k < 32){
return;
}else if(k&&k!==13){
if(pos.end - pos.begin!==0){
clearBuffer(pos.begin, pos.end);
shiftL(pos.begin, pos.end-1);
}
p=seekNext(pos.begin - 1);
if(p < len){
c=String.fromCharCode(k);
if(tests[p].test(c)){
shiftR(p);
buffer[p]=c;
writeBuffer();
next=seekNext(p);
if(android){
var proxy=function(){
$.proxy($.fn.caret,input,next)();
};
setTimeout(proxy,0);
}else{
input.caret(next);
}
if(pos.begin <=lastRequiredNonMaskPos){
tryFireCompleted();
}}
}
e.preventDefault();
}}
function clearBuffer(start, end){
var i;
for (i=start; i < end&&i < len; i++){
if(tests[i]){
buffer[i]=getPlaceholder(i);
}}
}
function writeBuffer(){ input.val(buffer.join('')); }
function checkVal(allow){
var test=input.val(),
lastMatch=-1,
i,
c,
pos;
for (i=0, pos=0; i < len; i++){
if(tests[i]){
buffer[i]=getPlaceholder(i);
while (pos++ < test.length){
c=test.charAt(pos - 1);
if(tests[i].test(c)){
buffer[i]=c;
lastMatch=i;
break;
}}
if(pos > test.length){
clearBuffer(i + 1, len);
break;
}}else{
if(buffer[i]===test.charAt(pos)){
pos++;
}
if(i < partialPosition){
lastMatch=i;
}}
}
if(allow){
writeBuffer();
}else if(lastMatch + 1 < partialPosition){
if(settings.autoclear||buffer.join('')===defaultBuffer){
if(input.val()) input.val("");
clearBuffer(0, len);
}else{
writeBuffer();
}}else{
writeBuffer();
input.val(input.val().substring(0, lastMatch + 1));
}
return (partialPosition ? i:firstNonMaskPos);
}
input.data($.mask.dataName,function(){
return $.map(buffer, function(c, i){
return tests[i]&&c!=getPlaceholder(i) ? c:null;
}).join('');
});
input
.one("unmask", function(){
input
.off(".mask")
.removeData($.mask.dataName);
})
.on("focus.mask", function(){
if(input.prop("readonly")){
return;
}
clearTimeout(caretTimeoutId);
var pos;
focusText=input.val();
pos=checkVal();
caretTimeoutId=setTimeout(function(){
if(input.get(0)!==document.activeElement){
return;
}
writeBuffer();
if(pos==mask.replace("?","").length){
input.caret(0, pos);
}else{
input.caret(pos);
}}, 10);
})
.on("blur.mask", blurEvent)
.on("keydown.mask", keydownEvent)
.on("keypress.mask", keypressEvent)
.on("input.mask paste.mask", function(){
if(input.prop("readonly")){
return;
}
setTimeout(function(){
var pos=checkVal(true);
input.caret(pos);
tryFireCompleted();
}, 0);
});
if(chrome&&android){
input
.off('input.mask')
.on('input.mask', androidInputEvent);
}
checkVal();
});
}});
}));