/** * @license input mask plugin for jquery * http://github.com/robinherbots/jquery.inputmask * copyright (c) 2010 - 2014 robin herbots * licensed under the mit license (http://www.opensource.org/licenses/mit-license.php) * version: 0.0.0 */ (function ($) { if ($.fn.inputmask === undefined) { //helper functions function isinputeventsupported(eventname) { var el = document.createelement('input'), eventname = 'on' + eventname, issupported = (eventname in el); if (!issupported) { el.setattribute(eventname, 'return;'); issupported = typeof el[eventname] == 'function'; } el = null; return issupported; } function resolvealias(aliasstr, options, opts) { var aliasdefinition = opts.aliases[aliasstr]; if (aliasdefinition) { if (aliasdefinition.alias) resolvealias(aliasdefinition.alias, undefined, opts); //alias is another alias $.extend(true, opts, aliasdefinition); //merge alias definition in the options $.extend(true, opts, options); //reapply extra given options return true; } return false; } function generatemasksets(opts) { var ms = []; var genmasks = []; //used to keep track of the masks that where processed, to avoid duplicates function getmasktemplate(mask) { if (opts.numericinput) { mask = mask.split('').reverse().join(''); } var escaped = false, outcount = 0, greedy = opts.greedy, repeat = opts.repeat; if (repeat == "*") greedy = false; //if (greedy == true && opts.placeholder == "") opts.placeholder = " "; if (mask.length == 1 && greedy == false && repeat != 0) { opts.placeholder = ""; } //hide placeholder with single non-greedy mask var singlemask = $.map(mask.split(""), function (element, index) { var outelem = []; if (element == opts.escapechar) { escaped = true; } else if ((element != opts.optionalmarker.start && element != opts.optionalmarker.end) || escaped) { var maskdef = opts.definitions[element]; if (maskdef && !escaped) { for (var i = 0; i < maskdef.cardinality; i++) { outelem.push(opts.placeholder.charat((outcount + i) % opts.placeholder.length)); } } else { outelem.push(element); escaped = false; } outcount += outelem.length; return outelem; } }); //allocate repetitions var repeatedmask = singlemask.slice(); for (var i = 1; i < repeat && greedy; i++) { repeatedmask = repeatedmask.concat(singlemask.slice()); } return { "mask": repeatedmask, "repeat": repeat, "greedy": greedy }; } //test definition => {fn: regexp/function, cardinality: int, optionality: bool, newblockmarker: bool, offset: int, casing: null/upper/lower, def: definitionsymbol} function gettestingchain(mask) { if (opts.numericinput) { mask = mask.split('').reverse().join(''); } var isoptional = false, escaped = false; var newblockmarker = false; //indicates wheter the begin/ending of a block should be indicated return $.map(mask.split(""), function (element, index) { var outelem = []; if (element == opts.escapechar) { escaped = true; } else if (element == opts.optionalmarker.start && !escaped) { isoptional = true; newblockmarker = true; } else if (element == opts.optionalmarker.end && !escaped) { isoptional = false; newblockmarker = true; } else { var maskdef = opts.definitions[element]; if (maskdef && !escaped) { var prevalidators = maskdef["prevalidator"], prevalidatorsl = prevalidators ? prevalidators.length : 0; for (var i = 1; i < maskdef.cardinality; i++) { var prevalidator = prevalidatorsl >= i ? prevalidators[i - 1] : [], validator = prevalidator["validator"], cardinality = prevalidator["cardinality"]; outelem.push({ fn: validator ? typeof validator == 'string' ? new regexp(validator) : new function () { this.test = validator; } : new regexp("."), cardinality: cardinality ? cardinality : 1, optionality: isoptional, newblockmarker: isoptional == true ? newblockmarker : false, offset: 0, casing: maskdef["casing"], def: maskdef["definitionsymbol"] || element }); if (isoptional == true) //reset newblockmarker newblockmarker = false; } outelem.push({ fn: maskdef.validator ? typeof maskdef.validator == 'string' ? new regexp(maskdef.validator) : new function () { this.test = maskdef.validator; } : new regexp("."), cardinality: maskdef.cardinality, optionality: isoptional, newblockmarker: newblockmarker, offset: 0, casing: maskdef["casing"], def: maskdef["definitionsymbol"] || element }); } else { outelem.push({ fn: null, cardinality: 0, optionality: isoptional, newblockmarker: newblockmarker, offset: 0, casing: null, def: element }); escaped = false; } //reset newblockmarker newblockmarker = false; return outelem; } }); } function markoptional(maskpart) { //needed for the clearoptionaltail functionality return opts.optionalmarker.start + maskpart + opts.optionalmarker.end; } function splitfirstoptionalendpart(maskpart) { var optionalstartmarkers = 0, optionalendmarkers = 0, mpl = maskpart.length; for (var i = 0; i < mpl; i++) { if (maskpart.charat(i) == opts.optionalmarker.start) { optionalstartmarkers++; } if (maskpart.charat(i) == opts.optionalmarker.end) { optionalendmarkers++; } if (optionalstartmarkers > 0 && optionalstartmarkers == optionalendmarkers) break; } var maskparts = [maskpart.substring(0, i)]; if (i < mpl) { maskparts.push(maskpart.substring(i + 1, mpl)); } return maskparts; } function splitfirstoptionalstartpart(maskpart) { var mpl = maskpart.length; for (var i = 0; i < mpl; i++) { if (maskpart.charat(i) == opts.optionalmarker.start) { break; } } var maskparts = [maskpart.substring(0, i)]; if (i < mpl) { maskparts.push(maskpart.substring(i + 1, mpl)); } return maskparts; } function generatemask(maskprefix, maskpart, metadata) { var maskparts = splitfirstoptionalendpart(maskpart); var newmask, masktemplate; var masks = splitfirstoptionalstartpart(maskparts[0]); if (masks.length > 1) { newmask = maskprefix + masks[0] + markoptional(masks[1]) + (maskparts.length > 1 ? maskparts[1] : ""); if ($.inarray(newmask, genmasks) == -1 && newmask != "") { genmasks.push(newmask); masktemplate = getmasktemplate(newmask); ms.push({ "mask": newmask, "_buffer": masktemplate["mask"], "buffer": masktemplate["mask"].slice(), "tests": gettestingchain(newmask), "lastvalidposition": -1, "greedy": masktemplate["greedy"], "repeat": masktemplate["repeat"], "metadata": metadata }); } newmask = maskprefix + masks[0] + (maskparts.length > 1 ? maskparts[1] : ""); if ($.inarray(newmask, genmasks) == -1 && newmask != "") { genmasks.push(newmask); masktemplate = getmasktemplate(newmask); ms.push({ "mask": newmask, "_buffer": masktemplate["mask"], "buffer": masktemplate["mask"].slice(), "tests": gettestingchain(newmask), "lastvalidposition": -1, "greedy": masktemplate["greedy"], "repeat": masktemplate["repeat"], "metadata": metadata }); } if (splitfirstoptionalstartpart(masks[1]).length > 1) { //optional contains another optional generatemask(maskprefix + masks[0], masks[1] + maskparts[1], metadata); } if (maskparts.length > 1 && splitfirstoptionalstartpart(maskparts[1]).length > 1) { generatemask(maskprefix + masks[0] + markoptional(masks[1]), maskparts[1], metadata); generatemask(maskprefix + masks[0], maskparts[1], metadata); } } else { newmask = maskprefix + maskparts; if ($.inarray(newmask, genmasks) == -1 && newmask != "") { genmasks.push(newmask); masktemplate = getmasktemplate(newmask); ms.push({ "mask": newmask, "_buffer": masktemplate["mask"], "buffer": masktemplate["mask"].slice(), "tests": gettestingchain(newmask), "lastvalidposition": -1, "greedy": masktemplate["greedy"], "repeat": masktemplate["repeat"], "metadata": metadata }); } } } if ($.isfunction(opts.mask)) { //allow mask to be a preprocessing fn - should return a valid mask opts.mask = opts.mask.call(this, opts); } if ($.isarray(opts.mask)) { $.each(opts.mask, function (ndx, msk) { if (msk["mask"] != undefined) { generatemask("", msk["mask"].tostring(), msk); } else generatemask("", msk.tostring()); }); } else generatemask("", opts.mask.tostring()); return opts.greedy ? ms : ms.sort(function (a, b) { return a["mask"].length - b["mask"].length; }); } var msie10 = navigator.useragent.match(new regexp("msie 10", "i")) !== null, iphone = navigator.useragent.match(new regexp("iphone", "i")) !== null, android = navigator.useragent.match(new regexp("android.*safari.*", "i")) !== null, androidchrome = navigator.useragent.match(new regexp("android.*chrome.*", "i")) !== null, pasteevent = isinputeventsupported('paste') ? 'paste' : isinputeventsupported('input') ? 'input' : "propertychange"; //masking scope //actionobj definition see below function maskscope(masksets, activemasksetindex, opts, actionobj) { var isrtl = false, valueonfocus = getactivebuffer().join(''), $el, chromevalueoninput, skipkeypressevent = false, //safari 5.1.x - modal dialog fires keypress twice workaround skipinputevent = false, //skip when triggered from within inputmask ignorable = false; //maskset helperfunctions function getactivemaskset() { return masksets[activemasksetindex]; } function getactivetests() { return getactivemaskset()['tests']; } function getactivebuffertemplate() { return getactivemaskset()['_buffer']; } function getactivebuffer() { return getactivemaskset()['buffer']; } function isvalid(pos, c, strict) { //strict true ~ no correction or autofill strict = strict === true; //always set a value to strict to prevent possible strange behavior in the extensions function _isvalid(position, activemaskset, c, strict) { var testpos = determinetestposition(position), loopend = c ? 1 : 0, chrs = '', buffer = activemaskset["buffer"]; for (var i = activemaskset['tests'][testpos].cardinality; i > loopend; i--) { chrs += getbufferelement(buffer, testpos - (i - 1)); } if (c) { chrs += c; } //return is false or a json object => { pos: ??, c: ??} or true return activemaskset['tests'][testpos].fn != null ? activemaskset['tests'][testpos].fn.test(chrs, buffer, position, strict, opts) : (c == getbufferelement(activemaskset['_buffer'], position, true) || c == opts.skipoptionalpartcharacter) ? { "refresh": true, c: getbufferelement(activemaskset['_buffer'], position, true), pos: position } : false; } function postprocessresults(maskforwards, results) { var hasvalidactual = false; $.each(results, function (ndx, rslt) { hasvalidactual = $.inarray(rslt["activemasksetindex"], maskforwards) == -1 && rslt["result"] !== false; if (hasvalidactual) return false; }); if (hasvalidactual) { //strip maskforwards results = $.map(results, function (rslt, ndx) { if ($.inarray(rslt["activemasksetindex"], maskforwards) == -1) { return rslt; } else { masksets[rslt["activemasksetindex"]]["lastvalidposition"] = actuallvp; } }); } else { //keep maskforwards with the least forward var lowestpos = -1, lowestindex = -1, rsltvalid; $.each(results, function (ndx, rslt) { if ($.inarray(rslt["activemasksetindex"], maskforwards) != -1 && rslt["result"] !== false & (lowestpos == -1 || lowestpos > rslt["result"]["pos"])) { lowestpos = rslt["result"]["pos"]; lowestindex = rslt["activemasksetindex"]; } }); results = $.map(results, function (rslt, ndx) { if ($.inarray(rslt["activemasksetindex"], maskforwards) != -1) { if (rslt["result"]["pos"] == lowestpos) { return rslt; } else if (rslt["result"] !== false) { for (var i = pos; i < lowestpos; i++) { rsltvalid = _isvalid(i, masksets[rslt["activemasksetindex"]], masksets[lowestindex]["buffer"][i], true); if (rsltvalid === false) { masksets[rslt["activemasksetindex"]]["lastvalidposition"] = lowestpos - 1; break; } else { setbufferelement(masksets[rslt["activemasksetindex"]]["buffer"], i, masksets[lowestindex]["buffer"][i], true); masksets[rslt["activemasksetindex"]]["lastvalidposition"] = i; } } //also check check for the lowestpos with the new input rsltvalid = _isvalid(lowestpos, masksets[rslt["activemasksetindex"]], c, true); if (rsltvalid !== false) { setbufferelement(masksets[rslt["activemasksetindex"]]["buffer"], lowestpos, c, true); masksets[rslt["activemasksetindex"]]["lastvalidposition"] = lowestpos; } //console.log("ndx " + rslt["activemasksetindex"] + " validate " + masksets[rslt["activemasksetindex"]]["buffer"].join('') + " lv " + masksets[rslt["activemasksetindex"]]['lastvalidposition']); return rslt; } } }); } return results; } if (strict) { var result = _isvalid(pos, getactivemaskset(), c, strict); //only check validity in current mask when validating strict if (result === true) { result = { "pos": pos }; //always take a possible corrected maskposition into account } return result; } var results = [], result = false, currentactivemasksetindex = activemasksetindex, actualbuffer = getactivebuffer().slice(), actuallvp = getactivemaskset()["lastvalidposition"], actualprevious = seekprevious(pos), maskforwards = []; $.each(masksets, function (index, value) { if (typeof (value) == "object") { activemasksetindex = index; var maskpos = pos; var lvp = getactivemaskset()['lastvalidposition'], rsltvalid; if (lvp == actuallvp) { if ((maskpos - actuallvp) > 1) { for (var i = lvp == -1 ? 0 : lvp; i < maskpos; i++) { rsltvalid = _isvalid(i, getactivemaskset(), actualbuffer[i], true); if (rsltvalid === false) { break; } else { setbufferelement(getactivebuffer(), i, actualbuffer[i], true); if (rsltvalid === true) { rsltvalid = { "pos": i }; //always take a possible corrected maskposition into account } var newvalidposition = rsltvalid.pos || i; if (getactivemaskset()['lastvalidposition'] < newvalidposition) getactivemaskset()['lastvalidposition'] = newvalidposition; //set new position from isvalid } } } //does the input match on a further position? if (!ismask(maskpos) && !_isvalid(maskpos, getactivemaskset(), c, strict)) { var maxforward = seeknext(maskpos) - maskpos; for (var fw = 0; fw < maxforward; fw++) { if (_isvalid(++maskpos, getactivemaskset(), c, strict) !== false) break; } maskforwards.push(activemasksetindex); //console.log('maskforward ' + activemasksetindex + " pos " + pos + " maskpos " + maskpos); } } if (getactivemaskset()['lastvalidposition'] >= actuallvp || activemasksetindex == currentactivemasksetindex) { if (maskpos >= 0 && maskpos < getmasklength()) { result = _isvalid(maskpos, getactivemaskset(), c, strict); if (result !== false) { if (result === true) { result = { "pos": maskpos }; //always take a possible corrected maskposition into account } var newvalidposition = result.pos || maskpos; if (getactivemaskset()['lastvalidposition'] < newvalidposition) getactivemaskset()['lastvalidposition'] = newvalidposition; //set new position from isvalid } //console.log("pos " + pos + " ndx " + activemasksetindex + " validate " + getactivebuffer().join('') + " lv " + getactivemaskset()['lastvalidposition']); results.push({ "activemasksetindex": index, "result": result }); } } } }); activemasksetindex = currentactivemasksetindex; //reset activemasksetindex return postprocessresults(maskforwards, results); //return results of the multiple mask validations } function determineactivemasksetindex() { var currentmasksetindex = activemasksetindex, highestvalid = { "activemasksetindex": 0, "lastvalidposition": -1, "next": -1 }; $.each(masksets, function (index, value) { if (typeof (value) == "object") { activemasksetindex = index; if (getactivemaskset()['lastvalidposition'] > highestvalid['lastvalidposition']) { highestvalid["activemasksetindex"] = index; highestvalid["lastvalidposition"] = getactivemaskset()['lastvalidposition']; highestvalid["next"] = seeknext(getactivemaskset()['lastvalidposition']); } else if (getactivemaskset()['lastvalidposition'] == highestvalid['lastvalidposition'] && (highestvalid['next'] == -1 || highestvalid['next'] > seeknext(getactivemaskset()['lastvalidposition']))) { highestvalid["activemasksetindex"] = index; highestvalid["lastvalidposition"] = getactivemaskset()['lastvalidposition']; highestvalid["next"] = seeknext(getactivemaskset()['lastvalidposition']); } } }); activemasksetindex = highestvalid["lastvalidposition"] != -1 && masksets[currentmasksetindex]["lastvalidposition"] == highestvalid["lastvalidposition"] ? currentmasksetindex : highestvalid["activemasksetindex"]; if (currentmasksetindex != activemasksetindex) { clearbuffer(getactivebuffer(), seeknext(highestvalid["lastvalidposition"]), getmasklength()); getactivemaskset()["writeoutbuffer"] = true; } $el.data('_inputmask')['activemasksetindex'] = activemasksetindex; //store the activemasksetindex } function ismask(pos) { var testpos = determinetestposition(pos); var test = getactivetests()[testpos]; return test != undefined ? test.fn : false; } function determinetestposition(pos) { return pos % getactivetests().length; } function getmasklength() { return opts.getmasklength(getactivebuffertemplate(), getactivemaskset()['greedy'], getactivemaskset()['repeat'], getactivebuffer(), opts); } //pos: from position function seeknext(pos) { var maskl = getmasklength(); if (pos >= maskl) return maskl; var position = pos; while (++position < maskl && !ismask(position)) { } return position; } //pos: from position function seekprevious(pos) { var position = pos; if (position <= 0) return 0; while (--position > 0 && !ismask(position)) { } return position; } function setbufferelement(buffer, position, element, autoprepare) { if (autoprepare) position = preparebuffer(buffer, position); var test = getactivetests()[determinetestposition(position)]; var elem = element; if (elem != undefined && test != undefined) { switch (test.casing) { case "upper": elem = element.touppercase(); break; case "lower": elem = element.tolowercase(); break; } } buffer[position] = elem; } function getbufferelement(buffer, position, autoprepare) { if (autoprepare) position = preparebuffer(buffer, position); return buffer[position]; } //needed to handle the non-greedy mask repetitions function preparebuffer(buffer, position) { var j; while (buffer[position] == undefined && buffer.length < getmasklength()) { j = 0; while (getactivebuffertemplate()[j] !== undefined) { //add a new buffer buffer.push(getactivebuffertemplate()[j++]); } } return position; } function writebuffer(input, buffer, caretpos) { input._valueset(buffer.join('')); if (caretpos != undefined) { caret(input, caretpos); } } function clearbuffer(buffer, start, end, stripnomasks) { for (var i = start, maskl = getmasklength() ; i < end && i < maskl; i++) { if (stripnomasks === true) { if (!ismask(i)) setbufferelement(buffer, i, ""); } else setbufferelement(buffer, i, getbufferelement(getactivebuffertemplate().slice(), i, true)); } } function setretargetplaceholder(buffer, pos) { var testpos = determinetestposition(pos); setbufferelement(buffer, pos, getbufferelement(getactivebuffertemplate(), testpos)); } function getplaceholder(pos) { return opts.placeholder.charat(pos % opts.placeholder.length); } function checkval(input, writeout, strict, nptvl, intellicheck) { var inputvalue = nptvl != undefined ? nptvl.slice() : truncateinput(input._valueget()).split(''); $.each(masksets, function (ndx, ms) { if (typeof (ms) == "object") { ms["buffer"] = ms["_buffer"].slice(); ms["lastvalidposition"] = -1; ms["p"] = -1; } }); if (strict !== true) activemasksetindex = 0; if (writeout) input._valueset(""); //initial clear var ml = getmasklength(); $.each(inputvalue, function (ndx, charcode) { if (intellicheck === true) { var p = getactivemaskset()["p"], lvp = p == -1 ? p : seekprevious(p), pos = lvp == -1 ? ndx : seeknext(lvp); if ($.inarray(charcode, getactivebuffertemplate().slice(lvp + 1, pos)) == -1) { keypressevent.call(input, undefined, true, charcode.charcodeat(0), writeout, strict, ndx); } } else { keypressevent.call(input, undefined, true, charcode.charcodeat(0), writeout, strict, ndx); } }); if (strict === true && getactivemaskset()["p"] != -1) { getactivemaskset()["lastvalidposition"] = seekprevious(getactivemaskset()["p"]); } } function escaperegex(str) { return $.inputmask.escaperegex.call(this, str); } function truncateinput(inputvalue) { return inputvalue.replace(new regexp("(" + escaperegex(getactivebuffertemplate().join('')) + ")*$"), ""); } function clearoptionaltail(input) { var buffer = getactivebuffer(), tmpbuffer = buffer.slice(), testpos, pos; for (var pos = tmpbuffer.length - 1; pos >= 0; pos--) { var testpos = determinetestposition(pos); if (getactivetests()[testpos].optionality) { if (!ismask(pos) || !isvalid(pos, buffer[pos], true)) tmpbuffer.pop(); else break; } else break; } writebuffer(input, tmpbuffer); } function unmaskedvalue($input, skipdatepickercheck) { if (getactivetests() && (skipdatepickercheck === true || !$input.hasclass('hasdatepicker'))) { //checkval(input, false, true); var umvalue = $.map(getactivebuffer(), function (element, index) { return ismask(index) && isvalid(index, element, true) ? element : null; }); var unmaskedvalue = (isrtl ? umvalue.reverse() : umvalue).join(''); return opts.onunmask != undefined ? opts.onunmask.call(this, getactivebuffer().join(''), unmaskedvalue) : unmaskedvalue; } else { return $input[0]._valueget(); } } function translateposition(pos) { if (isrtl && typeof pos == 'number' && (!opts.greedy || opts.placeholder != "")) { var bffrlght = getactivebuffer().length; pos = bffrlght - pos; } return pos; } function caret(input, begin, end) { var npt = input.jquery && input.length > 0 ? input[0] : input, range; if (typeof begin == 'number') { begin = translateposition(begin); end = translateposition(end); if (!$(input).is(':visible')) { return; } end = (typeof end == 'number') ? end : begin; npt.scrollleft = npt.scrollwidth; if (opts.insertmode == false && begin == end) end++; //set visualization for insert/overwrite mode if (npt.setselectionrange) { npt.selectionstart = begin; npt.selectionend = android ? begin : end; } else if (npt.createtextrange) { range = npt.createtextrange(); range.collapse(true); range.moveend('character', end); range.movestart('character', begin); range.select(); } } else { if (!$(input).is(':visible')) { return { "begin": 0, "end": 0 }; } if (npt.setselectionrange) { begin = npt.selectionstart; end = npt.selectionend; } else if (document.selection && document.selection.createrange) { range = document.selection.createrange(); begin = 0 - range.duplicate().movestart('character', -100000); end = begin + range.text.length; } begin = translateposition(begin); end = translateposition(end); return { "begin": begin, "end": end }; } } function iscomplete(buffer) { //return true / false / undefined (repeat *) if (opts.repeat == "*") return undefined; var complete = false, highestvalidposition = 0, currentactivemasksetindex = activemasksetindex; $.each(masksets, function (ndx, ms) { if (typeof (ms) == "object") { activemasksetindex = ndx; var aml = seekprevious(getmasklength()); if (ms["lastvalidposition"] >= highestvalidposition && ms["lastvalidposition"] == aml) { var mscomplete = true; for (var i = 0; i <= aml; i++) { var mask = ismask(i), testpos = determinetestposition(i); if ((mask && (buffer[i] == undefined || buffer[i] == getplaceholder(i))) || (!mask && buffer[i] != getactivebuffertemplate()[testpos])) { mscomplete = false; break; } } complete = complete || mscomplete; if (complete) //break loop return false; } highestvalidposition = ms["lastvalidposition"]; } }); activemasksetindex = currentactivemasksetindex; //reset activemaskset return complete; } function isselection(begin, end) { return isrtl ? (begin - end) > 1 || ((begin - end) == 1 && opts.insertmode) : (end - begin) > 1 || ((end - begin) == 1 && opts.insertmode); } //private functions function installeventruler(npt) { var events = $._data(npt).events; $.each(events, function (eventtype, eventhandlers) { $.each(eventhandlers, function (ndx, eventhandler) { if (eventhandler.namespace == "inputmask") { if (eventhandler.type != "setvalue") { var handler = eventhandler.handler; eventhandler.handler = function (e) { if (this.readonly || this.disabled) e.preventdefault; else return handler.apply(this, arguments); }; } } }); }); } function patchvalueproperty(npt) { var valueproperty; if (object.getownpropertydescriptor) valueproperty = object.getownpropertydescriptor(npt, "value"); if (valueproperty && valueproperty.get) { if (!npt._valueget) { var valueget = valueproperty.get; var valueset = valueproperty.set; npt._valueget = function () { return isrtl ? valueget.call(this).split('').reverse().join('') : valueget.call(this); }; npt._valueset = function (value) { valueset.call(this, isrtl ? value.split('').reverse().join('') : value); }; object.defineproperty(npt, "value", { get: function () { var $self = $(this), inputdata = $(this).data('_inputmask'), masksets = inputdata['masksets'], activemasksetindex = inputdata['activemasksetindex']; return inputdata && inputdata['opts'].autounmask ? $self.inputmask('unmaskedvalue') : valueget.call(this) != masksets[activemasksetindex]['_buffer'].join('') ? valueget.call(this) : ''; }, set: function (value) { valueset.call(this, value); $(this).triggerhandler('setvalue.inputmask'); } }); } } else if (document.__lookupgetter__ && npt.__lookupgetter__("value")) { if (!npt._valueget) { var valueget = npt.__lookupgetter__("value"); var valueset = npt.__lookupsetter__("value"); npt._valueget = function () { return isrtl ? valueget.call(this).split('').reverse().join('') : valueget.call(this); }; npt._valueset = function (value) { valueset.call(this, isrtl ? value.split('').reverse().join('') : value); }; npt.__definegetter__("value", function () { var $self = $(this), inputdata = $(this).data('_inputmask'), masksets = inputdata['masksets'], activemasksetindex = inputdata['activemasksetindex']; return inputdata && inputdata['opts'].autounmask ? $self.inputmask('unmaskedvalue') : valueget.call(this) != masksets[activemasksetindex]['_buffer'].join('') ? valueget.call(this) : ''; }); npt.__definesetter__("value", function (value) { valueset.call(this, value); $(this).triggerhandler('setvalue.inputmask'); }); } } else { if (!npt._valueget) { npt._valueget = function () { return isrtl ? this.value.split('').reverse().join('') : this.value; }; npt._valueset = function (value) { this.value = isrtl ? value.split('').reverse().join('') : value; }; } if ($.valhooks.text == undefined || $.valhooks.text.inputmaskpatch != true) { var valueget = $.valhooks.text && $.valhooks.text.get ? $.valhooks.text.get : function (elem) { return elem.value; }; var valueset = $.valhooks.text && $.valhooks.text.set ? $.valhooks.text.set : function (elem, value) { elem.value = value; return elem; }; jquery.extend($.valhooks, { text: { get: function (elem) { var $elem = $(elem); if ($elem.data('_inputmask')) { if ($elem.data('_inputmask')['opts'].autounmask) return $elem.inputmask('unmaskedvalue'); else { var result = valueget(elem), inputdata = $elem.data('_inputmask'), masksets = inputdata['masksets'], activemasksetindex = inputdata['activemasksetindex']; return result != masksets[activemasksetindex]['_buffer'].join('') ? result : ''; } } else return valueget(elem); }, set: function (elem, value) { var $elem = $(elem); var result = valueset(elem, value); if ($elem.data('_inputmask')) $elem.triggerhandler('setvalue.inputmask'); return result; }, inputmaskpatch: true } }); } } } //shift chars to left from start to end and put c at end position if defined function shiftl(start, end, c, maskjumps) { var buffer = getactivebuffer(); if (maskjumps !== false) //jumping over nonmask position while (!ismask(start) && start - 1 >= 0) start--; for (var i = start; i < end && i < getmasklength() ; i++) { if (ismask(i)) { setretargetplaceholder(buffer, i); var j = seeknext(i); var p = getbufferelement(buffer, j); if (p != getplaceholder(j)) { if (j < getmasklength() && isvalid(i, p, true) !== false && getactivetests()[determinetestposition(i)].def == getactivetests()[determinetestposition(j)].def) { setbufferelement(buffer, i, p, true); } else { if (ismask(i)) break; } } } else { setretargetplaceholder(buffer, i); } } if (c != undefined) setbufferelement(buffer, seekprevious(end), c); if (getactivemaskset()["greedy"] == false) { var trbuffer = truncateinput(buffer.join('')).split(''); buffer.length = trbuffer.length; for (var i = 0, bl = buffer.length; i < bl; i++) { buffer[i] = trbuffer[i]; } if (buffer.length == 0) getactivemaskset()["buffer"] = getactivebuffertemplate().slice(); } return start; //return the used start position } function shiftr(start, end, c) { var buffer = getactivebuffer(); if (getbufferelement(buffer, start, true) != getplaceholder(start)) { for (var i = seekprevious(end) ; i > start && i >= 0; i--) { if (ismask(i)) { var j = seekprevious(i); var t = getbufferelement(buffer, j); if (t != getplaceholder(j)) { if (isvalid(j, t, true) !== false && getactivetests()[determinetestposition(i)].def == getactivetests()[determinetestposition(j)].def) { setbufferelement(buffer, i, t, true); setretargetplaceholder(buffer, j); } //else break; } } else setretargetplaceholder(buffer, i); } } if (c != undefined && getbufferelement(buffer, start) == getplaceholder(start)) setbufferelement(buffer, start, c); var lengthbefore = buffer.length; if (getactivemaskset()["greedy"] == false) { var trbuffer = truncateinput(buffer.join('')).split(''); buffer.length = trbuffer.length; for (var i = 0, bl = buffer.length; i < bl; i++) { buffer[i] = trbuffer[i]; } if (buffer.length == 0) getactivemaskset()["buffer"] = getactivebuffertemplate().slice(); } return end - (lengthbefore - buffer.length); //return new start position } function handleremove(input, k, pos) { if (opts.numericinput || isrtl) { switch (k) { case opts.keycode.backspace: k = opts.keycode.delete; break; case opts.keycode.delete: k = opts.keycode.backspace; break; } if (isrtl) { var pend = pos.end; pos.end = pos.begin; pos.begin = pend; } } var isselection = true; if (pos.begin == pos.end) { var posbegin = k == opts.keycode.backspace ? pos.begin - 1 : pos.begin; if (opts.isnumeric && opts.radixpoint != "" && getactivebuffer()[posbegin] == opts.radixpoint) { pos.begin = (getactivebuffer().length - 1 == posbegin) /* radixpoint is latest? delete it */ ? pos.begin : k == opts.keycode.backspace ? posbegin : seeknext(posbegin); pos.end = pos.begin; } isselection = false; if (k == opts.keycode.backspace) pos.begin--; else if (k == opts.keycode.delete) pos.end++; } else if (pos.end - pos.begin == 1 && !opts.insertmode) { isselection = false; if (k == opts.keycode.backspace) pos.begin--; } clearbuffer(getactivebuffer(), pos.begin, pos.end); var ml = getmasklength(); if (opts.greedy == false) { shiftl(pos.begin, ml, undefined, !isrtl && (k == opts.keycode.backspace && !isselection)); } else { var newpos = pos.begin; for (var i = pos.begin; i < pos.end; i++) { //seeknext to skip placeholders at start in selection if (ismask(i) || !isselection) newpos = shiftl(pos.begin, ml, undefined, !isrtl && (k == opts.keycode.backspace && !isselection)); } if (!isselection) pos.begin = newpos; } var firstmaskpos = seeknext(-1); clearbuffer(getactivebuffer(), pos.begin, pos.end, true); checkval(input, false, masksets[1] == undefined || firstmaskpos >= pos.end, getactivebuffer()); if (getactivemaskset()['lastvalidposition'] < firstmaskpos) { getactivemaskset()["lastvalidposition"] = -1; getactivemaskset()["p"] = firstmaskpos; } else { getactivemaskset()["p"] = pos.begin; } } function keydownevent(e) { //safari 5.1.x - modal dialog fires keypress twice workaround skipkeypressevent = false; var input = this, $input = $(input), k = e.keycode, pos = caret(input); //backspace, delete, and escape get special treatment if (k == opts.keycode.backspace || k == opts.keycode.delete || (iphone && k == 127) || e.ctrlkey && k == 88) { //backspace/delete e.preventdefault(); //stop default action but allow propagation if (k == 88) valueonfocus = getactivebuffer().join(''); handleremove(input, k, pos); determineactivemasksetindex(); writebuffer(input, getactivebuffer(), getactivemaskset()["p"]); if (input._valueget() == getactivebuffertemplate().join('')) $input.trigger('cleared'); if (opts.showtooltip) { //update tooltip $input.prop("title", getactivemaskset()["mask"]); } } else if (k == opts.keycode.end || k == opts.keycode.page_down) { //when end or page_down pressed set position at lastmatch settimeout(function () { var caretpos = seeknext(getactivemaskset()["lastvalidposition"]); if (!opts.insertmode && caretpos == getmasklength() && !e.shiftkey) caretpos--; caret(input, e.shiftkey ? pos.begin : caretpos, caretpos); }, 0); } else if ((k == opts.keycode.home && !e.shiftkey) || k == opts.keycode.page_up) { //home or page_up caret(input, 0, e.shiftkey ? pos.begin : 0); } else if (k == opts.keycode.escape || (k == 90 && e.ctrlkey)) { //escape && undo checkval(input, true, false, valueonfocus.split('')); $input.click(); } else if (k == opts.keycode.insert && !(e.shiftkey || e.ctrlkey)) { //insert opts.insertmode = !opts.insertmode; caret(input, !opts.insertmode && pos.begin == getmasklength() ? pos.begin - 1 : pos.begin); } else if (opts.insertmode == false && !e.shiftkey) { if (k == opts.keycode.right) { settimeout(function () { var caretpos = caret(input); caret(input, caretpos.begin); }, 0); } else if (k == opts.keycode.left) { settimeout(function () { var caretpos = caret(input); caret(input, caretpos.begin - 1); }, 0); } } var currentcaretpos = caret(input); if (opts.onkeydown.call(this, e, getactivebuffer(), opts) === true) //extra stuff to execute on keydown caret(input, currentcaretpos.begin, currentcaretpos.end); ignorable = $.inarray(k, opts.ignorables) != -1; } function keypressevent(e, checkval, k, writeout, strict, ndx) { //safari 5.1.x - modal dialog fires keypress twice workaround if (k == undefined && skipkeypressevent) return false; skipkeypressevent = true; var input = this, $input = $(input); e = e || window.event; var k = checkval ? k : (e.which || e.charcode || e.keycode); if (checkval !== true && (!(e.ctrlkey && e.altkey) && (e.ctrlkey || e.metakey || ignorable))) { return true; } else { if (k) { //special treat the decimal separator if (checkval !== true && k == 46 && e.shiftkey == false && opts.radixpoint == ",") k = 44; var pos, results, result, c = string.fromcharcode(k); if (checkval) { var pcaret = strict ? ndx : getactivemaskset()["lastvalidposition"] + 1; pos = { begin: pcaret, end: pcaret }; } else { pos = caret(input); } //should we clear a possible selection?? var isslctn = isselection(pos.begin, pos.end), redeterminelvp = false, initialindex = activemasksetindex; if (isslctn) { activemasksetindex = initialindex; $.each(masksets, function (ndx, lmnt) { //init undobuffer for recovery when not valid if (typeof (lmnt) == "object") { activemasksetindex = ndx; getactivemaskset()["undobuffer"] = getactivebuffer().join(''); } }); handleremove(input, opts.keycode.delete, pos); if (!opts.insertmode) { //preserve some space $.each(masksets, function (ndx, lmnt) { if (typeof (lmnt) == "object") { activemasksetindex = ndx; shiftr(pos.begin, getmasklength()); getactivemaskset()["lastvalidposition"] = seeknext(getactivemaskset()["lastvalidposition"]); } }); } activemasksetindex = initialindex; //restore index } var radixposition = getactivebuffer().join('').indexof(opts.radixpoint); if (opts.isnumeric && checkval !== true && radixposition != -1) { if (opts.greedy && pos.begin <= radixposition) { pos.begin = seekprevious(pos.begin); pos.end = pos.begin; } else if (c == opts.radixpoint) { pos.begin = radixposition; pos.end = pos.begin; } } var p = pos.begin; results = isvalid(p, c, strict); if (strict === true) results = [{ "activemasksetindex": activemasksetindex, "result": results }]; var minimalforwardposition = -1; $.each(results, function (index, result) { activemasksetindex = result["activemasksetindex"]; getactivemaskset()["writeoutbuffer"] = true; var np = result["result"]; if (np !== false) { var refresh = false, buffer = getactivebuffer(); if (np !== true) { refresh = np["refresh"]; //only rewrite buffer from isvalid p = np.pos != undefined ? np.pos : p; //set new position from isvalid c = np.c != undefined ? np.c : c; //set new char from isvalid } if (refresh !== true) { if (opts.insertmode == true) { var lastunmaskedposition = getmasklength(); var bfrclone = buffer.slice(); while (getbufferelement(bfrclone, lastunmaskedposition, true) != getplaceholder(lastunmaskedposition) && lastunmaskedposition >= p) { lastunmaskedposition = lastunmaskedposition == 0 ? -1 : seekprevious(lastunmaskedposition); } if (lastunmaskedposition >= p) { shiftr(p, getmasklength(), c); //shift the lvp if needed var lvp = getactivemaskset()["lastvalidposition"], nlvp = seeknext(lvp); if (nlvp != getmasklength() && lvp >= p && (getbufferelement(getactivebuffer(), nlvp, true) != getplaceholder(nlvp))) { getactivemaskset()["lastvalidposition"] = nlvp; } } else getactivemaskset()["writeoutbuffer"] = false; } else setbufferelement(buffer, p, c, true); if (minimalforwardposition == -1 || minimalforwardposition > seeknext(p)) { minimalforwardposition = seeknext(p); } } else if (!strict) { var nextpos = p < getmasklength() ? p + 1 : p; if (minimalforwardposition == -1 || minimalforwardposition > nextpos) { minimalforwardposition = nextpos; } } if (minimalforwardposition > getactivemaskset()["p"]) getactivemaskset()["p"] = minimalforwardposition; //needed for checkval strict } }); if (strict !== true) { activemasksetindex = initialindex; determineactivemasksetindex(); } if (writeout !== false) { $.each(results, function (ndx, rslt) { if (rslt["activemasksetindex"] == activemasksetindex) { result = rslt; return false; } }); if (result != undefined) { var self = this; settimeout(function () { opts.onkeyvalidation.call(self, result["result"], opts); }, 0); if (getactivemaskset()["writeoutbuffer"] && result["result"] !== false) { var buffer = getactivebuffer(); var newcaretposition; if (checkval) { newcaretposition = undefined; } else if (opts.numericinput) { if (p > radixposition) { newcaretposition = seekprevious(minimalforwardposition); } else if (c == opts.radixpoint) { newcaretposition = minimalforwardposition - 1; } else newcaretposition = seekprevious(minimalforwardposition - 1); } else { newcaretposition = minimalforwardposition; } writebuffer(input, buffer, newcaretposition); if (checkval !== true) { settimeout(function () { //timeout needed for ie if (iscomplete(buffer) === true) $input.trigger("complete"); skipinputevent = true; $input.trigger("input"); }, 0); } } else if (isslctn) { getactivemaskset()["buffer"] = getactivemaskset()["undobuffer"].split(''); } } } if (opts.showtooltip) { //update tooltip $input.prop("title", getactivemaskset()["mask"]); } //needed for ie8 and below if (e) e.preventdefault ? e.preventdefault() : e.returnvalue = false; } } } function keyupevent(e) { var $input = $(this), input = this, k = e.keycode, buffer = getactivebuffer(); if (androidchrome && k == opts.keycode.backspace) { if (chromevalueoninput == input._valueget()) keydownevent.call(this, e); } opts.onkeyup.call(this, e, buffer, opts); //extra stuff to execute on keyup if (k == opts.keycode.tab && opts.showmaskonfocus) { if ($input.hasclass('focus.inputmask') && input._valueget().length == 0) { buffer = getactivebuffertemplate().slice(); writebuffer(input, buffer); caret(input, 0); valueonfocus = getactivebuffer().join(''); } else { writebuffer(input, buffer); if (buffer.join('') == getactivebuffertemplate().join('') && $.inarray(opts.radixpoint, buffer) != -1) { caret(input, translateposition(0)); $input.click(); } else caret(input, translateposition(0), translateposition(getmasklength())); } } } function inputevent(e) { if (skipinputevent === true) { skipinputevent = false; return true; } var input = this, $input = $(input); chromevalueoninput = getactivebuffer().join(''); checkval(input, false, false); writebuffer(input, getactivebuffer()); if (iscomplete(getactivebuffer()) === true) $input.trigger("complete"); $input.click(); } function mask(el) { $el = $(el); if ($el.is(":input")) { //store tests & original buffer in the input element - used to get the unmasked value $el.data('_inputmask', { 'masksets': masksets, 'activemasksetindex': activemasksetindex, 'opts': opts, 'isrtl': false }); //show tooltip if (opts.showtooltip) { $el.prop("title", getactivemaskset()["mask"]); } //correct greedy setting if needed getactivemaskset()['greedy'] = getactivemaskset()['greedy'] ? getactivemaskset()['greedy'] : getactivemaskset()['repeat'] == 0; //handle maxlength attribute if ($el.attr("maxlength") != null) //only when the attribute is set { var maxlength = $el.prop('maxlength'); if (maxlength > -1) { //handle *-repeat $.each(masksets, function (ndx, ms) { if (typeof (ms) == "object") { if (ms["repeat"] == "*") { ms["repeat"] = maxlength; } } }); } if (getmasklength() >= maxlength && maxlength > -1) { //ff sets no defined max length to -1 if (maxlength < getactivebuffertemplate().length) getactivebuffertemplate().length = maxlength; if (getactivemaskset()['greedy'] == false) { getactivemaskset()['repeat'] = math.round(maxlength / getactivebuffertemplate().length); } $el.prop('maxlength', getmasklength() * 2); } } patchvalueproperty(el); if (opts.numericinput) opts.isnumeric = opts.numericinput; if (el.dir == "rtl" || (opts.numericinput && opts.rightalignnumerics) || (opts.isnumeric && opts.rightalignnumerics)) $el.css("text-align", "right"); if (el.dir == "rtl" || opts.numericinput) { el.dir = "ltr"; $el.removeattr("dir"); var inputdata = $el.data('_inputmask'); inputdata['isrtl'] = true; $el.data('_inputmask', inputdata); isrtl = true; } //unbind all events - to make sure that no other mask will interfere when re-masking $el.unbind(".inputmask"); $el.removeclass('focus.inputmask'); //bind events $el.closest('form').bind("submit", function () { //trigger change on submit if any if (valueonfocus != getactivebuffer().join('')) { $el.change(); } }).bind('reset', function () { settimeout(function () { $el.trigger("setvalue"); }, 0); }); $el.bind("mouseenter.inputmask", function () { var $input = $(this), input = this; if (!$input.hasclass('focus.inputmask') && opts.showmaskonhover) { if (input._valueget() != getactivebuffer().join('')) { writebuffer(input, getactivebuffer()); } } }).bind("blur.inputmask", function () { var $input = $(this), input = this, nptvalue = input._valueget(), buffer = getactivebuffer(); $input.removeclass('focus.inputmask'); if (valueonfocus != getactivebuffer().join('')) { $input.change(); } if (opts.clearmaskonlostfocus && nptvalue != '') { if (nptvalue == getactivebuffertemplate().join('')) input._valueset(''); else { //clearout optional tail of the mask clearoptionaltail(input); } } if (iscomplete(buffer) === false) { $input.trigger("incomplete"); if (opts.clearincomplete) { $.each(masksets, function (ndx, ms) { if (typeof (ms) == "object") { ms["buffer"] = ms["_buffer"].slice(); ms["lastvalidposition"] = -1; } }); activemasksetindex = 0; if (opts.clearmaskonlostfocus) input._valueset(''); else { buffer = getactivebuffertemplate().slice(); writebuffer(input, buffer); } } } }).bind("focus.inputmask", function () { var $input = $(this), input = this, nptvalue = input._valueget(); if (opts.showmaskonfocus && !$input.hasclass('focus.inputmask') && (!opts.showmaskonhover || (opts.showmaskonhover && nptvalue == ''))) { if (input._valueget() != getactivebuffer().join('')) { writebuffer(input, getactivebuffer(), seeknext(getactivemaskset()["lastvalidposition"])); } } $input.addclass('focus.inputmask'); valueonfocus = getactivebuffer().join(''); }).bind("mouseleave.inputmask", function () { var $input = $(this), input = this; if (opts.clearmaskonlostfocus) { if (!$input.hasclass('focus.inputmask') && input._valueget() != $input.attr("placeholder")) { if (input._valueget() == getactivebuffertemplate().join('') || input._valueget() == '') input._valueset(''); else { //clearout optional tail of the mask clearoptionaltail(input); } } } }).bind("click.inputmask", function () { var input = this; settimeout(function () { var selectedcaret = caret(input), buffer = getactivebuffer(); if (selectedcaret.begin == selectedcaret.end) { var clickposition = isrtl ? translateposition(selectedcaret.begin) : selectedcaret.begin, lvp = getactivemaskset()["lastvalidposition"], lastposition; if (opts.isnumeric) { lastposition = opts.skipradixdance === false && opts.radixpoint != "" && $.inarray(opts.radixpoint, buffer) != -1 ? (opts.numericinput ? seeknext($.inarray(opts.radixpoint, buffer)) : $.inarray(opts.radixpoint, buffer)) : seeknext(lvp); } else { lastposition = seeknext(lvp); } if (clickposition < lastposition) { if (ismask(clickposition)) caret(input, clickposition); else caret(input, seeknext(clickposition)); } else caret(input, lastposition); } }, 0); }).bind('dblclick.inputmask', function () { var input = this; settimeout(function () { caret(input, 0, seeknext(getactivemaskset()["lastvalidposition"])); }, 0); }).bind(pasteevent + ".inputmask dragdrop.inputmask drop.inputmask", function (e) { if (skipinputevent === true) { skipinputevent = false; return true; } var input = this, $input = $(input); //paste event for ie8 and lower i guess ;-) if (e.type == "propertychange" && input._valueget().length <= getmasklength()) { return true; } settimeout(function () { var pastevalue = opts.onbeforepaste != undefined ? opts.onbeforepaste.call(this, input._valueget()) : input._valueget(); checkval(input, true, false, pastevalue.split(''), true); if (iscomplete(getactivebuffer()) === true) $input.trigger("complete"); $input.click(); }, 0); }).bind('setvalue.inputmask', function () { var input = this; checkval(input, true); valueonfocus = getactivebuffer().join(''); if (input._valueget() == getactivebuffertemplate().join('')) input._valueset(''); }).bind('complete.inputmask', opts.oncomplete ).bind('incomplete.inputmask', opts.onincomplete ).bind('cleared.inputmask', opts.oncleared ).bind("keyup.inputmask", keyupevent); if (androidchrome) { $el.bind("input.inputmask", inputevent); } else { $el.bind("keydown.inputmask", keydownevent ).bind("keypress.inputmask", keypressevent); } if (msie10) $el.bind("input.inputmask", inputevent); //apply mask checkval(el, true, false); valueonfocus = getactivebuffer().join(''); // wrap document.activeelement in a try/catch block since ie9 throw "unspecified error" if document.activeelement is undefined when we are in an iframe. var activeelement; try { activeelement = document.activeelement; } catch (e) { } if (activeelement === el) { //position the caret when in focus $el.addclass('focus.inputmask'); caret(el, seeknext(getactivemaskset()["lastvalidposition"])); } else if (opts.clearmaskonlostfocus) { if (getactivebuffer().join('') == getactivebuffertemplate().join('')) { el._valueset(''); } else { clearoptionaltail(el); } } else { writebuffer(el, getactivebuffer()); } installeventruler(el); } } //action object if (actionobj != undefined) { switch (actionobj["action"]) { case "iscomplete": return iscomplete(actionobj["buffer"]); case "unmaskedvalue": isrtl = actionobj["$input"].data('_inputmask')['isrtl']; return unmaskedvalue(actionobj["$input"], actionobj["skipdatepickercheck"]); case "mask": mask(actionobj["el"]); break; case "format": $el = $({}); $el.data('_inputmask', { 'masksets': masksets, 'activemasksetindex': activemasksetindex, 'opts': opts, 'isrtl': opts.numericinput }); if (opts.numericinput) { opts.isnumeric = opts.numericinput; isrtl = true; } checkval($el, false, false, actionobj["value"].split(''), true); return getactivebuffer().join(''); } } } $.inputmask = { //options default defaults: { placeholder: "_", optionalmarker: { start: "[", end: "]" }, quantifiermarker: { start: "{", end: "}" }, groupmarker: { start: "(", end: ")" }, escapechar: "\\", mask: null, oncomplete: $.noop, //executes when the mask is complete onincomplete: $.noop, //executes when the mask is incomplete and focus is lost oncleared: $.noop, //executes when the mask is cleared repeat: 0, //repetitions of the mask: * ~ forever, otherwise specify an integer greedy: true, //true: allocated buffer for the mask and repetitions - false: allocate only if needed autounmask: false, //automatically unmask when retrieving the value with $.fn.val or value if the browser supports __lookupgetter__ or getownpropertydescriptor clearmaskonlostfocus: true, insertmode: true, //insert the input or overwrite the input clearincomplete: false, //clear the incomplete input on blur aliases: {}, //aliases definitions => see jquery.inputmask.extensions.js onkeyup: $.noop, //override to implement autocomplete on certain keys for example onkeydown: $.noop, //override to implement autocomplete on certain keys for example onbeforepaste: undefined, //executes before masking the pasted value to allow preprocessing of the pasted value. args => pastedvalue => return processedvalue onunmask: undefined, //executes after unmasking to allow postprocessing of the unmaskedvalue. args => maskedvalue, unmaskedvalue showmaskonfocus: true, //show the mask-placeholder when the input has focus showmaskonhover: true, //show the mask-placeholder when hovering the empty input onkeyvalidation: $.noop, //executes on every key-press with the result of isvalid. params: result, opts skipoptionalpartcharacter: " ", //a character which can be used to skip an optional part of a mask showtooltip: false, //show the activemask as tooltip numericinput: false, //numericinput input direction style (input shifts to the left while holding the caret position) //numeric basic properties isnumeric: false, //enable numeric features radixpoint: "", //".", // | "," skipradixdance: false, //disable radixpoint caret positioning rightalignnumerics: true, //align numerics to the right //numeric basic properties definitions: { '9': { validator: "[0-9]", cardinality: 1 }, 'a': { validator: "[a-za-z\u0410-\u044f\u0401\u0451]", cardinality: 1 }, '*': { validator: "[a-za-z\u0410-\u044f\u0401\u04510-9]", cardinality: 1 } }, keycode: { alt: 18, backspace: 8, caps_lock: 20, comma: 188, command: 91, command_left: 91, command_right: 93, control: 17, delete: 46, down: 40, end: 35, enter: 13, escape: 27, home: 36, insert: 45, left: 37, menu: 93, numpad_add: 107, numpad_decimal: 110, numpad_divide: 111, numpad_enter: 108, numpad_multiply: 106, numpad_subtract: 109, page_down: 34, page_up: 33, period: 190, right: 39, shift: 16, space: 32, tab: 9, up: 38, windows: 91 }, //specify keycodes which should not be considered in the keypress event, otherwise the preventdefault will stop their default behavior especially in ff ignorables: [8, 9, 13, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123], getmasklength: function (buffer, greedy, repeat, currentbuffer, opts) { var calculatedlength = buffer.length; if (!greedy) { if (repeat == "*") { calculatedlength = currentbuffer.length + 1; } else if (repeat > 1) { calculatedlength += (buffer.length * (repeat - 1)); } } return calculatedlength; } }, escaperegex: function (str) { var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\']; return str.replace(new regexp('(\\' + specials.join('|\\') + ')', 'gim'), '\\$1'); }, format: function (value, options) { var opts = $.extend(true, {}, $.inputmask.defaults, options); resolvealias(opts.alias, options, opts); return maskscope(generatemasksets(opts), 0, opts, { "action": "format", "value": value }); } }; $.fn.inputmask = function (fn, options) { var opts = $.extend(true, {}, $.inputmask.defaults, options), masksets, activemasksetindex = 0; if (typeof fn === "string") { switch (fn) { case "mask": //resolve possible aliases given by options resolvealias(opts.alias, options, opts); masksets = generatemasksets(opts); if (masksets.length == 0) { return this; } return this.each(function () { maskscope($.extend(true, {}, masksets), 0, opts, { "action": "mask", "el": this }); }); case "unmaskedvalue": var $input = $(this), input = this; if ($input.data('_inputmask')) { masksets = $input.data('_inputmask')['masksets']; activemasksetindex = $input.data('_inputmask')['activemasksetindex']; opts = $input.data('_inputmask')['opts']; return maskscope(masksets, activemasksetindex, opts, { "action": "unmaskedvalue", "$input": $input }); } else return $input.val(); case "remove": return this.each(function () { var $input = $(this), input = this; if ($input.data('_inputmask')) { masksets = $input.data('_inputmask')['masksets']; activemasksetindex = $input.data('_inputmask')['activemasksetindex']; opts = $input.data('_inputmask')['opts']; //writeout the unmaskedvalue input._valueset(maskscope(masksets, activemasksetindex, opts, { "action": "unmaskedvalue", "$input": $input, "skipdatepickercheck": true })); //clear data $input.removedata('_inputmask'); //unbind all events $input.unbind(".inputmask"); $input.removeclass('focus.inputmask'); //restore the value property var valueproperty; if (object.getownpropertydescriptor) valueproperty = object.getownpropertydescriptor(input, "value"); if (valueproperty && valueproperty.get) { if (input._valueget) { object.defineproperty(input, "value", { get: input._valueget, set: input._valueset }); } } else if (document.__lookupgetter__ && input.__lookupgetter__("value")) { if (input._valueget) { input.__definegetter__("value", input._valueget); input.__definesetter__("value", input._valueset); } } try { //try catch needed for ie7 as it does not supports deleting fns delete input._valueget; delete input._valueset; } catch (e) { input._valueget = undefined; input._valueset = undefined; } } }); break; case "getemptymask": //return the default (empty) mask value, usefull for setting the default value in validation if (this.data('_inputmask')) { masksets = this.data('_inputmask')['masksets']; activemasksetindex = this.data('_inputmask')['activemasksetindex']; return masksets[activemasksetindex]['_buffer'].join(''); } else return ""; case "hasmaskedvalue": //check wheter the returned value is masked or not; currently only works reliable when using jquery.val fn to retrieve the value return this.data('_inputmask') ? !this.data('_inputmask')['opts'].autounmask : false; case "iscomplete": masksets = this.data('_inputmask')['masksets']; activemasksetindex = this.data('_inputmask')['activemasksetindex']; opts = this.data('_inputmask')['opts']; return maskscope(masksets, activemasksetindex, opts, { "action": "iscomplete", "buffer": this[0]._valueget().split('') }); case "getmetadata": //return mask metadata if exists if (this.data('_inputmask')) { masksets = this.data('_inputmask')['masksets']; activemasksetindex = this.data('_inputmask')['activemasksetindex']; return masksets[activemasksetindex]['metadata']; } else return undefined; default: //check if the fn is an alias if (!resolvealias(fn, options, opts)) { //maybe fn is a mask so we try //set mask opts.mask = fn; } masksets = generatemasksets(opts); if (masksets.length == 0) { return this; } return this.each(function () { maskscope($.extend(true, {}, masksets), activemasksetindex, opts, { "action": "mask", "el": this }); }); break; } } else if (typeof fn == "object") { opts = $.extend(true, {}, $.inputmask.defaults, fn); resolvealias(opts.alias, fn, opts); //resolve aliases masksets = generatemasksets(opts); if (masksets.length == 0) { return this; } return this.each(function () { maskscope($.extend(true, {}, masksets), activemasksetindex, opts, { "action": "mask", "el": this }); }); } else if (fn == undefined) { //look for data-inputmask atribute - the attribute should only contain optipns return this.each(function () { var attroptions = $(this).attr("data-inputmask"); if (attroptions && attroptions != "") { try { attroptions = attroptions.replace(new regexp("'", "g"), '"'); var dataoptions = $.parsejson("{" + attroptions + "}"); $.extend(true, dataoptions, options); opts = $.extend(true, {}, $.inputmask.defaults, dataoptions); resolvealias(opts.alias, dataoptions, opts); opts.alias = undefined; $(this).inputmask(opts); } catch (ex) { } //need a more relax parsejson } }); } }; } })(jquery);