'use strict';
(function (factory, jQuery, Zepto){
if(typeof define==='function'&&define.amd){
define(['jquery'], factory);
}else if(typeof exports==='object'){
module.exports=factory(require('jquery'));
}else{
factory(jQuery||Zepto);
}}(function ($){
var Mask=function (el, mask, options){
var p={
invalid: [],
getCaret: function (){
try {
var sel,
pos=0,
ctrl=el.get(0),
dSel=document.selection,
cSelStart=ctrl.selectionStart;
if(dSel&&navigator.appVersion.indexOf('MSIE 10')===-1){
sel=dSel.createRange();
sel.moveStart('character', -p.val().length);
pos=sel.text.length;
}
else if(cSelStart||cSelStart==='0'){
pos=cSelStart;
}
return pos;
} catch (e){}},
setCaret: function(pos){
try {
if(el.is(':focus')){
var range, ctrl=el.get(0);
pos +=1;
if(ctrl.setSelectionRange){
ctrl.setSelectionRange(pos, pos);
}else{
range=ctrl.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}}
} catch (e){}},
events: function(){
el
.on('keydown.mask', function(e){
el.data('mask-keycode', e.keyCode||e.which);
})
.on($.jMaskGlobals.useInput ? 'input.mask':'keyup.mask', p.behaviour)
.on('paste.mask drop.mask', function(){
setTimeout(function(){
el.keydown().keyup();
}, 100);
})
.on('change.mask', function(){
el.data('changed', true);
})
.on('blur.mask', function(){
if(oldValue!==p.val()&&!el.data('changed')){
el.trigger('change');
}
el.data('changed', false);
})
.on('blur.mask', function(){
oldValue=p.val();
})
.on('focus.mask', function (e){
if(options.selectOnFocus===true){
$(e.target).select();
}})
.on('focusout.mask', function(){
if(options.clearIfNotMatch&&!regexMask.test(p.val())){
p.val('');
}});
},
getRegexMask: function(){
var maskChunks=[], translation, pattern, optional, recursive, oRecursive, r;
for (var i=0; i < mask.length; i++){
translation=jMask.translation[mask.charAt(i)];
if(translation){
pattern=translation.pattern.toString().replace(/.{1}$|^.{1}/g, '');
optional=translation.optional;
recursive=translation.recursive;
if(recursive){
maskChunks.push(mask.charAt(i));
oRecursive={digit: mask.charAt(i), pattern: pattern};}else{
maskChunks.push(!optional&&!recursive ? pattern:(pattern + '?'));
}}else{
maskChunks.push(mask.charAt(i).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
}}
r=maskChunks.join('');
if(oRecursive){
r=r.replace(new RegExp('(' + oRecursive.digit + '(.*' + oRecursive.digit + ')?)'), '($1)?')
.replace(new RegExp(oRecursive.digit, 'g'), oRecursive.pattern);
}
return new RegExp(r);
},
destroyEvents: function(){
el.off(['input', 'keydown', 'keyup', 'paste', 'drop', 'blur', 'focusout', ''].join('.mask '));
},
val: function(v){
var isInput=el.is('input'),
method=isInput ? 'val':'text',
r;
if(arguments.length > 0){
if(el[method]()!==v){
el[method](v);
}
r=el;
}else{
r=el[method]();
}
return r;
},
getMCharsBeforeCount: function(index, onCleanVal){
for (var count=0, i=0, maskL=mask.length; i < maskL&&i < index; i++){
if(!jMask.translation[mask.charAt(i)]){
index=onCleanVal ? index + 1:index;
count++;
}}
return count;
},
caretPos: function (originalCaretPos, oldLength, newLength, maskDif){
var translation=jMask.translation[mask.charAt(Math.min(originalCaretPos - 1, mask.length - 1))];
return !translation ? p.caretPos(originalCaretPos + 1, oldLength, newLength, maskDif)
: Math.min(originalCaretPos + newLength - oldLength - maskDif, newLength);
},
behaviour: function(e){
e=e||window.event;
p.invalid=[];
var keyCode=el.data('mask-keycode');
if($.inArray(keyCode, jMask.byPassKeys)===-1){
var caretPos=p.getCaret(),
currVal=p.val(),
currValL=currVal.length,
newVal=p.getMasked(),
newValL=newVal.length,
maskDif=p.getMCharsBeforeCount(newValL - 1) - p.getMCharsBeforeCount(currValL - 1),
changeCaret=caretPos < currValL;
p.val(newVal);
if(changeCaret){
(!(keyCode===8||keyCode===46))
? caretPos=p.caretPos(caretPos, currValL, newValL, maskDif)
: caretPos -=1;
p.setCaret(caretPos);
}
return p.callbacks(e);
}},
getMasked: function(skipMaskChars, val){
var buf=[],
value=val===undefined ? p.val():val + '',
m=0, maskLen=mask.length,
v=0, valLen=value.length,
offset=1, addMethod='push',
resetPos=-1,
lastMaskChar,
check;
if(options.reverse){
addMethod='unshift';
offset=-1;
lastMaskChar=0;
m=maskLen - 1;
v=valLen - 1;
check=function (){
return m > -1&&v > -1;
};}else{
lastMaskChar=maskLen - 1;
check=function (){
return m < maskLen&&v < valLen;
};}
var lastUntranslatedMaskChar;
while (check()){
var maskDigit=mask.charAt(m),
valDigit=value.charAt(v),
translation=jMask.translation[maskDigit];
if(translation){
if(valDigit.match(translation.pattern)){
buf[addMethod](valDigit);
if(translation.recursive){
if(resetPos===-1){
resetPos=m;
}else if(m===lastMaskChar){
m=resetPos - offset;
}
if(lastMaskChar===resetPos){
m -=offset;
}}
m +=offset;
}else if(valDigit===lastUntranslatedMaskChar){
lastUntranslatedMaskChar=undefined;
}else if(translation.optional){
m +=offset;
v -=offset;
}else if(translation.fallback){
buf[addMethod](translation.fallback);
m +=offset;
v -=offset;
}else{
p.invalid.push({p: v, v: valDigit, e: translation.pattern});
}
v +=offset;
}else{
if(!skipMaskChars){
buf[addMethod](maskDigit);
}
if(valDigit===maskDigit){
v +=offset;
}else{
lastUntranslatedMaskChar=maskDigit;
}
m +=offset;
}}
var lastMaskCharDigit=mask.charAt(lastMaskChar);
if(maskLen===valLen + 1&&!jMask.translation[lastMaskCharDigit]){
buf.push(lastMaskCharDigit);
}
return buf.join('');
},
callbacks: function (e){
var val=p.val(),
changed=val!==oldValue,
defaultArgs=[val, e, el, options],
callback=function(name, criteria, args){
if(typeof options[name]==='function'&&criteria){
options[name].apply(this, args);
}};
callback('onChange', changed===true, defaultArgs);
callback('onKeyPress', changed===true, defaultArgs);
callback('onComplete', val.length===mask.length, defaultArgs);
callback('onInvalid', p.invalid.length > 0, [val, e, el, p.invalid, options]);
}};
el=$(el);
var jMask=this, oldValue=p.val(), regexMask;
mask=typeof mask==='function' ? mask(p.val(), undefined, el,  options):mask;
jMask.mask=mask;
jMask.options=options;
jMask.remove=function(){
var caret=p.getCaret();
p.destroyEvents();
p.val(jMask.getCleanVal());
p.setCaret(caret - p.getMCharsBeforeCount(caret));
return el;
};
jMask.getCleanVal=function(){
return p.getMasked(true);
};
jMask.getMaskedVal=function(val){
return p.getMasked(false, val);
};
jMask.init=function(onlyMask){
onlyMask=onlyMask||false;
options=options||{};
jMask.clearIfNotMatch=$.jMaskGlobals.clearIfNotMatch;
jMask.byPassKeys=$.jMaskGlobals.byPassKeys;
jMask.translation=$.extend({}, $.jMaskGlobals.translation, options.translation);
jMask=$.extend(true, {}, jMask, options);
regexMask=p.getRegexMask();
if(onlyMask){
p.events();
p.val(p.getMasked());
}else{
if(options.placeholder){
el.attr('placeholder' , options.placeholder);
}
if(el.data('mask')){
el.attr('autocomplete', 'off');
}
for (var i=0, maxlength=true; i < mask.length; i++){
var translation=jMask.translation[mask.charAt(i)];
if(translation&&translation.recursive){
maxlength=false;
break;
}}
if(maxlength){
el.attr('maxlength', mask.length);
}
p.destroyEvents();
p.events();
var caret=p.getCaret();
p.val(p.getMasked());
p.setCaret(caret + p.getMCharsBeforeCount(caret, true));
}};
jMask.init(!el.is('input'));
};
$.maskWatchers={};
var HTMLAttributes=function (){
var input=$(this),
options={},
prefix='data-mask-',
mask=input.attr('data-mask');
if(input.attr(prefix + 'reverse')){
options.reverse=true;
}
if(input.attr(prefix + 'clearifnotmatch')){
options.clearIfNotMatch=true;
}
if(input.attr(prefix + 'selectonfocus')==='true'){
options.selectOnFocus=true;
}
if(notSameMaskObject(input, mask, options)){
return input.data('mask', new Mask(this, mask, options));
}},
notSameMaskObject=function(field, mask, options){
options=options||{};
var maskObject=$(field).data('mask'),
stringify=JSON.stringify,
value=$(field).val()||$(field).text();
try {
if(typeof mask==='function'){
mask=mask(value);
}
return typeof maskObject!=='object'||stringify(maskObject.options)!==stringify(options)||maskObject.mask!==mask;
} catch (e){}},
eventSupported=function(eventName){
var el=document.createElement('div'), isSupported;
eventName='on' + eventName;
isSupported=(eventName in el);
if(!isSupported){
el.setAttribute(eventName, 'return;');
isSupported=typeof el[eventName]==='function';
}
el=null;
return isSupported;
};
$.fn.mask=function(mask, options){
options=options||{};
var selector=this.selector,
globals=$.jMaskGlobals,
interval=globals.watchInterval,
watchInputs=options.watchInputs||globals.watchInputs,
maskFunction=function(){
if(notSameMaskObject(this, mask, options)){
return $(this).data('mask', new Mask(this, mask, options));
}};
$(this).each(maskFunction);
if(selector&&selector!==''&&watchInputs){
clearInterval($.maskWatchers[selector]);
$.maskWatchers[selector]=setInterval(function(){
$(document).find(selector).each(maskFunction);
}, interval);
}
return this;
};
$.fn.masked=function(val){
return this.data('mask').getMaskedVal(val);
};
$.fn.unmask=function(){
clearInterval($.maskWatchers[this.selector]);
delete $.maskWatchers[this.selector];
return this.each(function(){
var dataMask=$(this).data('mask');
if(dataMask){
dataMask.remove().removeData('mask');
}});
};
$.fn.cleanVal=function(){
return this.data('mask').getCleanVal();
};
$.applyDataMask=function(selector){
selector=selector||$.jMaskGlobals.maskElements;
var $selector=(selector instanceof $) ? selector:$(selector);
$selector.filter($.jMaskGlobals.dataMaskAttr).each(HTMLAttributes);
};
var globals={
maskElements: 'input,td,span,div',
dataMaskAttr: '*[data-mask]',
dataMask: true,
watchInterval: 300,
watchInputs: true,
useInput: eventSupported('input'),
watchDataMask: false,
byPassKeys: [9, 16, 17, 18, 36, 37, 38, 39, 40, 91],
translation: {
'0': {pattern: /\d/},
'9': {pattern: /\d/, optional: true},
'#': {pattern: /\d/, recursive: true},
'A': {pattern: /[a-zA-Z0-9]/},
'S': {pattern: /[a-zA-Z]/}}
};
$.jMaskGlobals=$.jMaskGlobals||{};
globals=$.jMaskGlobals=$.extend(true, {}, globals, $.jMaskGlobals);
if(globals.dataMask){
$.applyDataMask();
}
setInterval(function(){
if($.jMaskGlobals.watchDataMask){
$.applyDataMask();
}}, globals.watchInterval);
}, window.jQuery, window.Zepto));