From 963662ddd182a7a796cbd9bef6e2ff2a27d69d6d Mon Sep 17 00:00:00 2001 From: Page Brooks Date: Tue, 29 Jan 2013 13:41:14 -0800 Subject: [PATCH] Add jQuery Masked Input 1.3.1 compatibility --- lib/maskedinput/jquery.maskedinput.js | 352 +++++++++++++++----------- 1 file changed, 205 insertions(+), 147 deletions(-) diff --git a/lib/maskedinput/jquery.maskedinput.js b/lib/maskedinput/jquery.maskedinput.js index 1c207bc..192b35d 100644 --- a/lib/maskedinput/jquery.maskedinput.js +++ b/lib/maskedinput/jquery.maskedinput.js @@ -1,34 +1,50 @@ -/* +/* Masked Input plugin for jQuery - Copyright (c) 2007-2011 Josh Bush (digitalbush.com) - Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) - Version: 1.3 + 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($) { - var pasteEventName = ($.browser.msie ? 'paste' : 'input') + ".mask"; - var iPhone = (window.orientation != undefined); + 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: { + definitions: { '9': "[0-9]", 'a': "[A-Za-z]", '*': "[A-Za-z0-9]" }, - dataName:"rawMaskFn" + dataName: "rawMaskFn", + placeholder: '_', }; $.fn.extend({ //Helper Function for Caret positioning caret: function(begin, end) { - if (this.length == 0) return; - if (typeof begin == 'number') { - end = (typeof end == 'number') ? end : begin; + 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) { + if(this.setSelectionRange) { this.setSelectionRange(begin, end); - } else if (this.createTextRange) { - var range = this.createTextRange(); + } else if(this.createTextRange) { + range = this.createTextRange(); range.collapse(true); range.moveEnd('character', end); range.moveStart('character', begin); @@ -36,255 +52,297 @@ } }); } else { - if (this[0].setSelectionRange) { + if(this[0].setSelectionRange) { begin = this[0].selectionStart; end = this[0].selectionEnd; - } else if (document.selection && document.selection.createRange) { - var range = document.selection.createRange(); + } 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 }; + return { + begin: begin, + end: end + }; } }, - unmask: function() { return this.trigger("unmask"); }, - isMaskValid: function(){ + unmask: function() { + return this.trigger("unmask"); + }, + isMaskValid: function() { return $(this).data('mask-isvalid'); }, mask: function(mask, settings) { - if (!mask && this.length > 0) { - var input = $(this[0]); + var input, defs, tests, partialPosition, firstNonMaskPos, len; + + if(!mask && this.length > 0) { + input = $(this[0]); return input.data($.mask.dataName)(); } settings = $.extend({ - placeholder: "_", + placeholder: $.mask.placeholder, + // Load default placeholder completed: null }, settings); - var defs = $.mask.definitions; - var tests = []; - var partialPosition = mask.length; - var firstNonMaskPos = null; - var len = mask.length; + + defs = $.mask.definitions; + tests = []; + partialPosition = len = mask.length; + firstNonMaskPos = null; $.each(mask.split(""), function(i, c) { - if (c == '?') { + if(c == '?') { len--; partialPosition = i; - } else if (defs[c]) { + } else if(defs[c]) { tests.push(new RegExp(defs[c])); - if(firstNonMaskPos==null) - firstNonMaskPos = tests.length - 1; + if(firstNonMaskPos === null) { + firstNonMaskPos = tests.length - 1; + } } else { tests.push(null); } }); return this.trigger("unmask").each(function() { - var input = $(this); - var buffer = $.map(mask.split(""), function(c, i) { if (c != '?') return defs[c] ? settings.placeholder : c }); - var focusText = input.val(); + 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]); + while(++pos < len && !tests[pos]); return pos; - }; + } + function seekPrev(pos) { - while (--pos >= 0 && !tests[pos]); + while(--pos >= 0 && !tests[pos]); return pos; - }; + } + + function shiftL(begin, end) { + var i, j; - function shiftL(begin,end) { - if(begin<0) - return; - for (var i = begin,j = seekNext(end); i < len; i++) { - if (tests[i]) { - if (j < len && tests[i].test(buffer[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 + } else { break; + } + j = seekNext(j); } } writeBuffer(); input.caret(Math.max(firstNonMaskPos, begin)); - }; + } function shiftR(pos) { - for (var i = pos, c = settings.placeholder; i < len; i++) { - if (tests[i]) { - var j = seekNext(i); - var t = buffer[i]; + 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)) + if(j < len && tests[j].test(t)) { c = t; - else + } else { break; + } } } - }; + } function keydownEvent(e) { - var k=e.which; + var k = e.which, + pos, begin, end; //backspace, delete, and escape get special treatment - if(k == 8 || k == 46 || (iPhone && k == 127)){ - var 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; + 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); - isValid(); //twarogowski + shiftL(begin, end - 1); + isValid(); - return false; - } else if (k == 27) {//escape + e.preventDefault(); + } else if(k == 27) { //escape input.val(focusText); input.caret(0, checkVal()); - return false; + e.preventDefault(); } - }; + } function keypressEvent(e) { var k = e.which, - pos = input.caret(); - if (e.ctrlKey || e.altKey || e.metaKey || k<32) {//Ignore - return true; - } else if (k) { - if(pos.end-pos.begin!=0){ + 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); - isValid(); //twarogowski + shiftL(pos.begin, pos.end - 1); + isValid(); } - var p = seekNext(pos.begin - 1); - if (p < len) { - var c = String.fromCharCode(k); - if (tests[p].test(c)) { + p = seekNext(pos.begin - 1); + if(p < len) { + c = String.fromCharCode(k); + if(tests[p].test(c)) { shiftR(p); + buffer[p] = c; writeBuffer(); - var next = seekNext(p); - input.caret(next); - isValid(); //twarogowski - if (settings.completed && next >= len) + next = seekNext(p); + + if(android) { + setTimeout($.proxy($.fn.caret, input, next), 0); + } else { + input.caret(next); + } + + isValid(); + if(settings.completed && next >= len) { settings.completed.call(input); + } } } - return false; + e.preventDefault(); } - }; + } function clearBuffer(start, end) { - for (var i = start; i < end && i < len; i++) { - if (tests[i]) + var i; + for(i = start; i < end && i < len; i++) { + if(tests[i]) { buffer[i] = settings.placeholder; + } } - }; + } - function writeBuffer() { return input.val(buffer.join('')).val(); }; + function writeBuffer() { + input.val(buffer.join('')); + } - function isValid(){ + function isValid() { var test = input.val(); var lastMatch = -1; - for (var i = 0, pos = 0; i < len; i++) { - if (tests[i]) { + for(var i = 0, pos = 0; i < len; i++) { + if(tests[i]) { buffer[i] = settings.placeholder; - while (pos++ < test.length) { + while(pos++ < test.length) { var c = test.charAt(pos - 1); - if (tests[i].test(c)) { + 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) { + if(pos > test.length) break; + } else if(buffer[i] == test.charAt(pos) && i != partialPosition) { pos++; lastMatch = i; } } var valid = (lastMatch + 1 >= partialPosition); - input.data('mask-isvalid',valid); + input.data('mask-isvalid', valid); return valid; } function checkVal(allow) { //try to place characters where they belong - var test = input.val(); - var lastMatch = -1; - for (var i = 0, pos = 0; i < len; i++) { - if (tests[i]) { + 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) { - var c = test.charAt(pos - 1); - if (tests[i].test(c)) { + while(pos++ < test.length) { + c = test.charAt(pos - 1); + if(tests[i].test(c)) { buffer[i] = c; lastMatch = i; break; } } - if (pos > test.length) + if(pos > test.length) { break; - } else if (buffer[i] == test.charAt(pos) && i!=partialPosition) { + } + } else if(buffer[i] === test.charAt(pos) && i !== partialPosition) { pos++; lastMatch = i; } } - if (!allow && lastMatch + 1 < partialPosition) { + if(allow) { + writeBuffer(); + } else if(lastMatch + 1 < partialPosition) { input.val(""); clearBuffer(0, len); - } else if (allow || lastMatch + 1 >= partialPosition) { + } else { writeBuffer(); - if (!allow) input.val(input.val().substring(0, lastMatch + 1)); + input.val(input.val().substring(0, lastMatch + 1)); } - return (partialPosition ? i : firstNonMaskPos); - }; + return(partialPosition ? i : firstNonMaskPos); + } - input.data($.mask.dataName,function(){ + input.data($.mask.dataName, function() { return $.map(buffer, function(c, i) { - return tests[i]&&c!=settings.placeholder ? c : null; + 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() { - focusText = input.val(); - var pos = checkVal(); - writeBuffer(); - var moveCaret=function(){ - if (pos == mask.length) - input.caret(0, pos); - else - input.caret(pos); - }; - ($.browser.msie ? moveCaret:function(){setTimeout(moveCaret,0)})(); - }) - .bind("blur.mask", function() { - checkVal(); - if (input.val() != focusText) - input.change(); - }) - .bind("keydown.mask", keydownEvent) - .bind("keypress.mask", keypressEvent) - .bind(pasteEventName, function() { - setTimeout(function() { input.caret(checkVal(true)); }, 0); - }); + }); + 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); + + +})(jQuery); \ No newline at end of file