From 86435ffed97ea2e060f0fc8b4ae4a886a7b20ebe Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Oct 2013 00:10:59 -0400 Subject: [PATCH 1/9] adds node_modules/ to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index bfa0621..3175dd7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .idea/* + +node_modules/ From b3ce183ff41825c358b46dbe6e9fc7840bf4ef6e Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Oct 2013 01:04:25 -0400 Subject: [PATCH 2/9] changes to gruntjs powered build The existing SpecRunner.html is still in /spec, I didn't see the need to change it, so it will still load the specs correctly. It will need to be updated whenever a new spec file is added, but I don't think this is too much work. The grunt build will automatically pick up new spec files and executes via the command line. Also, this will enable integration via Travis-CI so in the future we can have PRs automatically tested before we accept them. --- Jakefile | 31 --------------------------- README.md | 12 +++++++++++ gruntfile.js | 27 +++++++++++++++++++++++ package.json | 12 +++++++++++ spec/lib/setup.js | 14 ++++++++++++ src/jquery.maskedinput.js | 17 +++++++++++---- templates/jquery.maskedinput.template | 9 -------- 7 files changed, 78 insertions(+), 44 deletions(-) delete mode 100644 Jakefile create mode 100644 gruntfile.js create mode 100644 package.json create mode 100644 spec/lib/setup.js delete mode 100644 templates/jquery.maskedinput.template diff --git a/Jakefile b/Jakefile deleted file mode 100644 index 5001cb7..0000000 --- a/Jakefile +++ /dev/null @@ -1,31 +0,0 @@ -var Handlebars=require("handlebars"), - fs = require("fs"), - path = require ("path"), - UglifyJS = require("uglify-js"), - distPath='dist/'; - -Handlebars.registerHelper('include', function(context) { - return fs.readFileSync(context,'utf8'); -}); - -function keepComment(node,comment){ - return comment.type === "comment2"; -} - -task('clean',function(){ - fs.rmdir(distPath) -}); - -task('default',['clean'], function (params) { - fs.mkdir(distPath,0755); - - var options = JSON.parse(fs.readFileSync('plugin.json','utf8')) - options.Year=new Date().getFullYear() - - var template = Handlebars.compile(fs.readFileSync('templates/jquery.maskedinput.template','utf8')); - var debugFile = path.join(distPath,'jquery.maskedinput.js'); - fs.writeFileSync(debugFile,template(options)); - - compressed = UglifyJS.minify(debugFile,{output:{comments:keepComment}}); - fs.writeFileSync(path.join(distPath,'jquery.maskedinput.min.js'), compressed.code); -}); \ No newline at end of file diff --git a/README.md b/README.md index ef6f39b..bcc7370 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,15 @@ If your requirements aren't met by the predefined placeholders, you can always a By design, this plugin will reject input which doesn't complete the mask. You can bypass this by using a '?' character at the position where you would like to consider input optional. For example, a mask of "(999) 999-9999? x99999" would require only the first 10 digits of a phone number with extension being optional. +Setting up your Developer Environment +------------------------------------- +jQuery Masked Input uses [NodeJS](http://www.nodejs.org) and [GruntJS](http://www.gruntjs.com) as it's developer platform and build automation tool. + +To get your environment setup correctly, you'll need nodejs version 0.8.25 or greater installed. + +Once node is installed on your system all that you need to do is install the developer dependencies and run the grunt build: + + $ npm install + $ grunt + +All of the tests for jQuery Masked Input are run using the [jasmine](http://pivotal.github.io/jasmine/) test runner. diff --git a/gruntfile.js b/gruntfile.js new file mode 100644 index 0000000..27bd038 --- /dev/null +++ b/gruntfile.js @@ -0,0 +1,27 @@ + +"use strict"; + +module.exports = function( grunt ) { + grunt.initConfig({ + jasmine: { + full: { + src: "src/**/*.js", + options: { + specs: "spec/*Spec.js", + vendor: [ + "spec/lib/matchers.js", + "spec/lib/jasmine-species/jasmine-grammar.js", + "spec/lib/setup.js", + "lib/jquery-1.9.0.min.js", + "spec/lib/jquery.keymasher.js" + ] + } + } + } + }); + + grunt.loadNpmTasks("grunt-contrib-jasmine"); + + grunt.registerTask('test', ['jasmine']); + grunt.registerTask('default', ['test']); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..bd9e406 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "jquery.maskedinput", + "version": "1.3.0", + "author": "Josh Bush", + "description": "jQuery Masked Input Plugin", + + "devDependencies": { + "grunt": "0.4.x", + "grunt-contrib-jasmine": "0.5.x", + "grunt-contrib-watch": "0.5.x" + } +} diff --git a/spec/lib/setup.js b/spec/lib/setup.js new file mode 100644 index 0000000..9539215 --- /dev/null +++ b/spec/lib/setup.js @@ -0,0 +1,14 @@ +function importGrammar(g){ + for (var prop in g) { + if (g.hasOwnProperty(prop)) + window[prop] = g[prop]; + + } +} + +importGrammar(jasmine.grammar.FeatureStory); +importGrammar(jasmine.grammar.GWT); + +var input; +beforeEach(function(){ input = $("").appendTo("body").focus(); }); +afterEach(function(){ input.remove();}); diff --git a/src/jquery.maskedinput.js b/src/jquery.maskedinput.js index 9c0d392..ef7fba8 100644 --- a/src/jquery.maskedinput.js +++ b/src/jquery.maskedinput.js @@ -1,8 +1,16 @@ +/* + Masked Input plugin for jQuery + Copyright (c) 2007-{{Year}} Josh Bush (digitalbush.com) + Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) + Version: {{version}} +*/ +(function($) { + function getPasteEvent() { var el = document.createElement('input'), name = 'onpaste'; el.setAttribute(name, ''); - return (typeof el[name] === 'function')?'paste':'input'; + return (typeof el[name] === 'function')?'paste':'input'; } var pasteEventName = getPasteEvent() + ".mask", @@ -314,7 +322,7 @@ $.fn.extend({ focusText = input.val(); pos = checkVal(); - + caretTimeoutId = setTimeout(function(){ writeBuffer(); if (pos == mask.length) { @@ -332,9 +340,9 @@ $.fn.extend({ .bind("keydown.mask", keydownEvent) .bind("keypress.mask", keypressEvent) .bind(pasteEventName, function() { - setTimeout(function() { + setTimeout(function() { var pos=checkVal(true); - input.caret(pos); + input.caret(pos); if (settings.completed && pos == input.val().length) settings.completed.call(input); }, 0); @@ -346,3 +354,4 @@ $.fn.extend({ }); } }); +})(jQuery); diff --git a/templates/jquery.maskedinput.template b/templates/jquery.maskedinput.template deleted file mode 100644 index 18f6d17..0000000 --- a/templates/jquery.maskedinput.template +++ /dev/null @@ -1,9 +0,0 @@ -/* - Masked Input plugin for jQuery - Copyright (c) 2007-{{Year}} Josh Bush (digitalbush.com) - Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) - Version: {{version}} -*/ -(function($) { - {{{include "src/jquery.maskedinput.js"}}} -})(jQuery); \ No newline at end of file From 02ad44c2bf0d9a5638b7a876f88323123312d116 Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Oct 2013 21:21:05 -0400 Subject: [PATCH 3/9] removes interpolation keys from banner comment --- src/jquery.maskedinput.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jquery.maskedinput.js b/src/jquery.maskedinput.js index ef7fba8..5a1fc52 100644 --- a/src/jquery.maskedinput.js +++ b/src/jquery.maskedinput.js @@ -1,8 +1,8 @@ /* Masked Input plugin for jQuery - Copyright (c) 2007-{{Year}} Josh Bush (digitalbush.com) + Copyright (c) 2007-2013 Josh Bush (digitalbush.com) Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) - Version: {{version}} + Version: 1.3 */ (function($) { From b28407984d76edfd9197b4d800baae7643f90eca Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Oct 2013 21:55:59 -0400 Subject: [PATCH 4/9] banner comments are generated using data from package.json when we merge #105 we should change the to load component.json instead --- dist/jquery.maskedinput.js | 466 +++++++++------------------------ dist/jquery.maskedinput.min.js | 10 +- gruntfile.js | 28 +- package.json | 5 +- src/jquery.maskedinput.js | 6 - 5 files changed, 165 insertions(+), 350 deletions(-) diff --git a/dist/jquery.maskedinput.js b/dist/jquery.maskedinput.js index 89ce020..f5a5e29 100644 --- a/dist/jquery.maskedinput.js +++ b/dist/jquery.maskedinput.js @@ -1,338 +1,132 @@ /* - 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 + jQuery Masked Input Plugin + Copyright (c) 2007 - 2013 Josh Bush (digitalbush.com) + Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) + Version: 1.3.0 */ -(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); +!function(a) { + function b() { + var a = document.createElement("input"), b = "onpaste"; + return a.setAttribute(b, ""), "function" == typeof a[b] ? "paste" : "input"; + } + var c, d = b() + ".mask", e = navigator.userAgent, f = /iphone/i.test(e), g = /chrome/i.test(e), h = /android/i.test(e); + a.mask = { + definitions: { + "9": "[0-9]", + a: "[A-Za-z]", + "*": "[A-Za-z0-9]" + }, + dataName: "rawMaskFn", + placeholder: "_" + }, a.fn.extend({ + caret: function(a, b) { + var c; + if (0 !== this.length && !this.is(":hidden")) return "number" == typeof a ? (b = "number" == typeof b ? b : a, + this.each(function() { + this.setSelectionRange ? this.setSelectionRange(a, b) : this.createTextRange && (c = this.createTextRange(), + c.collapse(!0), c.moveEnd("character", b), c.moveStart("character", a), c.select()); + })) : (this[0].setSelectionRange ? (a = this[0].selectionStart, b = this[0].selectionEnd) : document.selection && document.selection.createRange && (c = document.selection.createRange(), + a = 0 - c.duplicate().moveStart("character", -1e5), b = a + c.text.length), { + begin: a, + end: b + }); + }, + unmask: function() { + return this.trigger("unmask"); + }, + mask: function(b, e) { + var i, j, k, l, m, n; + return !b && this.length > 0 ? (i = a(this[0]), i.data(a.mask.dataName)()) : (e = a.extend({ + placeholder: a.mask.placeholder, + completed: null + }, e), j = a.mask.definitions, k = [], l = n = b.length, m = null, a.each(b.split(""), function(a, b) { + "?" == b ? (n--, l = a) : j[b] ? (k.push(new RegExp(j[b])), null === m && (m = k.length - 1)) : k.push(null); + }), this.trigger("unmask").each(function() { + function i(a) { + for (;++a < n && !k[a]; ) ; + return a; + } + function o(a) { + for (;--a >= 0 && !k[a]; ) ; + return a; + } + function p(a, b) { + var c, d; + if (!(0 > a)) { + for (c = a, d = i(b); n > c; c++) if (k[c]) { + if (!(n > d && k[c].test(x[d]))) break; + x[c] = x[d], x[d] = e.placeholder, d = i(d); + } + u(), w.caret(Math.max(m, a)); + } + } + function q(a) { + var b, c, d, f; + for (b = a, c = e.placeholder; n > b; b++) if (k[b]) { + if (d = i(b), f = x[b], x[b] = c, !(n > d && k[d].test(f))) break; + c = f; + } + } + function r(a) { + var b, c, d, e = a.which; + 8 === e || 46 === e || f && 127 === e ? (b = w.caret(), c = b.begin, d = b.end, + 0 === d - c && (c = 46 !== e ? o(c) : d = i(c - 1), d = 46 === e ? i(d) : d), t(c, d), + p(c, d - 1), a.preventDefault()) : 27 == e && (w.val(y), w.caret(0, v()), a.preventDefault()); + } + function s(b) { + var c, d, f, g = b.which, j = w.caret(); + if (0 == g) { + if (j.begin >= n) return w.val(w.val().substr(0, n)), b.preventDefault(), !1; + j.begin == j.end && (g = w.val().charCodeAt(j.begin - 1), j.begin--, j.end--); + } + b.ctrlKey || b.altKey || b.metaKey || 32 > g || g && (0 !== j.end - j.begin && (t(j.begin, j.end), + p(j.begin, j.end - 1)), c = i(j.begin - 1), n > c && (d = String.fromCharCode(g), + k[c].test(d) && (q(c), x[c] = d, u(), f = i(c), h ? setTimeout(a.proxy(a.fn.caret, w, f), 0) : w.caret(f), + e.completed && f >= n && e.completed.call(w))), b.preventDefault()); + } + function t(a, b) { + var c; + for (c = a; b > c && n > c; c++) k[c] && (x[c] = e.placeholder); + } + function u() { + w.val(x.join("")); + } + function v(a) { + var b, c, d, f = w.val(), g = -1; + for (b = 0, d = 0; n > b; b++) if (k[b]) { + for (x[b] = e.placeholder; d++ < f.length; ) if (c = f.charAt(d - 1), k[b].test(c)) { + x[b] = c, g = b; + break; + } + if (d > f.length) break; + } else x[b] === f.charAt(d) && b !== l && (d++, g = b); + return a ? u() : l > g + 1 ? (w.val(""), t(0, n)) : (u(), w.val(w.val().substring(0, g + 1))), + l ? b : m; + } + var w = a(this), x = a.map(b.split(""), function(a) { + return "?" != a ? j[a] ? e.placeholder : a : void 0; + }), y = w.val(); + w.data(a.mask.dataName, function() { + return a.map(x, function(a, b) { + return k[b] && a != e.placeholder ? a : null; + }).join(""); + }), w.attr("readonly") || w.one("unmask", function() { + w.unbind(".mask").removeData(a.mask.dataName); + }).bind("focus.mask", function() { + clearTimeout(c); + var a; + y = w.val(), a = v(), c = setTimeout(function() { + u(), a == b.length ? w.caret(0, a) : w.caret(a); + }, 10); + }).bind("blur.mask", function() { + v(), w.val() != y && w.change(); + }).bind("keydown.mask", r).bind("keypress.mask", s).bind(d, function() { + setTimeout(function() { + var a = v(!0); + w.caret(a), e.completed && a == w.val().length && e.completed.call(w); + }, 0); + }), g && h && w.bind("keyup.mask", s), v(); + })); + } + }); +}(jQuery); \ No newline at end of file diff --git a/dist/jquery.maskedinput.min.js b/dist/jquery.maskedinput.min.js index 0d9ce6e..45baf54 100644 --- a/dist/jquery.maskedinput.min.js +++ b/dist/jquery.maskedinput.min.js @@ -1,7 +1,7 @@ /* - 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 + jQuery Masked Input Plugin + Copyright (c) 2007 - 2013 Josh Bush (digitalbush.com) + Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) + Version: 1.3.0 */ -(function(e){function t(){var e=document.createElement("input"),t="onpaste";return e.setAttribute(t,""),"function"==typeof e[t]?"paste":"input"}var n,a=t()+".mask",r=navigator.userAgent,i=/iphone/i.test(r),o=/android/i.test(r);e.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},dataName:"rawMaskFn",placeholder:"_"},e.fn.extend({caret:function(e,t){var n;if(0!==this.length&&!this.is(":hidden"))return"number"==typeof e?(t="number"==typeof t?t:e,this.each(function(){this.setSelectionRange?this.setSelectionRange(e,t):this.createTextRange&&(n=this.createTextRange(),n.collapse(!0),n.moveEnd("character",t),n.moveStart("character",e),n.select())})):(this[0].setSelectionRange?(e=this[0].selectionStart,t=this[0].selectionEnd):document.selection&&document.selection.createRange&&(n=document.selection.createRange(),e=0-n.duplicate().moveStart("character",-1e5),t=e+n.text.length),{begin:e,end:t})},unmask:function(){return this.trigger("unmask")},mask:function(t,r){var c,l,s,u,f,h;return!t&&this.length>0?(c=e(this[0]),c.data(e.mask.dataName)()):(r=e.extend({placeholder:e.mask.placeholder,completed:null},r),l=e.mask.definitions,s=[],u=h=t.length,f=null,e.each(t.split(""),function(e,t){"?"==t?(h--,u=e):l[t]?(s.push(RegExp(l[t])),null===f&&(f=s.length-1)):s.push(null)}),this.trigger("unmask").each(function(){function c(e){for(;h>++e&&!s[e];);return e}function d(e){for(;--e>=0&&!s[e];);return e}function m(e,t){var n,a;if(!(0>e)){for(n=e,a=c(t);h>n;n++)if(s[n]){if(!(h>a&&s[n].test(R[a])))break;R[n]=R[a],R[a]=r.placeholder,a=c(a)}b(),x.caret(Math.max(f,e))}}function p(e){var t,n,a,i;for(t=e,n=r.placeholder;h>t;t++)if(s[t]){if(a=c(t),i=R[t],R[t]=n,!(h>a&&s[a].test(i)))break;n=i}}function g(e){var t,n,a,r=e.which;8===r||46===r||i&&127===r?(t=x.caret(),n=t.begin,a=t.end,0===a-n&&(n=46!==r?d(n):a=c(n-1),a=46===r?c(a):a),k(n,a),m(n,a-1),e.preventDefault()):27==r&&(x.val(S),x.caret(0,y()),e.preventDefault())}function v(t){var n,a,i,l=t.which,u=x.caret();t.ctrlKey||t.altKey||t.metaKey||32>l||l&&(0!==u.end-u.begin&&(k(u.begin,u.end),m(u.begin,u.end-1)),n=c(u.begin-1),h>n&&(a=String.fromCharCode(l),s[n].test(a)&&(p(n),R[n]=a,b(),i=c(n),o?setTimeout(e.proxy(e.fn.caret,x,i),0):x.caret(i),r.completed&&i>=h&&r.completed.call(x))),t.preventDefault())}function k(e,t){var n;for(n=e;t>n&&h>n;n++)s[n]&&(R[n]=r.placeholder)}function b(){x.val(R.join(""))}function y(e){var t,n,a=x.val(),i=-1;for(t=0,pos=0;h>t;t++)if(s[t]){for(R[t]=r.placeholder;pos++a.length)break}else R[t]===a.charAt(pos)&&t!==u&&(pos++,i=t);return e?b():u>i+1?(x.val(""),k(0,h)):(b(),x.val(x.val().substring(0,i+1))),u?t:f}var x=e(this),R=e.map(t.split(""),function(e){return"?"!=e?l[e]?r.placeholder:e:void 0}),S=x.val();x.data(e.mask.dataName,function(){return e.map(R,function(e,t){return s[t]&&e!=r.placeholder?e:null}).join("")}),x.attr("readonly")||x.one("unmask",function(){x.unbind(".mask").removeData(e.mask.dataName)}).bind("focus.mask",function(){clearTimeout(n);var e;S=x.val(),e=y(),n=setTimeout(function(){b(),e==t.length?x.caret(0,e):x.caret(e)},10)}).bind("blur.mask",function(){y(),x.val()!=S&&x.change()}).bind("keydown.mask",g).bind("keypress.mask",v).bind(a,function(){setTimeout(function(){var e=y(!0);x.caret(e),r.completed&&e==x.val().length&&r.completed.call(x)},0)}),y()}))}})})(jQuery); \ No newline at end of file +!function(a){function b(){var a=document.createElement("input"),b="onpaste";return a.setAttribute(b,""),"function"==typeof a[b]?"paste":"input"}var c,d=b()+".mask",e=navigator.userAgent,f=/iphone/i.test(e),g=/chrome/i.test(e),h=/android/i.test(e);a.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},dataName:"rawMaskFn",placeholder:"_"},a.fn.extend({caret:function(a,b){var c;if(0!==this.length&&!this.is(":hidden"))return"number"==typeof a?(b="number"==typeof b?b:a,this.each(function(){this.setSelectionRange?this.setSelectionRange(a,b):this.createTextRange&&(c=this.createTextRange(),c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select())})):(this[0].setSelectionRange?(a=this[0].selectionStart,b=this[0].selectionEnd):document.selection&&document.selection.createRange&&(c=document.selection.createRange(),a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length),{begin:a,end:b})},unmask:function(){return this.trigger("unmask")},mask:function(b,e){var i,j,k,l,m,n;return!b&&this.length>0?(i=a(this[0]),i.data(a.mask.dataName)()):(e=a.extend({placeholder:a.mask.placeholder,completed:null},e),j=a.mask.definitions,k=[],l=n=b.length,m=null,a.each(b.split(""),function(a,b){"?"==b?(n--,l=a):j[b]?(k.push(new RegExp(j[b])),null===m&&(m=k.length-1)):k.push(null)}),this.trigger("unmask").each(function(){function i(a){for(;++a=0&&!k[a];);return a}function p(a,b){var c,d;if(!(0>a)){for(c=a,d=i(b);n>c;c++)if(k[c]){if(!(n>d&&k[c].test(x[d])))break;x[c]=x[d],x[d]=e.placeholder,d=i(d)}u(),w.caret(Math.max(m,a))}}function q(a){var b,c,d,f;for(b=a,c=e.placeholder;n>b;b++)if(k[b]){if(d=i(b),f=x[b],x[b]=c,!(n>d&&k[d].test(f)))break;c=f}}function r(a){var b,c,d,e=a.which;8===e||46===e||f&&127===e?(b=w.caret(),c=b.begin,d=b.end,0===d-c&&(c=46!==e?o(c):d=i(c-1),d=46===e?i(d):d),t(c,d),p(c,d-1),a.preventDefault()):27==e&&(w.val(y),w.caret(0,v()),a.preventDefault())}function s(b){var c,d,f,g=b.which,j=w.caret();if(0==g){if(j.begin>=n)return w.val(w.val().substr(0,n)),b.preventDefault(),!1;j.begin==j.end&&(g=w.val().charCodeAt(j.begin-1),j.begin--,j.end--)}b.ctrlKey||b.altKey||b.metaKey||32>g||g&&(0!==j.end-j.begin&&(t(j.begin,j.end),p(j.begin,j.end-1)),c=i(j.begin-1),n>c&&(d=String.fromCharCode(g),k[c].test(d)&&(q(c),x[c]=d,u(),f=i(c),h?setTimeout(a.proxy(a.fn.caret,w,f),0):w.caret(f),e.completed&&f>=n&&e.completed.call(w))),b.preventDefault())}function t(a,b){var c;for(c=a;b>c&&n>c;c++)k[c]&&(x[c]=e.placeholder)}function u(){w.val(x.join(""))}function v(a){var b,c,d,f=w.val(),g=-1;for(b=0,d=0;n>b;b++)if(k[b]){for(x[b]=e.placeholder;d++f.length)break}else x[b]===f.charAt(d)&&b!==l&&(d++,g=b);return a?u():l>g+1?(w.val(""),t(0,n)):(u(),w.val(w.val().substring(0,g+1))),l?b:m}var w=a(this),x=a.map(b.split(""),function(a){return"?"!=a?j[a]?e.placeholder:a:void 0}),y=w.val();w.data(a.mask.dataName,function(){return a.map(x,function(a,b){return k[b]&&a!=e.placeholder?a:null}).join("")}),w.attr("readonly")||w.one("unmask",function(){w.unbind(".mask").removeData(a.mask.dataName)}).bind("focus.mask",function(){clearTimeout(c);var a;y=w.val(),a=v(),c=setTimeout(function(){u(),a==b.length?w.caret(0,a):w.caret(a)},10)}).bind("blur.mask",function(){v(),w.val()!=y&&w.change()}).bind("keydown.mask",r).bind("keypress.mask",s).bind(d,function(){setTimeout(function(){var a=v(!0);w.caret(a),e.completed&&a==w.val().length&&e.completed.call(w)},0)}),g&&h&&w.bind("keyup.mask",s),v()}))}})}(jQuery); \ No newline at end of file diff --git a/gruntfile.js b/gruntfile.js index 27bd038..2ec3979 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -3,6 +3,31 @@ module.exports = function( grunt ) { grunt.initConfig({ + // TODO: change to read component.json + pkg: require('./package.json'), + + uglify: { + options: { + banner: '/*\n <%= pkg.description %>\n Copyright (c) 2007 - <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)\n Version: <%= pkg.version %>\n*/\n' + }, + + dev: { + options: { + beautify: true + }, + + files: { + 'dist/jquery.maskedinput.js': ['src/jquery.maskedinput.js'] + } + }, + + min: { + files: { + 'dist/jquery.maskedinput.min.js': ['src/jquery.maskedinput.js'] + } + } + }, + jasmine: { full: { src: "src/**/*.js", @@ -21,7 +46,8 @@ module.exports = function( grunt ) { }); grunt.loadNpmTasks("grunt-contrib-jasmine"); + grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.registerTask('test', ['jasmine']); - grunt.registerTask('default', ['test']); + grunt.registerTask('default', ['test', 'uglify']); }; diff --git a/package.json b/package.json index bd9e406..11702b8 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "jquery.maskedinput", "version": "1.3.0", - "author": "Josh Bush", + "author": "Josh Bush (digitalbush.com)", "description": "jQuery Masked Input Plugin", "devDependencies": { "grunt": "0.4.x", "grunt-contrib-jasmine": "0.5.x", - "grunt-contrib-watch": "0.5.x" + "grunt-contrib-watch": "0.5.x", + "grunt-contrib-uglify": "0.2.x" } } diff --git a/src/jquery.maskedinput.js b/src/jquery.maskedinput.js index 5a1fc52..a526da8 100644 --- a/src/jquery.maskedinput.js +++ b/src/jquery.maskedinput.js @@ -1,9 +1,3 @@ -/* - 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 -*/ (function($) { function getPasteEvent() { From 1249c9c928b3c41568bdb529f7e47b0d9db332dc Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Oct 2013 21:57:31 -0400 Subject: [PATCH 5/9] adds documentation about installing grunt-cli --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bcc7370..c95df69 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,9 @@ Setting up your Developer Environment ------------------------------------- jQuery Masked Input uses [NodeJS](http://www.nodejs.org) and [GruntJS](http://www.gruntjs.com) as it's developer platform and build automation tool. -To get your environment setup correctly, you'll need nodejs version 0.8.25 or greater installed. +To get your environment setup correctly, you'll need nodejs version 0.8.25 or greater installed. You'll also need to install the grunt command line tool: + + $ sudo npm install -g grunt-cli Once node is installed on your system all that you need to do is install the developer dependencies and run the grunt build: From 09ccf54932717db47c1cc253efc413d96c8e4115 Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Oct 2013 22:00:03 -0400 Subject: [PATCH 6/9] uglify grunt task does not mangle uncompressed source --- dist/jquery.maskedinput.js | 183 +++++++++++++++++---------------- dist/jquery.maskedinput.min.js | 2 +- gruntfile.js | 3 +- 3 files changed, 100 insertions(+), 88 deletions(-) diff --git a/dist/jquery.maskedinput.js b/dist/jquery.maskedinput.js index f5a5e29..74e2a41 100644 --- a/dist/jquery.maskedinput.js +++ b/dist/jquery.maskedinput.js @@ -2,15 +2,15 @@ jQuery Masked Input Plugin Copyright (c) 2007 - 2013 Josh Bush (digitalbush.com) Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) - Version: 1.3.0 + Version: 1.3.1 */ -!function(a) { - function b() { - var a = document.createElement("input"), b = "onpaste"; - return a.setAttribute(b, ""), "function" == typeof a[b] ? "paste" : "input"; +!function($) { + function getPasteEvent() { + var el = document.createElement("input"), name = "onpaste"; + return el.setAttribute(name, ""), "function" == typeof el[name] ? "paste" : "input"; } - var c, d = b() + ".mask", e = navigator.userAgent, f = /iphone/i.test(e), g = /chrome/i.test(e), h = /android/i.test(e); - a.mask = { + var caretTimeoutId, pasteEventName = getPasteEvent() + ".mask", ua = navigator.userAgent, iPhone = /iphone/i.test(ua), chrome = /chrome/i.test(ua), android = /android/i.test(ua); + $.mask = { definitions: { "9": "[0-9]", a: "[A-Za-z]", @@ -18,114 +18,125 @@ }, dataName: "rawMaskFn", placeholder: "_" - }, a.fn.extend({ - caret: function(a, b) { - var c; - if (0 !== this.length && !this.is(":hidden")) return "number" == typeof a ? (b = "number" == typeof b ? b : a, + }, $.fn.extend({ + caret: function(begin, end) { + var range; + if (0 !== this.length && !this.is(":hidden")) return "number" == typeof begin ? (end = "number" == typeof end ? end : begin, this.each(function() { - this.setSelectionRange ? this.setSelectionRange(a, b) : this.createTextRange && (c = this.createTextRange(), - c.collapse(!0), c.moveEnd("character", b), c.moveStart("character", a), c.select()); - })) : (this[0].setSelectionRange ? (a = this[0].selectionStart, b = this[0].selectionEnd) : document.selection && document.selection.createRange && (c = document.selection.createRange(), - a = 0 - c.duplicate().moveStart("character", -1e5), b = a + c.text.length), { - begin: a, - end: b + this.setSelectionRange ? this.setSelectionRange(begin, end) : this.createTextRange && (range = this.createTextRange(), + range.collapse(!0), range.moveEnd("character", end), range.moveStart("character", begin), + range.select()); + })) : (this[0].setSelectionRange ? (begin = this[0].selectionStart, end = this[0].selectionEnd) : document.selection && document.selection.createRange && (range = document.selection.createRange(), + begin = 0 - range.duplicate().moveStart("character", -1e5), end = begin + range.text.length), + { + begin: begin, + end: end }); }, unmask: function() { return this.trigger("unmask"); }, - mask: function(b, e) { - var i, j, k, l, m, n; - return !b && this.length > 0 ? (i = a(this[0]), i.data(a.mask.dataName)()) : (e = a.extend({ - placeholder: a.mask.placeholder, + mask: function(mask, settings) { + var input, defs, tests, partialPosition, firstNonMaskPos, len; + return !mask && this.length > 0 ? (input = $(this[0]), input.data($.mask.dataName)()) : (settings = $.extend({ + placeholder: $.mask.placeholder, completed: null - }, e), j = a.mask.definitions, k = [], l = n = b.length, m = null, a.each(b.split(""), function(a, b) { - "?" == b ? (n--, l = a) : j[b] ? (k.push(new RegExp(j[b])), null === m && (m = k.length - 1)) : k.push(null); + }, settings), defs = $.mask.definitions, tests = [], partialPosition = len = mask.length, + firstNonMaskPos = null, $.each(mask.split(""), function(i, c) { + "?" == c ? (len--, partialPosition = i) : defs[c] ? (tests.push(new RegExp(defs[c])), + null === firstNonMaskPos && (firstNonMaskPos = tests.length - 1)) : tests.push(null); }), this.trigger("unmask").each(function() { - function i(a) { - for (;++a < n && !k[a]; ) ; - return a; + function seekNext(pos) { + for (;++pos < len && !tests[pos]; ) ; + return pos; } - function o(a) { - for (;--a >= 0 && !k[a]; ) ; - return a; + function seekPrev(pos) { + for (;--pos >= 0 && !tests[pos]; ) ; + return pos; } - function p(a, b) { - var c, d; - if (!(0 > a)) { - for (c = a, d = i(b); n > c; c++) if (k[c]) { - if (!(n > d && k[c].test(x[d]))) break; - x[c] = x[d], x[d] = e.placeholder, d = i(d); + function shiftL(begin, end) { + var i, j; + if (!(0 > begin)) { + for (i = begin, j = seekNext(end); len > i; i++) if (tests[i]) { + if (!(len > j && tests[i].test(buffer[j]))) break; + buffer[i] = buffer[j], buffer[j] = settings.placeholder, j = seekNext(j); } - u(), w.caret(Math.max(m, a)); + writeBuffer(), input.caret(Math.max(firstNonMaskPos, begin)); } } - function q(a) { - var b, c, d, f; - for (b = a, c = e.placeholder; n > b; b++) if (k[b]) { - if (d = i(b), f = x[b], x[b] = c, !(n > d && k[d].test(f))) break; - c = f; + function shiftR(pos) { + var i, c, j, t; + for (i = pos, c = settings.placeholder; len > i; i++) if (tests[i]) { + if (j = seekNext(i), t = buffer[i], buffer[i] = c, !(len > j && tests[j].test(t))) break; + c = t; } } - function r(a) { - var b, c, d, e = a.which; - 8 === e || 46 === e || f && 127 === e ? (b = w.caret(), c = b.begin, d = b.end, - 0 === d - c && (c = 46 !== e ? o(c) : d = i(c - 1), d = 46 === e ? i(d) : d), t(c, d), - p(c, d - 1), a.preventDefault()) : 27 == e && (w.val(y), w.caret(0, v()), a.preventDefault()); + function keydownEvent(e) { + var pos, begin, end, k = e.which; + 8 === k || 46 === k || iPhone && 127 === k ? (pos = input.caret(), begin = pos.begin, + end = pos.end, 0 === end - begin && (begin = 46 !== k ? seekPrev(begin) : end = seekNext(begin - 1), + end = 46 === k ? seekNext(end) : end), clearBuffer(begin, end), shiftL(begin, end - 1), + e.preventDefault()) : 27 == k && (input.val(focusText), input.caret(0, checkVal()), + e.preventDefault()); } - function s(b) { - var c, d, f, g = b.which, j = w.caret(); - if (0 == g) { - if (j.begin >= n) return w.val(w.val().substr(0, n)), b.preventDefault(), !1; - j.begin == j.end && (g = w.val().charCodeAt(j.begin - 1), j.begin--, j.end--); + function keypressEvent(e) { + var p, c, next, k = e.which, pos = input.caret(); + if (0 == k) { + if (pos.begin >= len) return input.val(input.val().substr(0, len)), e.preventDefault(), + !1; + pos.begin == pos.end && (k = input.val().charCodeAt(pos.begin - 1), pos.begin--, + pos.end--); } - b.ctrlKey || b.altKey || b.metaKey || 32 > g || g && (0 !== j.end - j.begin && (t(j.begin, j.end), - p(j.begin, j.end - 1)), c = i(j.begin - 1), n > c && (d = String.fromCharCode(g), - k[c].test(d) && (q(c), x[c] = d, u(), f = i(c), h ? setTimeout(a.proxy(a.fn.caret, w, f), 0) : w.caret(f), - e.completed && f >= n && e.completed.call(w))), b.preventDefault()); + e.ctrlKey || e.altKey || e.metaKey || 32 > k || k && (0 !== pos.end - pos.begin && (clearBuffer(pos.begin, pos.end), + shiftL(pos.begin, pos.end - 1)), p = seekNext(pos.begin - 1), len > p && (c = String.fromCharCode(k), + tests[p].test(c) && (shiftR(p), buffer[p] = c, writeBuffer(), next = seekNext(p), + android ? setTimeout($.proxy($.fn.caret, input, next), 0) : input.caret(next), settings.completed && next >= len && settings.completed.call(input))), + e.preventDefault()); } - function t(a, b) { - var c; - for (c = a; b > c && n > c; c++) k[c] && (x[c] = e.placeholder); + function clearBuffer(start, end) { + var i; + for (i = start; end > i && len > i; i++) tests[i] && (buffer[i] = settings.placeholder); } - function u() { - w.val(x.join("")); + function writeBuffer() { + input.val(buffer.join("")); } - function v(a) { - var b, c, d, f = w.val(), g = -1; - for (b = 0, d = 0; n > b; b++) if (k[b]) { - for (x[b] = e.placeholder; d++ < f.length; ) if (c = f.charAt(d - 1), k[b].test(c)) { - x[b] = c, g = b; + function checkVal(allow) { + var i, c, pos, test = input.val(), lastMatch = -1; + for (i = 0, pos = 0; len > i; i++) if (tests[i]) { + for (buffer[i] = settings.placeholder; pos++ < test.length; ) if (c = test.charAt(pos - 1), + tests[i].test(c)) { + buffer[i] = c, lastMatch = i; break; } - if (d > f.length) break; - } else x[b] === f.charAt(d) && b !== l && (d++, g = b); - return a ? u() : l > g + 1 ? (w.val(""), t(0, n)) : (u(), w.val(w.val().substring(0, g + 1))), - l ? b : m; + if (pos > test.length) break; + } else buffer[i] === test.charAt(pos) && i !== partialPosition && (pos++, lastMatch = i); + return allow ? writeBuffer() : partialPosition > lastMatch + 1 ? (input.val(""), + clearBuffer(0, len)) : (writeBuffer(), input.val(input.val().substring(0, lastMatch + 1))), + partialPosition ? i : firstNonMaskPos; } - var w = a(this), x = a.map(b.split(""), function(a) { - return "?" != a ? j[a] ? e.placeholder : a : void 0; - }), y = w.val(); - w.data(a.mask.dataName, function() { - return a.map(x, function(a, b) { - return k[b] && a != e.placeholder ? a : null; + var input = $(this), buffer = $.map(mask.split(""), function(c) { + return "?" != c ? defs[c] ? settings.placeholder : c : void 0; + }), focusText = input.val(); + input.data($.mask.dataName, function() { + return $.map(buffer, function(c, i) { + return tests[i] && c != settings.placeholder ? c : null; }).join(""); - }), w.attr("readonly") || w.one("unmask", function() { - w.unbind(".mask").removeData(a.mask.dataName); + }), input.attr("readonly") || input.one("unmask", function() { + input.unbind(".mask").removeData($.mask.dataName); }).bind("focus.mask", function() { - clearTimeout(c); - var a; - y = w.val(), a = v(), c = setTimeout(function() { - u(), a == b.length ? w.caret(0, a) : w.caret(a); + clearTimeout(caretTimeoutId); + var pos; + focusText = input.val(), pos = checkVal(), caretTimeoutId = setTimeout(function() { + writeBuffer(), pos == mask.length ? input.caret(0, pos) : input.caret(pos); }, 10); }).bind("blur.mask", function() { - v(), w.val() != y && w.change(); - }).bind("keydown.mask", r).bind("keypress.mask", s).bind(d, function() { + checkVal(), input.val() != focusText && input.change(); + }).bind("keydown.mask", keydownEvent).bind("keypress.mask", keypressEvent).bind(pasteEventName, function() { setTimeout(function() { - var a = v(!0); - w.caret(a), e.completed && a == w.val().length && e.completed.call(w); + var pos = checkVal(!0); + input.caret(pos), settings.completed && pos == input.val().length && settings.completed.call(input); }, 0); - }), g && h && w.bind("keyup.mask", s), v(); + }), chrome && android && input.bind("keyup.mask", keypressEvent), checkVal(); })); } }); diff --git a/dist/jquery.maskedinput.min.js b/dist/jquery.maskedinput.min.js index 45baf54..683f0e1 100644 --- a/dist/jquery.maskedinput.min.js +++ b/dist/jquery.maskedinput.min.js @@ -2,6 +2,6 @@ jQuery Masked Input Plugin Copyright (c) 2007 - 2013 Josh Bush (digitalbush.com) Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) - Version: 1.3.0 + Version: 1.3.1 */ !function(a){function b(){var a=document.createElement("input"),b="onpaste";return a.setAttribute(b,""),"function"==typeof a[b]?"paste":"input"}var c,d=b()+".mask",e=navigator.userAgent,f=/iphone/i.test(e),g=/chrome/i.test(e),h=/android/i.test(e);a.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},dataName:"rawMaskFn",placeholder:"_"},a.fn.extend({caret:function(a,b){var c;if(0!==this.length&&!this.is(":hidden"))return"number"==typeof a?(b="number"==typeof b?b:a,this.each(function(){this.setSelectionRange?this.setSelectionRange(a,b):this.createTextRange&&(c=this.createTextRange(),c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select())})):(this[0].setSelectionRange?(a=this[0].selectionStart,b=this[0].selectionEnd):document.selection&&document.selection.createRange&&(c=document.selection.createRange(),a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length),{begin:a,end:b})},unmask:function(){return this.trigger("unmask")},mask:function(b,e){var i,j,k,l,m,n;return!b&&this.length>0?(i=a(this[0]),i.data(a.mask.dataName)()):(e=a.extend({placeholder:a.mask.placeholder,completed:null},e),j=a.mask.definitions,k=[],l=n=b.length,m=null,a.each(b.split(""),function(a,b){"?"==b?(n--,l=a):j[b]?(k.push(new RegExp(j[b])),null===m&&(m=k.length-1)):k.push(null)}),this.trigger("unmask").each(function(){function i(a){for(;++a=0&&!k[a];);return a}function p(a,b){var c,d;if(!(0>a)){for(c=a,d=i(b);n>c;c++)if(k[c]){if(!(n>d&&k[c].test(x[d])))break;x[c]=x[d],x[d]=e.placeholder,d=i(d)}u(),w.caret(Math.max(m,a))}}function q(a){var b,c,d,f;for(b=a,c=e.placeholder;n>b;b++)if(k[b]){if(d=i(b),f=x[b],x[b]=c,!(n>d&&k[d].test(f)))break;c=f}}function r(a){var b,c,d,e=a.which;8===e||46===e||f&&127===e?(b=w.caret(),c=b.begin,d=b.end,0===d-c&&(c=46!==e?o(c):d=i(c-1),d=46===e?i(d):d),t(c,d),p(c,d-1),a.preventDefault()):27==e&&(w.val(y),w.caret(0,v()),a.preventDefault())}function s(b){var c,d,f,g=b.which,j=w.caret();if(0==g){if(j.begin>=n)return w.val(w.val().substr(0,n)),b.preventDefault(),!1;j.begin==j.end&&(g=w.val().charCodeAt(j.begin-1),j.begin--,j.end--)}b.ctrlKey||b.altKey||b.metaKey||32>g||g&&(0!==j.end-j.begin&&(t(j.begin,j.end),p(j.begin,j.end-1)),c=i(j.begin-1),n>c&&(d=String.fromCharCode(g),k[c].test(d)&&(q(c),x[c]=d,u(),f=i(c),h?setTimeout(a.proxy(a.fn.caret,w,f),0):w.caret(f),e.completed&&f>=n&&e.completed.call(w))),b.preventDefault())}function t(a,b){var c;for(c=a;b>c&&n>c;c++)k[c]&&(x[c]=e.placeholder)}function u(){w.val(x.join(""))}function v(a){var b,c,d,f=w.val(),g=-1;for(b=0,d=0;n>b;b++)if(k[b]){for(x[b]=e.placeholder;d++f.length)break}else x[b]===f.charAt(d)&&b!==l&&(d++,g=b);return a?u():l>g+1?(w.val(""),t(0,n)):(u(),w.val(w.val().substring(0,g+1))),l?b:m}var w=a(this),x=a.map(b.split(""),function(a){return"?"!=a?j[a]?e.placeholder:a:void 0}),y=w.val();w.data(a.mask.dataName,function(){return a.map(x,function(a,b){return k[b]&&a!=e.placeholder?a:null}).join("")}),w.attr("readonly")||w.one("unmask",function(){w.unbind(".mask").removeData(a.mask.dataName)}).bind("focus.mask",function(){clearTimeout(c);var a;y=w.val(),a=v(),c=setTimeout(function(){u(),a==b.length?w.caret(0,a):w.caret(a)},10)}).bind("blur.mask",function(){v(),w.val()!=y&&w.change()}).bind("keydown.mask",r).bind("keypress.mask",s).bind(d,function(){setTimeout(function(){var a=v(!0);w.caret(a),e.completed&&a==w.val().length&&e.completed.call(w)},0)}),g&&h&&w.bind("keyup.mask",s),v()}))}})}(jQuery); \ No newline at end of file diff --git a/gruntfile.js b/gruntfile.js index 2ec3979..76bb0e8 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -13,7 +13,8 @@ module.exports = function( grunt ) { dev: { options: { - beautify: true + beautify: true, + mangle: false }, files: { From bf5b3a306baf9333bad334af7d550150616b609c Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Tue, 29 Oct 2013 22:00:13 -0400 Subject: [PATCH 7/9] corrects package version to 1.3.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 11702b8..8b3a95d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jquery.maskedinput", - "version": "1.3.0", + "version": "1.3.1", "author": "Josh Bush (digitalbush.com)", "description": "jQuery Masked Input Plugin", From 8250c1d12982ecd5d1f173a847c9b538221b2487 Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Thu, 31 Oct 2013 22:03:57 -0400 Subject: [PATCH 8/9] Jasmine Spec file suffix is not case sensitive --- gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gruntfile.js b/gruntfile.js index 76bb0e8..5896f86 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -33,7 +33,7 @@ module.exports = function( grunt ) { full: { src: "src/**/*.js", options: { - specs: "spec/*Spec.js", + specs: "spec/*[S|s]pec.js", vendor: [ "spec/lib/matchers.js", "spec/lib/jasmine-species/jasmine-grammar.js", From 00f855f840770bd8c1e91977266b83c72d1a614c Mon Sep 17 00:00:00 2001 From: Jared Barboza Date: Thu, 31 Oct 2013 22:08:22 -0400 Subject: [PATCH 9/9] removes spec/SpecRunner.html --- spec/SpecRunner.html | 68 -------------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 spec/SpecRunner.html diff --git a/spec/SpecRunner.html b/spec/SpecRunner.html deleted file mode 100644 index 0339b85..0000000 --- a/spec/SpecRunner.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - Masked Input Plugin Tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -