From 75c27c9f148276ac33ddab079b68e12c103c985e Mon Sep 17 00:00:00 2001
From: Simon Timms
Date: Fri, 18 Jan 2013 13:15:57 -0800
Subject: [PATCH 01/87] Create jquery.makedinput.nuspec
---
dist/jquery.makedinput.nuspec | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 dist/jquery.makedinput.nuspec
diff --git a/dist/jquery.makedinput.nuspec b/dist/jquery.makedinput.nuspec
new file mode 100644
index 0000000..632c0c4
--- /dev/null
+++ b/dist/jquery.makedinput.nuspec
@@ -0,0 +1,17 @@
+
+
+
+ jQuery.MaskedInput
+ 1.3.1.0
+ digitalBush
+ stimms
+ https://github.com/digitalBush/jquery.maskedinput/blob/master/LICENSE
+ http://digitalbush.com/projects/masked-input-plugin/
+ false
+ A jQuery plugin which applies a mask to input boxes to provide both a UI hint for users as well as some rudimentary input checking.
+ jQuery,plugins
+
+
+
+
+
From 5ebc74d05ca3a5401ac6543279a09367a55f888b Mon Sep 17 00:00:00 2001
From: holtkamp
Date: Tue, 27 Aug 2013 19:22:45 +0200
Subject: [PATCH 02/87] Properly closed mask object definition to prevent
JavaScript error in IE7
Unclosed object generates a JavaScript error in IE7: "Expected identifier, string, or number"
---
dist/jquery.maskedinput.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dist/jquery.maskedinput.js b/dist/jquery.maskedinput.js
index 49a5a72..89ce020 100644
--- a/dist/jquery.maskedinput.js
+++ b/dist/jquery.maskedinput.js
@@ -26,7 +26,7 @@ $.mask = {
'*': "[A-Za-z0-9]"
},
dataName: "rawMaskFn",
- placeholder: '_',
+ placeholder: '_'
};
$.fn.extend({
@@ -335,4 +335,4 @@ $.fn.extend({
});
-})(jQuery);
\ No newline at end of file
+})(jQuery);
From 0dea72e516f8c3443b1e321d5504421d43a5c311 Mon Sep 17 00:00:00 2001
From: Greg Burghardt
Date: Wed, 9 Oct 2013 11:07:46 -0400
Subject: [PATCH 03/87] Added "autoclear" setting so invalid values persist
To increase usability, add a new setting that keeps invalid values in the
input field to give the user a chance to correct a mistake. If the user
fat fingers the value on accident and doesn't realize it before tabbing
away from the form field, the invalid value will remain so the user can
correct the value rather than retyping it.
- Added new setting called "autoclear", defaulting to true, to maintain
existing behavior.
- When autoclear=false, leave invalid values visible so the user can
correct their mistake.
- Added test coverage for when the mask(...) is first invoked
(Init.Spec.js)
- Added scenarios to Focus.Spec.js to cover new functionality
- Repackaged the distribution version to include this new feature
---
dist/jquery.maskedinput.js | 33 ++++++++++++++--------
dist/jquery.maskedinput.min.js | 2 +-
spec/Focus.Spec.js | 32 +++++++++++++++++++++
spec/Init.Spec.js | 51 ++++++++++++++++++++++++++++++++++
spec/SpecRunner.html | 3 +-
src/jquery.maskedinput.js | 27 +++++++++++++-----
6 files changed, 128 insertions(+), 20 deletions(-)
create mode 100644 spec/Init.Spec.js
diff --git a/dist/jquery.maskedinput.js b/dist/jquery.maskedinput.js
index 89ce020..7ecfcc0 100644
--- a/dist/jquery.maskedinput.js
+++ b/dist/jquery.maskedinput.js
@@ -9,7 +9,7 @@
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",
@@ -25,6 +25,7 @@ $.mask = {
'a': "[A-Za-z]",
'*': "[A-Za-z0-9]"
},
+ autoclear: true,
dataName: "rawMaskFn",
placeholder: '_'
};
@@ -79,6 +80,7 @@ $.fn.extend({
return input.data($.mask.dataName)();
}
settings = $.extend({
+ autoclear: $.mask.autoclear,
placeholder: $.mask.placeholder, // Load default placeholder
completed: null
}, settings);
@@ -251,7 +253,8 @@ $.fn.extend({
var test = input.val(),
lastMatch = -1,
i,
- c;
+ c,
+ pos;
for (i = 0, pos = 0; i < len; i++) {
if (tests[i]) {
@@ -275,8 +278,14 @@ $.fn.extend({
if (allow) {
writeBuffer();
} else if (lastMatch + 1 < partialPosition) {
- input.val("");
- clearBuffer(0, len);
+ if (settings.autoclear) {
+ input.val("");
+ clearBuffer(0, len);
+ } else {
+ // Invalid value, but we opt to show the value to the
+ // user and allow them to correct their mistake.
+ writeBuffer();
+ }
} else {
writeBuffer();
input.val(input.val().substring(0, lastMatch + 1));
@@ -299,12 +308,12 @@ $.fn.extend({
})
.bind("focus.mask", function() {
clearTimeout(caretTimeoutId);
- var pos,
- moveCaret;
+ var pos;
focusText = input.val();
+
pos = checkVal();
-
+
caretTimeoutId = setTimeout(function(){
writeBuffer();
if (pos == mask.length) {
@@ -316,23 +325,25 @@ $.fn.extend({
})
.bind("blur.mask", function() {
checkVal();
+
if (input.val() != focusText)
input.change();
})
.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);
});
- checkVal(); //Perform initial check for existing values
+
+ checkVal(); //Perform initial check for existing values
});
}
});
-})(jQuery);
+})(jQuery);
\ No newline at end of file
diff --git a/dist/jquery.maskedinput.min.js b/dist/jquery.maskedinput.min.js
index 0d9ce6e..558899e 100644
--- a/dist/jquery.maskedinput.min.js
+++ b/dist/jquery.maskedinput.min.js
@@ -4,4 +4,4 @@
Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
Version: 1.3.1
*/
-(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(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),c=/android/i.test(r);e.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,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 o,l,u,s,f,h;return!t&&this.length>0?(o=e(this[0]),o.data(e.mask.dataName)()):(r=e.extend({autoclear:e.mask.autoclear,placeholder:e.mask.placeholder,completed:null},r),l=e.mask.definitions,u=[],s=h=t.length,f=null,e.each(t.split(""),function(e,t){"?"==t?(h--,s=e):l[t]?(u.push(new RegExp(l[t])),null===f&&(f=u.length-1)):u.push(null)}),this.trigger("unmask").each(function(){function o(e){for(;++e=0&&!u[e];);return e}function m(e,t){var n,a;if(!(0>e)){for(n=e,a=o(t);h>n;n++)if(u[n]){if(!(h>a&&u[n].test(R[a])))break;R[n]=R[a],R[a]=r.placeholder,a=o(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(u[t]){if(a=o(t),i=R[t],R[t]=n,!(h>a&&u[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=o(n-1),a=46===r?o(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,s=x.caret();t.ctrlKey||t.altKey||t.metaKey||32>l||l&&(0!==s.end-s.begin&&(k(s.begin,s.end),m(s.begin,s.end-1)),n=o(s.begin-1),h>n&&(a=String.fromCharCode(l),u[n].test(a)&&(p(n),R[n]=a,b(),i=o(n),c?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++)u[n]&&(R[n]=r.placeholder)}function b(){x.val(R.join(""))}function y(e){var t,n,a,i=x.val(),c=-1;for(t=0,a=0;h>t;t++)if(u[t]){for(R[t]=r.placeholder;a++i.length)break}else R[t]===i.charAt(a)&&t!==s&&(a++,c=t);return e?b():s>c+1?r.autoclear?(x.val(""),k(0,h)):b():(b(),x.val(x.val().substring(0,c+1))),s?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 u[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
diff --git a/spec/Focus.Spec.js b/spec/Focus.Spec.js
index b7a2143..01ddebd 100644
--- a/spec/Focus.Spec.js
+++ b/spec/Focus.Spec.js
@@ -50,6 +50,24 @@ feature("Focusing A Masked Input",function(){
expect(error).toBeUndefined();
})
});
+
+ scenario("Mask contains a partial value with autoclear set to false",function(){
+ given("the input has a partial value",function(){
+ input.val("1");
+ });
+ given("a mask with two placeholders and autoclear=false",function(){
+ input.mask("99", { autoclear: false });
+ });
+ when("focusing on the input",function(){
+ input.focus();
+ });
+ then("the value should be partially filled out",function(){
+ expect(input).toHaveValue("1_");
+ });
+ then("the input partial value should remain",function(){
+ expect(input).toHaveValue("1_");
+ });
+ });
});
feature("Leaving A Masked Input",function(){
@@ -76,6 +94,20 @@ feature("Leaving A Masked Input",function(){
expect(input).toHaveValue("");
});
});
+
+ scenario("Empty placeholders remaining with autoclear set to false",function(){
+ given("a mask with two placeholders",function(){
+ input.mask("99", { autoclear: false });
+ });
+ when("typing one character and blurring",function(){
+ input.caret(0);
+ input.mashKeys("1")
+ input.blur();
+ });
+ then("value should remain visible with placeholders",function(){
+ expect(input).toHaveValue("1_");
+ });
+ });
});
feature("Optional marker",function(){
diff --git a/spec/Init.Spec.js b/spec/Init.Spec.js
new file mode 100644
index 0000000..1b64130
--- /dev/null
+++ b/spec/Init.Spec.js
@@ -0,0 +1,51 @@
+feature("Initializing a Mask",function(){
+ scenario("An input with no value",function(){
+ given("an input with no value",function(){
+ input.val("");
+ });
+ when("setting a mask with two placeholders",function(){
+ input.mask("99");
+ });
+ then("the value should be an empty string",function(){
+ expect(input).toHaveValue("");
+ });
+ });
+
+ scenario("An input with a valid value and no placeholders remaining",function(){
+ given("an input with a valid value",function(){
+ input.val("5555555555");
+ });
+ when("setting a mask",function(){
+ input.mask("(999) 999-9999");
+ });
+ then("the value should be intact",function(){
+ expect(input).toHaveValue("(555) 555-5555");
+ });
+ });
+
+ scenario("An input with an invalid value and placeholders remaining",function(){
+ given("an invalid input value",function(){
+ input.val("55555555");
+ });
+ when("setting a mask",function(){
+ input.mask("(999) 999-9999");
+ });
+ then("the value should be empty",function(){
+ expect(input).toHaveValue("");
+ });
+ });
+
+ scenario("An input with an invalid value, placeholders remaining and autoclear set to false",function(){
+ given("an invalid input value",function(){
+ input.val("55555555");
+ });
+ when("setting a mask with autoclear set to false",function(){
+ input.mask("(999) 999-9999", { autoclear: false });
+ });
+ then("the value be intact with placeholders visible",function(){
+ expect(input).toHaveValue("(555) 555-55__");
+ });
+ });
+
+ scenario("An input with an invalid value and placeholders remaining");
+});
diff --git a/spec/SpecRunner.html b/spec/SpecRunner.html
index 0339b85..6747474 100644
--- a/spec/SpecRunner.html
+++ b/spec/SpecRunner.html
@@ -40,7 +40,8 @@
-
+
+
diff --git a/src/jquery.maskedinput.js b/src/jquery.maskedinput.js
index 749da65..6382f70 100644
--- a/src/jquery.maskedinput.js
+++ b/src/jquery.maskedinput.js
@@ -2,7 +2,7 @@ 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",
@@ -18,6 +18,7 @@ $.mask = {
'a': "[A-Za-z]",
'*': "[A-Za-z0-9]"
},
+ autoclear: true,
dataName: "rawMaskFn",
placeholder: '_'
};
@@ -72,6 +73,7 @@ $.fn.extend({
return input.data($.mask.dataName)();
}
settings = $.extend({
+ autoclear: $.mask.autoclear,
placeholder: $.mask.placeholder, // Load default placeholder
completed: null
}, settings);
@@ -269,8 +271,16 @@ $.fn.extend({
if (allow) {
writeBuffer();
} else if (lastMatch + 1 < partialPosition) {
- input.val("");
- clearBuffer(0, len);
+ if (settings.autoclear) {
+ // Invalid value. Remove it and replace it with the
+ // mask, which is the default behavior.
+ input.val("");
+ clearBuffer(0, len);
+ } else {
+ // Invalid value, but we opt to show the value to the
+ // user and allow them to correct their mistake.
+ writeBuffer();
+ }
} else {
writeBuffer();
input.val(input.val().substring(0, lastMatch + 1));
@@ -296,8 +306,9 @@ $.fn.extend({
var pos;
focusText = input.val();
+
pos = checkVal();
-
+
caretTimeoutId = setTimeout(function(){
writeBuffer();
if (pos == mask.length) {
@@ -309,20 +320,22 @@ $.fn.extend({
})
.bind("blur.mask", function() {
checkVal();
+
if (input.val() != focusText)
input.change();
})
.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);
});
- checkVal(); //Perform initial check for existing values
+
+ checkVal(); //Perform initial check for existing values
});
}
});
From b9c0097c176d41c9d7e3d3dd6be5fed8115abcda Mon Sep 17 00:00:00 2001
From: Greg Burghardt
Date: Thu, 10 Oct 2013 13:17:49 -0400
Subject: [PATCH 04/87] Fixing default mask display with "autoclear" set to
false
When a mask is initialized, a text field with an empty value should show
up as a blank field. When "autoclear" was set to false, it showed the mask
even when the user did not have focus on the field. This fixes that issue.
---
demo/index.html | 8 +++++---
dist/jquery.maskedinput.js | 5 ++++-
dist/jquery.maskedinput.min.js | 2 +-
spec/Init.Spec.js | 12 +++++++++++-
src/jquery.maskedinput.js | 3 ++-
5 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/demo/index.html b/demo/index.html
index 60d7e12..68dfe10 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -2,7 +2,7 @@
jQuery Mask Test
-
+
@@ -38,6 +39,7 @@
| Eye Script | | ~9.99 ~9.99 999 |
| Purchase Order | | aaa-999-*** |
| Percent | | 99% |
+ | Phone (autoclear=false) | | 99% |
diff --git a/dist/jquery.maskedinput.js b/dist/jquery.maskedinput.js
index 7ecfcc0..656174f 100644
--- a/dist/jquery.maskedinput.js
+++ b/dist/jquery.maskedinput.js
@@ -114,6 +114,7 @@ $.fn.extend({
return defs[c] ? settings.placeholder : c;
}
}),
+ defaultBuffer = buffer.join(''),
focusText = input.val();
function seekNext(pos) {
@@ -278,7 +279,9 @@ $.fn.extend({
if (allow) {
writeBuffer();
} else if (lastMatch + 1 < partialPosition) {
- if (settings.autoclear) {
+ if (settings.autoclear || buffer.join('') === defaultBuffer) {
+ // Invalid value. Remove it and replace it with the
+ // mask, which is the default behavior.
input.val("");
clearBuffer(0, len);
} else {
diff --git a/dist/jquery.maskedinput.min.js b/dist/jquery.maskedinput.min.js
index 558899e..9c6056c 100644
--- a/dist/jquery.maskedinput.min.js
+++ b/dist/jquery.maskedinput.min.js
@@ -4,4 +4,4 @@
Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
Version: 1.3.1
*/
-!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),c=/android/i.test(r);e.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,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 o,l,u,s,f,h;return!t&&this.length>0?(o=e(this[0]),o.data(e.mask.dataName)()):(r=e.extend({autoclear:e.mask.autoclear,placeholder:e.mask.placeholder,completed:null},r),l=e.mask.definitions,u=[],s=h=t.length,f=null,e.each(t.split(""),function(e,t){"?"==t?(h--,s=e):l[t]?(u.push(new RegExp(l[t])),null===f&&(f=u.length-1)):u.push(null)}),this.trigger("unmask").each(function(){function o(e){for(;++e=0&&!u[e];);return e}function m(e,t){var n,a;if(!(0>e)){for(n=e,a=o(t);h>n;n++)if(u[n]){if(!(h>a&&u[n].test(R[a])))break;R[n]=R[a],R[a]=r.placeholder,a=o(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(u[t]){if(a=o(t),i=R[t],R[t]=n,!(h>a&&u[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=o(n-1),a=46===r?o(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,s=x.caret();t.ctrlKey||t.altKey||t.metaKey||32>l||l&&(0!==s.end-s.begin&&(k(s.begin,s.end),m(s.begin,s.end-1)),n=o(s.begin-1),h>n&&(a=String.fromCharCode(l),u[n].test(a)&&(p(n),R[n]=a,b(),i=o(n),c?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++)u[n]&&(R[n]=r.placeholder)}function b(){x.val(R.join(""))}function y(e){var t,n,a,i=x.val(),c=-1;for(t=0,a=0;h>t;t++)if(u[t]){for(R[t]=r.placeholder;a++i.length)break}else R[t]===i.charAt(a)&&t!==s&&(a++,c=t);return e?b():s>c+1?r.autoclear?(x.val(""),k(0,h)):b():(b(),x.val(x.val().substring(0,c+1))),s?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 u[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(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),c=/android/i.test(r);e.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,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 o,l,u,s,f,h;return!t&&this.length>0?(o=e(this[0]),o.data(e.mask.dataName)()):(r=e.extend({autoclear:e.mask.autoclear,placeholder:e.mask.placeholder,completed:null},r),l=e.mask.definitions,u=[],s=h=t.length,f=null,e.each(t.split(""),function(e,t){"?"==t?(h--,s=e):l[t]?(u.push(new RegExp(l[t])),null===f&&(f=u.length-1)):u.push(null)}),this.trigger("unmask").each(function(){function o(e){for(;++e=0&&!u[e];);return e}function m(e,t){var n,a;if(!(0>e)){for(n=e,a=o(t);h>n;n++)if(u[n]){if(!(h>a&&u[n].test(R[a])))break;R[n]=R[a],R[a]=r.placeholder,a=o(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(u[t]){if(a=o(t),i=R[t],R[t]=n,!(h>a&&u[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=o(n-1),a=46===r?o(a):a),k(n,a),m(n,a-1),e.preventDefault()):27==r&&(x.val(A),x.caret(0,y()),e.preventDefault())}function v(t){var n,a,i,l=t.which,s=x.caret();t.ctrlKey||t.altKey||t.metaKey||32>l||l&&(0!==s.end-s.begin&&(k(s.begin,s.end),m(s.begin,s.end-1)),n=o(s.begin-1),h>n&&(a=String.fromCharCode(l),u[n].test(a)&&(p(n),R[n]=a,b(),i=o(n),c?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++)u[n]&&(R[n]=r.placeholder)}function b(){x.val(R.join(""))}function y(e){var t,n,a,i=x.val(),c=-1;for(t=0,a=0;h>t;t++)if(u[t]){for(R[t]=r.placeholder;a++i.length)break}else R[t]===i.charAt(a)&&t!==s&&(a++,c=t);return e?b():s>c+1?r.autoclear||R.join("")===S?(x.val(""),k(0,h)):b():(b(),x.val(x.val().substring(0,c+1))),s?t:f}var x=e(this),R=e.map(t.split(""),function(e){return"?"!=e?l[e]?r.placeholder:e:void 0}),S=R.join(""),A=x.val();x.data(e.mask.dataName,function(){return e.map(R,function(e,t){return u[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;A=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()!=A&&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
diff --git a/spec/Init.Spec.js b/spec/Init.Spec.js
index 1b64130..0bd7dea 100644
--- a/spec/Init.Spec.js
+++ b/spec/Init.Spec.js
@@ -47,5 +47,15 @@ feature("Initializing a Mask",function(){
});
});
- scenario("An input with an invalid value and placeholders remaining");
+ scenario("An input no value and autoclear set to false", function() {
+ given("an input with no value",function(){
+ input.val("");
+ });
+ when("setting a mask with autoclear set to false",function(){
+ input.mask("(999) 999-9999", { autoclear: false });
+ });
+ then("the value should be empty",function(){
+ expect(input).toHaveValue("");
+ });
+ });
});
diff --git a/src/jquery.maskedinput.js b/src/jquery.maskedinput.js
index 6382f70..060a946 100644
--- a/src/jquery.maskedinput.js
+++ b/src/jquery.maskedinput.js
@@ -107,6 +107,7 @@ $.fn.extend({
return defs[c] ? settings.placeholder : c;
}
}),
+ defaultBuffer = buffer.join(''),
focusText = input.val();
function seekNext(pos) {
@@ -271,7 +272,7 @@ $.fn.extend({
if (allow) {
writeBuffer();
} else if (lastMatch + 1 < partialPosition) {
- if (settings.autoclear) {
+ if (settings.autoclear || buffer.join('') === defaultBuffer) {
// Invalid value. Remove it and replace it with the
// mask, which is the default behavior.
input.val("");
From e677e8da7765a4e8ad90ab7d3a9e58daa7ea723d Mon Sep 17 00:00:00 2001
From: b2k
Date: Fri, 23 Aug 2013 14:11:01 -0500
Subject: [PATCH 05/87] Fix for chrome browser on Android
On a Samsung Galaxy, Chrome version 28 does not throw the keypress event.
Here is a fix for that.
---
src/jquery.maskedinput.js | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/jquery.maskedinput.js b/src/jquery.maskedinput.js
index 749da65..0869182 100644
--- a/src/jquery.maskedinput.js
+++ b/src/jquery.maskedinput.js
@@ -8,6 +8,7 @@ function getPasteEvent() {
var pasteEventName = getPasteEvent() + ".mask",
ua = navigator.userAgent,
iPhone = /iphone/i.test(ua),
+ chrome = /chrome/i.test(ua),
android=/android/i.test(ua),
caretTimeoutId;
@@ -195,6 +196,22 @@ $.fn.extend({
c,
next;
+ if (k == 0) {
+ // unable to detect key pressed. Grab it from pos and adjust
+ // this is a failsafe for mobile chrome
+ // which can't detect keypress events
+ // reliably
+ if (pos.begin >= len) {
+ input.val(input.val().substr(0, len));
+ e.preventDefault();
+ return false;
+ }
+ if (pos.begin == pos.end) {
+ k = input.val().charCodeAt(pos.begin - 1);
+ pos.begin--;
+ pos.end--;
+ }
+ }
if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
return;
} else if (k) {
@@ -322,8 +339,10 @@ $.fn.extend({
settings.completed.call(input);
}, 0);
});
+ if (chrome) {
+ input.bind("keyup.mask", keypressEvent);
+ }
checkVal(); //Perform initial check for existing values
});
}
});
-
From 4791c99777c8468274e19401f5024dca0059d7e8 Mon Sep 17 00:00:00 2001
From: b2k
Date: Fri, 23 Aug 2013 14:15:57 -0500
Subject: [PATCH 06/87] Add android to if statement
---
src/jquery.maskedinput.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/jquery.maskedinput.js b/src/jquery.maskedinput.js
index 0869182..9c0d392 100644
--- a/src/jquery.maskedinput.js
+++ b/src/jquery.maskedinput.js
@@ -339,7 +339,7 @@ $.fn.extend({
settings.completed.call(input);
}, 0);
});
- if (chrome) {
+ if (chrome && android) {
input.bind("keyup.mask", keypressEvent);
}
checkVal(); //Perform initial check for existing values
From 0589b7ccc3c78aad5c42aefa23b1a34b4e1c6bf6 Mon Sep 17 00:00:00 2001
From: Jared Barboza
Date: Mon, 28 Oct 2013 23:49:18 -0400
Subject: [PATCH 07/87] Changes the Jakefile to work with node v0.10.x
Node introduced a breaking change in v0.10
where all FS module actions require a callback
to be passed.
This change simply passes an empty callback that
will swallow any errors passed in. Basically
keeping things the same as they were in node v0.8.x
Read More:
https://github.com/joyent/node/issues/5005
---
Jakefile | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Jakefile b/Jakefile
index 5001cb7..901dc9f 100644
--- a/Jakefile
+++ b/Jakefile
@@ -5,27 +5,27 @@ var Handlebars=require("handlebars"),
distPath='dist/';
Handlebars.registerHelper('include', function(context) {
- return fs.readFileSync(context,'utf8');
+ return fs.readFileSync(context,'utf8', function() { /* swallow errors */ });
});
-function keepComment(node,comment){
+function keepComment(node,comment){
return comment.type === "comment2";
}
task('clean',function(){
- fs.rmdir(distPath)
+ fs.rmdir(distPath, function() { /* swallow errors */ });
});
task('default',['clean'], function (params) {
- fs.mkdir(distPath,0755);
+ fs.mkdir(distPath,0755, function() { /* swallow errors */ });
- var options = JSON.parse(fs.readFileSync('plugin.json','utf8'))
+ var options = JSON.parse(fs.readFileSync('plugin.json','utf8', function() { /* swallow errors */ }))
options.Year=new Date().getFullYear()
- var template = Handlebars.compile(fs.readFileSync('templates/jquery.maskedinput.template','utf8'));
+ var template = Handlebars.compile(fs.readFileSync('templates/jquery.maskedinput.template','utf8', function() { /* swallow errors */ }));
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
+});
From 86435ffed97ea2e060f0fc8b4ae4a886a7b20ebe Mon Sep 17 00:00:00 2001
From: Jared Barboza
Date: Tue, 29 Oct 2013 00:10:59 -0400
Subject: [PATCH 08/87] 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 09/87] 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 10/87] 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 11/87] 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 12/87] 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 13/87] 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 14/87] 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 debc0d1878fca126c09acdaccedae20d95a507b6 Mon Sep 17 00:00:00 2001
From: Greg Burghardt
Date: Thu, 31 Oct 2013 09:00:07 -0400
Subject: [PATCH 15/87] Adding demo with optional markers and autoclear=false
---
demo/index.html | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/demo/index.html b/demo/index.html
index 68dfe10..8efda6a 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -16,7 +16,8 @@
$("#eyescript").mask("~9.99 ~9.99 999");
$("#po").mask("PO: aaa-999-***");
$("#pct").mask("99%");
- $("#phoneAutoclearFalse").mask("(999) 999-999-9999", { autoclear: false });
+ $("#phoneAutoclearFalse").mask("(999) 999-9999", { autoclear: false });
+ $("#phoneExtAutoclearFalse").mask("(999) 999-9999? x99999", { autoclear: false });
$("input").blur(function() {
$("#info").html("Unmasked value: " + $(this).mask());
@@ -39,7 +40,8 @@
| Eye Script | | ~9.99 ~9.99 999 |
| Purchase Order | | aaa-999-*** |
| Percent | | 99% |
- | Phone (autoclear=false) | | 99% |
+ | Phone (autoclear=false) | | (999) 999-9999 |
+ | Phone + Ext (autoclear=false) | | (999) 999-9999? x99999 |
From 2f518e6f37df7b1bde026b4fa4a284faee686905 Mon Sep 17 00:00:00 2001
From: Greg Burghardt
Date: Thu, 31 Oct 2013 09:01:19 -0400
Subject: [PATCH 16/87] Adding test coverage around masks with optional markers
and autoclear=false
---
spec/Focus.Spec.js | 48 +++++++++++++++++++++++++++
spec/Raw.Spec.js | 82 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 130 insertions(+)
diff --git a/spec/Focus.Spec.js b/spec/Focus.Spec.js
index 01ddebd..f469bf5 100644
--- a/spec/Focus.Spec.js
+++ b/spec/Focus.Spec.js
@@ -123,6 +123,18 @@ feature("Optional marker",function(){
});
});
+ scenario("Placeholders not filled to marker and autoclear = false", function() {
+ given("a mask with an optional marker",function(){
+ input.mask("99?99", { autoclear: false });
+ });
+ when("typing one character and leaving",function(){
+ input.mashKeys("1").blur();
+ });
+ then("value should be empty",function(){
+ expect(input).toHaveValue("1___");
+ });
+ });
+
scenario("Placeholders filled to marker",function(){
given("a mask with an optional marker",function(){
input.mask("99?99");
@@ -134,4 +146,40 @@ feature("Optional marker",function(){
expect(input).toHaveValue("12");
});
});
+
+ scenario("Placeholders filled to marker and autoclear = false", function() {
+ given("a mask with an optional marker",function(){
+ input.mask("99?99", { autoclear: false });
+ });
+ when("typing two characters and leaving",function(){
+ input.mashKeys("12").blur();
+ });
+ then("value should remain",function(){
+ expect(input).toHaveValue("12");
+ });
+ });
+
+ scenario("Placeholders filled, one marker filled, and autoclear = false", function() {
+ given("a mask with an optional marker",function(){
+ input.mask("99?99", { autoclear: false });
+ });
+ when("typing three characters and leaving",function(){
+ input.mashKeys("123").blur();
+ });
+ then("value should remain",function(){
+ expect(input).toHaveValue("123");
+ });
+ });
+
+ scenario("Placeholders and markers filled, and autoclear = false", function() {
+ given("a mask with an optional marker",function(){
+ input.mask("99?99", { autoclear: false });
+ });
+ when("typing four characters and leaving",function(){
+ input.mashKeys("1234").blur();
+ });
+ then("value should remain",function(){
+ expect(input).toHaveValue("1234");
+ });
+ });
});
diff --git a/spec/Raw.Spec.js b/spec/Raw.Spec.js
index 0516971..97be1f8 100644
--- a/spec/Raw.Spec.js
+++ b/spec/Raw.Spec.js
@@ -54,4 +54,86 @@ feature("Getting raw value",function(){
expect(input.mask()).toEqual("12");
});
});
+});
+
+feature("Getting raw value with autoclear set to false", function() {
+ scenario("After typing",function(){
+ given("an input with a mask containing a literal", function(){
+ input.mask("9/9", { autoclear: false });
+ });
+
+ when("typing all numbers",function(){
+ input.mashKeys("12");
+ });
+
+ then("raw value should be correct",function(){
+ expect(input.mask()).toEqual("12");
+ });
+ });
+
+ scenario("While typing",function(){
+ given("an input with a mask containing a literal", function(){
+ input.mask("9/9", { autoclear: false });
+ });
+
+ when("typing a number",function(){
+ input.mashKeys("1");
+ });
+
+ then("raw value should be correct",function(){
+ expect(input.mask()).toEqual("1");
+ });
+ });
+
+ scenario("Before typing",function(){
+ given("an input with a mask containing a literal", function(){
+ input.mask("9/9", { autoclear: false });
+ });
+
+ then("raw value should be correct",function(){
+ expect(input.mask()).toEqual("");
+ });
+ });
+
+ scenario("After typing partial input past an optional marker",function(){
+ given("an input with a mask containing a literal", function(){
+ input.mask("9?99", { autoclear: false });
+ });
+
+ when("typing a partial input",function(){
+ input.mashKeys("12");
+ });
+
+ then("raw value should be correct",function(){
+ expect(input.mask()).toEqual("12");
+ });
+ });
+
+ scenario("After typing partial input",function(){
+ given("an input with a mask containing a literal", function(){
+ input.mask("99?99", { autoclear: false });
+ });
+
+ when("typing a partial input",function(){
+ input.mashKeys("1");
+ });
+
+ then("raw value should be correct",function(){
+ expect(input.mask()).toEqual("1");
+ });
+ });
+
+ scenario("After typing partial input up to an optional marker",function(){
+ given("an input with a mask containing a literal", function(){
+ input.mask("9?99", { autoclear: false });
+ });
+
+ when("typing a partial input",function(){
+ input.mashKeys("1");
+ });
+
+ then("raw value should be correct",function(){
+ expect(input.mask()).toEqual("1");
+ });
+ });
});
\ No newline at end of file
From a4308eac7c3bffaeef6415cefec583b3230f5cae Mon Sep 17 00:00:00 2001
From: Greg Burghardt
Date: Thu, 31 Oct 2013 09:47:41 -0400
Subject: [PATCH 17/87] Rebuilding distribution files after merging from
upsteam/master.
---
dist/jquery.maskedinput.js | 22 ++++++++++++++++++++--
dist/jquery.maskedinput.min.js | 2 +-
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/dist/jquery.maskedinput.js b/dist/jquery.maskedinput.js
index 656174f..5c84271 100644
--- a/dist/jquery.maskedinput.js
+++ b/dist/jquery.maskedinput.js
@@ -15,6 +15,7 @@
var pasteEventName = getPasteEvent() + ".mask",
ua = navigator.userAgent,
iPhone = /iphone/i.test(ua),
+ chrome = /chrome/i.test(ua),
android=/android/i.test(ua),
caretTimeoutId;
@@ -205,6 +206,22 @@ $.fn.extend({
c,
next;
+ if (k == 0) {
+ // unable to detect key pressed. Grab it from pos and adjust
+ // this is a failsafe for mobile chrome
+ // which can't detect keypress events
+ // reliably
+ if (pos.begin >= len) {
+ input.val(input.val().substr(0, len));
+ e.preventDefault();
+ return false;
+ }
+ if (pos.begin == pos.end) {
+ k = input.val().charCodeAt(pos.begin - 1);
+ pos.begin--;
+ pos.end--;
+ }
+ }
if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
return;
} else if (k) {
@@ -342,11 +359,12 @@ $.fn.extend({
settings.completed.call(input);
}, 0);
});
-
+ if (chrome && android) {
+ input.bind("keyup.mask", keypressEvent);
+ }
checkVal(); //Perform initial check for existing values
});
}
});
-
})(jQuery);
\ No newline at end of file
diff --git a/dist/jquery.maskedinput.min.js b/dist/jquery.maskedinput.min.js
index 9c6056c..818d1c8 100644
--- a/dist/jquery.maskedinput.min.js
+++ b/dist/jquery.maskedinput.min.js
@@ -4,4 +4,4 @@
Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
Version: 1.3.1
*/
-!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),c=/android/i.test(r);e.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,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 o,l,u,s,f,h;return!t&&this.length>0?(o=e(this[0]),o.data(e.mask.dataName)()):(r=e.extend({autoclear:e.mask.autoclear,placeholder:e.mask.placeholder,completed:null},r),l=e.mask.definitions,u=[],s=h=t.length,f=null,e.each(t.split(""),function(e,t){"?"==t?(h--,s=e):l[t]?(u.push(new RegExp(l[t])),null===f&&(f=u.length-1)):u.push(null)}),this.trigger("unmask").each(function(){function o(e){for(;++e=0&&!u[e];);return e}function m(e,t){var n,a;if(!(0>e)){for(n=e,a=o(t);h>n;n++)if(u[n]){if(!(h>a&&u[n].test(R[a])))break;R[n]=R[a],R[a]=r.placeholder,a=o(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(u[t]){if(a=o(t),i=R[t],R[t]=n,!(h>a&&u[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=o(n-1),a=46===r?o(a):a),k(n,a),m(n,a-1),e.preventDefault()):27==r&&(x.val(A),x.caret(0,y()),e.preventDefault())}function v(t){var n,a,i,l=t.which,s=x.caret();t.ctrlKey||t.altKey||t.metaKey||32>l||l&&(0!==s.end-s.begin&&(k(s.begin,s.end),m(s.begin,s.end-1)),n=o(s.begin-1),h>n&&(a=String.fromCharCode(l),u[n].test(a)&&(p(n),R[n]=a,b(),i=o(n),c?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++)u[n]&&(R[n]=r.placeholder)}function b(){x.val(R.join(""))}function y(e){var t,n,a,i=x.val(),c=-1;for(t=0,a=0;h>t;t++)if(u[t]){for(R[t]=r.placeholder;a++i.length)break}else R[t]===i.charAt(a)&&t!==s&&(a++,c=t);return e?b():s>c+1?r.autoclear||R.join("")===S?(x.val(""),k(0,h)):b():(b(),x.val(x.val().substring(0,c+1))),s?t:f}var x=e(this),R=e.map(t.split(""),function(e){return"?"!=e?l[e]?r.placeholder:e:void 0}),S=R.join(""),A=x.val();x.data(e.mask.dataName,function(){return e.map(R,function(e,t){return u[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;A=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()!=A&&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(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),c=/chrome/i.test(r),o=/android/i.test(r);e.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,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 l,u,s,f,d,h;return!t&&this.length>0?(l=e(this[0]),l.data(e.mask.dataName)()):(r=e.extend({autoclear:e.mask.autoclear,placeholder:e.mask.placeholder,completed:null},r),u=e.mask.definitions,s=[],f=h=t.length,d=null,e.each(t.split(""),function(e,t){"?"==t?(h--,f=e):u[t]?(s.push(new RegExp(u[t])),null===d&&(d=s.length-1)):s.push(null)}),this.trigger("unmask").each(function(){function l(e){for(;++e=0&&!s[e];);return e}function p(e,t){var n,a;if(!(0>e)){for(n=e,a=l(t);h>n;n++)if(s[n]){if(!(h>a&&s[n].test(A[a])))break;A[n]=A[a],A[a]=r.placeholder,a=l(a)}y(),R.caret(Math.max(d,e))}}function g(e){var t,n,a,i;for(t=e,n=r.placeholder;h>t;t++)if(s[t]){if(a=l(t),i=A[t],A[t]=n,!(h>a&&s[a].test(i)))break;n=i}}function v(e){var t,n,a,r=e.which;8===r||46===r||i&&127===r?(t=R.caret(),n=t.begin,a=t.end,0===a-n&&(n=46!==r?m(n):a=l(n-1),a=46===r?l(a):a),k(n,a),p(n,a-1),e.preventDefault()):27==r&&(R.val(T),R.caret(0,x()),e.preventDefault())}function b(t){var n,a,i,c=t.which,u=R.caret();if(0==c){if(u.begin>=h)return R.val(R.val().substr(0,h)),t.preventDefault(),!1;u.begin==u.end&&(c=R.val().charCodeAt(u.begin-1),u.begin--,u.end--)}t.ctrlKey||t.altKey||t.metaKey||32>c||c&&(0!==u.end-u.begin&&(k(u.begin,u.end),p(u.begin,u.end-1)),n=l(u.begin-1),h>n&&(a=String.fromCharCode(c),s[n].test(a)&&(g(n),A[n]=a,y(),i=l(n),o?setTimeout(e.proxy(e.fn.caret,R,i),0):R.caret(i),r.completed&&i>=h&&r.completed.call(R))),t.preventDefault())}function k(e,t){var n;for(n=e;t>n&&h>n;n++)s[n]&&(A[n]=r.placeholder)}function y(){R.val(A.join(""))}function x(e){var t,n,a,i=R.val(),c=-1;for(t=0,a=0;h>t;t++)if(s[t]){for(A[t]=r.placeholder;a++i.length)break}else A[t]===i.charAt(a)&&t!==f&&(a++,c=t);return e?y():f>c+1?r.autoclear||A.join("")===S?(R.val(""),k(0,h)):y():(y(),R.val(R.val().substring(0,c+1))),f?t:d}var R=e(this),A=e.map(t.split(""),function(e){return"?"!=e?u[e]?r.placeholder:e:void 0}),S=A.join(""),T=R.val();R.data(e.mask.dataName,function(){return e.map(A,function(e,t){return s[t]&&e!=r.placeholder?e:null}).join("")}),R.attr("readonly")||R.one("unmask",function(){R.unbind(".mask").removeData(e.mask.dataName)}).bind("focus.mask",function(){clearTimeout(n);var e;T=R.val(),e=x(),n=setTimeout(function(){y(),e==t.length?R.caret(0,e):R.caret(e)},10)}).bind("blur.mask",function(){x(),R.val()!=T&&R.change()}).bind("keydown.mask",v).bind("keypress.mask",b).bind(a,function(){setTimeout(function(){var e=x(!0);R.caret(e),r.completed&&e==R.val().length&&r.completed.call(R)},0)}),c&&o&&R.bind("keyup.mask",b),x()}))}})}(jQuery);
\ No newline at end of file
From 8250c1d12982ecd5d1f173a847c9b538221b2487 Mon Sep 17 00:00:00 2001
From: Jared Barboza
Date: Thu, 31 Oct 2013 22:03:57 -0400
Subject: [PATCH 18/87] 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 19/87] 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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-