123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- /*
- Masked Input plugin for jQuery
- Copyright (c) 2007-2013 Josh Bush (digitalbush.com)
- Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
- Version: 1.3.1
- */
- (function($) {
- function getPasteEvent() {
- var el = document.createElement('input'),
- name = 'onpaste';
- el.setAttribute(name, '');
- return (typeof el[name] === 'function')?'paste':'input';
- }
- var pasteEventName = getPasteEvent() + ".mask",
- ua = navigator.userAgent,
- iPhone = /iphone/i.test(ua),
- android=/android/i.test(ua),
- caretTimeoutId;
- $.mask = {
- //Predefined character definitions
- definitions: {
- '9': "[0-9]",
- 'a': "[A-Za-z]",
- '*': "[A-Za-z0-9]"
- },
- dataName: "rawMaskFn",
- placeholder: '_',
- };
- $.fn.extend({
- //Helper Function for Caret positioning
- caret: function(begin, end) {
- var range;
- if (this.length === 0 || this.is(":hidden")) {
- 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,
- len;
- if (!mask && this.length > 0) {
- input = $(this[0]);
- return input.data($.mask.dataName)();
- }
- settings = $.extend({
- placeholder: $.mask.placeholder, // Load default placeholder
- completed: null
- }, settings);
- defs = $.mask.definitions;
- tests = [];
- partialPosition = len = mask.length;
- firstNonMaskPos = null;
- $.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;
- }
- } 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] ? settings.placeholder : c;
- }
- }),
- focusText = input.val();
- 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] = settings.placeholder;
- } else {
- break;
- }
- j = seekNext(j);
- }
- }
- writeBuffer();
- input.caret(Math.max(firstNonMaskPos, begin));
- }
- function shiftR(pos) {
- var i,
- c,
- j,
- t;
- for (i = pos, c = settings.placeholder; 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 keydownEvent(e) {
- var k = e.which,
- pos,
- begin,
- end;
- //backspace, delete, and escape get special treatment
- 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 == 27) {//escape
- input.val(focusText);
- input.caret(0, checkVal());
- e.preventDefault();
- }
- }
- function keypressEvent(e) {
- var k = e.which,
- pos = input.caret(),
- p,
- c,
- next;
- if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
- return;
- } else if (k) {
- 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){
- setTimeout($.proxy($.fn.caret,input,next),0);
- }else{
- input.caret(next);
- }
- if (settings.completed && next >= len) {
- settings.completed.call(input);
- }
- }
- }
- e.preventDefault();
- }
- }
- function clearBuffer(start, end) {
- var i;
- for (i = start; i < end && i < len; i++) {
- if (tests[i]) {
- buffer[i] = settings.placeholder;
- }
- }
- }
- function writeBuffer() { input.val(buffer.join('')); }
- function checkVal(allow) {
- //try to place characters where they belong
- var test = input.val(),
- lastMatch = -1,
- i,
- c;
- for (i = 0, pos = 0; i < len; i++) {
- if (tests[i]) {
- buffer[i] = settings.placeholder;
- while (pos++ < test.length) {
- c = test.charAt(pos - 1);
- if (tests[i].test(c)) {
- buffer[i] = c;
- lastMatch = i;
- break;
- }
- }
- if (pos > test.length) {
- break;
- }
- } else if (buffer[i] === test.charAt(pos) && i !== partialPosition) {
- pos++;
- lastMatch = i;
- }
- }
- if (allow) {
- writeBuffer();
- } else if (lastMatch + 1 < partialPosition) {
- input.val("");
- clearBuffer(0, len);
- } 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!=settings.placeholder ? c : null;
- }).join('');
- });
- if (!input.attr("readonly"))
- input
- .one("unmask", function() {
- input
- .unbind(".mask")
- .removeData($.mask.dataName);
- })
- .bind("focus.mask", function() {
- clearTimeout(caretTimeoutId);
- var pos,
- moveCaret;
- focusText = input.val();
- pos = checkVal();
-
- caretTimeoutId = setTimeout(function(){
- writeBuffer();
- if (pos == mask.length) {
- input.caret(0, pos);
- } else {
- input.caret(pos);
- }
- }, 10);
- })
- .bind("blur.mask", function() {
- checkVal();
- if (input.val() != focusText)
- input.change();
- })
- .bind("keydown.mask", keydownEvent)
- .bind("keypress.mask", keypressEvent)
- .bind(pasteEventName, function() {
- setTimeout(function() {
- var pos=checkVal(true);
- input.caret(pos);
- if (settings.completed && pos == input.val().length)
- settings.completed.call(input);
- }, 0);
- });
- checkVal(); //Perform initial check for existing values
- });
- }
- });
- })(jQuery);
|