ソースを参照

In valid Leap Year dates can be entered fix #1368 fix #1389

Robin Herbots 9 年 前
コミット
a3a2a3bff6

+ 1 - 0
CHANGELOG.md

@@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file.
 - improve inputfallback (Android support)
 
 ### Fixed
+- In valid Leap Year dates can be entered #1368
 - jquery.val returns empty value (when using an unsupported input type) #1415
 - Losing the decimal part when the maximum number of digits is reached #1257
 - Not allowing to change existing number to 0 #1381

+ 1 - 1
bower.json

@@ -1,6 +1,6 @@
 {
   "name": "jquery.inputmask",
-  "version": "3.3.4-60",
+  "version": "3.3.4-64",
   "main": [
 	  "./dist/inputmask/inputmask.loader.js"
   ],

+ 1 - 1
component.json

@@ -2,7 +2,7 @@
   "name": "jquery_inputmask",
   "repository": "robinherbots/jquery.inputmask",
   "description": "jquery.inputmask is a jquery plugin which create an input mask.",
-  "version": "3.3.4-60",
+  "version": "3.3.4-64",
   "keywords": ["jquery", "plugins", "input", "form", "inputmask", "mask"],
   "main": "./dist/inputmask/inputmask.loader.js",
   "scripts": [

+ 1 - 1
composer.json

@@ -1,7 +1,7 @@
 {
   "name": "robinherbots/jquery.inputmask",
   "description": "jquery.inputmask is a jquery plugin which create an input mask.",
-  "version": "3.3.4-60",
+  "version": "3.3.4-64",
   "type": "library",
   "keywords": ["jquery", "plugins", "input", "form", "inputmask", "mask"],
   "homepage": "http://robinherbots.github.io/jquery.inputmask",

+ 15 - 26
dist/inputmask/inputmask.date.extensions.js

@@ -3,11 +3,14 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function(factory) {
     "function" == typeof define && define.amd ? define([ "inputmask.dependencyLib", "inputmask" ], factory) : "object" == typeof exports ? module.exports = factory(require("./inputmask.dependencyLib"), require("./inputmask")) : factory(window.dependencyLib || jQuery, window.Inputmask);
 }(function($, Inputmask) {
+    function isLeapYear(year) {
+        return isNaN(year) || 29 === new Date(year, 2, 0).getDate();
+    }
     return Inputmask.extendDefinitions({
         h: {
             validator: "[01][0-9]|2[0-3]",
@@ -112,6 +115,11 @@
                 }
                 return buffer.join("").substr(start, length);
             },
+            postValidation: function(buffer, currentResult, opts) {
+                var dayMonthValue, year, bufferStr = buffer.join("");
+                return 0 === opts.mask.indexOf("y") ? (year = bufferStr.substr(0, 4), dayMonthValue = bufferStr.substr(4, 11)) : (year = bufferStr.substr(6, 11), 
+                dayMonthValue = bufferStr.substr(0, 6)), currentResult && (dayMonthValue !== opts.leapday || isLeapYear(year));
+            },
             definitions: {
                 "1": {
                     validator: function(chrs, maskset, pos, strict, opts) {
@@ -153,7 +161,7 @@
                         var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
                         frontValue.indexOf(opts.placeholder[0]) !== -1 && (frontValue = "01" + opts.separator);
                         var isValid = opts.regex.val2(opts.separator).test(frontValue + chrs);
-                        if (!strict && !isValid && (chrs.charAt(1) === opts.separator || "-./".indexOf(chrs.charAt(1)) !== -1) && (isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0)))) return maskset.buffer[pos - 1] = "0", 
+                        return strict || isValid || chrs.charAt(1) !== opts.separator && "-./".indexOf(chrs.charAt(1)) === -1 || !(isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0))) ? isValid : (maskset.buffer[pos - 1] = "0", 
                         {
                             refreshFromBuffer: {
                                 start: pos - 1,
@@ -161,14 +169,7 @@
                             },
                             pos: pos,
                             c: chrs.charAt(0)
-                        };
-                        if (opts.mask.indexOf("2") === opts.mask.length - 1 && isValid) {
-                            var dayMonthValue = maskset.buffer.join("").substr(4, 4) + chrs;
-                            if (dayMonthValue !== opts.leapday) return !0;
-                            var year = parseInt(maskset.buffer.join("").substr(0, 4), 10);
-                            return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
-                        }
-                        return isValid;
+                        });
                     },
                     cardinality: 2,
                     prevalidator: [ {
@@ -187,13 +188,7 @@
                 },
                 y: {
                     validator: function(chrs, maskset, pos, strict, opts) {
-                        if (opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
-                            var dayMonthValue = maskset.buffer.join("").substr(0, 6);
-                            if (dayMonthValue !== opts.leapday) return !0;
-                            var year = parseInt(chrs, 10);
-                            return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
-                        }
-                        return !1;
+                        return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
                     },
                     cardinality: 4,
                     prevalidator: [ {
@@ -224,15 +219,9 @@
                                     pos: pos
                                 };
                                 if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2), 
-                                opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
-                                    var dayMonthValue = maskset.buffer.join("").substr(0, 6);
-                                    if (dayMonthValue !== opts.leapday) isValid = !0; else {
-                                        var year = parseInt(chrs, 10);
-                                        isValid = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
-                                    }
-                                } else isValid = !1;
-                                if (isValid) return maskset.buffer[pos - 1] = yearPrefix.charAt(0), maskset.buffer[pos++] = yearPrefix.charAt(1), 
-                                maskset.buffer[pos++] = chrs.charAt(0), {
+                                isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos - 1] = yearPrefix.charAt(0), 
+                                maskset.buffer[pos++] = yearPrefix.charAt(1), maskset.buffer[pos++] = chrs.charAt(0), 
+                                {
                                     refreshFromBuffer: {
                                         start: pos - 3,
                                         end: pos

+ 1 - 1
dist/inputmask/inputmask.dependencyLib.js

@@ -3,7 +3,7 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function(factory) {
     "function" == typeof define && define.amd ? define("inputmask.dependencyLib", [ "jquery" ], factory) : "object" == typeof exports ? module.exports = factory(require("jquery")) : factory(jQuery);

+ 1 - 1
dist/inputmask/inputmask.extensions.js

@@ -3,7 +3,7 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function(factory) {
     "function" == typeof define && define.amd ? define([ "inputmask.dependencyLib", "inputmask" ], factory) : "object" == typeof exports ? module.exports = factory(require("./inputmask.dependencyLib"), require("./inputmask")) : factory(window.dependencyLib || jQuery, window.Inputmask);

+ 1 - 1
dist/inputmask/inputmask.js

@@ -3,7 +3,7 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function(factory) {
     "function" == typeof define && define.amd ? define("inputmask", [ "inputmask.dependencyLib" ], factory) : "object" == typeof exports ? module.exports = factory(require("./inputmask.dependencyLib")) : factory(window.dependencyLib || jQuery);

ファイルの差分が大きいため隠しています
+ 1 - 1
dist/inputmask/inputmask.loader.js


+ 1 - 1
dist/inputmask/inputmask.numeric.extensions.js

@@ -3,7 +3,7 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function(factory) {
     "function" == typeof define && define.amd ? define([ "inputmask.dependencyLib", "inputmask" ], factory) : "object" == typeof exports ? module.exports = factory(require("./inputmask.dependencyLib"), require("./inputmask")) : factory(window.dependencyLib || jQuery, window.Inputmask);

+ 6 - 2
dist/inputmask/inputmask.phone.extensions.js

@@ -3,12 +3,16 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function(factory) {
     "function" == typeof define && define.amd ? define([ "inputmask.dependencyLib", "inputmask" ], factory) : "object" == typeof exports ? module.exports = factory(require("./inputmask.dependencyLib"), require("./inputmask")) : factory(window.dependencyLib || jQuery, window.Inputmask);
 }(function($, Inputmask) {
-    return Inputmask.extendAliases({
+    var analyseMaskBase = Inputmask.analyseMask;
+    return Inputmask.analyseMask = function(mask, opts) {
+        var mt = analyseMaskBase.call(this, mask, opts);
+        return mt;
+    }, Inputmask.extendAliases({
         abstractphone: {
             countrycode: "",
             phoneCodes: [],

+ 1 - 1
dist/inputmask/inputmask.regex.extensions.js

@@ -3,7 +3,7 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function(factory) {
     "function" == typeof define && define.amd ? define([ "inputmask.dependencyLib", "inputmask" ], factory) : "object" == typeof exports ? module.exports = factory(require("./inputmask.dependencyLib"), require("./inputmask")) : factory(window.dependencyLib || jQuery, window.Inputmask);

+ 1 - 1
dist/inputmask/jquery.inputmask.js

@@ -3,7 +3,7 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function(factory) {
     "function" == typeof define && define.amd ? define([ "jquery", "inputmask" ], factory) : "object" == typeof exports ? module.exports = factory(require("jquery"), require("./inputmask")) : factory(jQuery, window.Inputmask);

+ 20 - 27
dist/jquery.inputmask.bundle.js

@@ -3,7 +3,7 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function($) {
     function Inputmask(alias, options) {
@@ -1606,6 +1606,9 @@
         }
     }), $.fn.inputmask;
 }(jQuery, Inputmask), function($, Inputmask) {
+    function isLeapYear(year) {
+        return isNaN(year) || 29 === new Date(year, 2, 0).getDate();
+    }
     return Inputmask.extendDefinitions({
         h: {
             validator: "[01][0-9]|2[0-3]",
@@ -1710,6 +1713,11 @@
                 }
                 return buffer.join("").substr(start, length);
             },
+            postValidation: function(buffer, currentResult, opts) {
+                var dayMonthValue, year, bufferStr = buffer.join("");
+                return 0 === opts.mask.indexOf("y") ? (year = bufferStr.substr(0, 4), dayMonthValue = bufferStr.substr(4, 11)) : (year = bufferStr.substr(6, 11), 
+                dayMonthValue = bufferStr.substr(0, 6)), currentResult && (dayMonthValue !== opts.leapday || isLeapYear(year));
+            },
             definitions: {
                 "1": {
                     validator: function(chrs, maskset, pos, strict, opts) {
@@ -1751,7 +1759,7 @@
                         var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
                         frontValue.indexOf(opts.placeholder[0]) !== -1 && (frontValue = "01" + opts.separator);
                         var isValid = opts.regex.val2(opts.separator).test(frontValue + chrs);
-                        if (!strict && !isValid && (chrs.charAt(1) === opts.separator || "-./".indexOf(chrs.charAt(1)) !== -1) && (isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0)))) return maskset.buffer[pos - 1] = "0", 
+                        return strict || isValid || chrs.charAt(1) !== opts.separator && "-./".indexOf(chrs.charAt(1)) === -1 || !(isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0))) ? isValid : (maskset.buffer[pos - 1] = "0", 
                         {
                             refreshFromBuffer: {
                                 start: pos - 1,
@@ -1759,14 +1767,7 @@
                             },
                             pos: pos,
                             c: chrs.charAt(0)
-                        };
-                        if (opts.mask.indexOf("2") === opts.mask.length - 1 && isValid) {
-                            var dayMonthValue = maskset.buffer.join("").substr(4, 4) + chrs;
-                            if (dayMonthValue !== opts.leapday) return !0;
-                            var year = parseInt(maskset.buffer.join("").substr(0, 4), 10);
-                            return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
-                        }
-                        return isValid;
+                        });
                     },
                     cardinality: 2,
                     prevalidator: [ {
@@ -1785,13 +1786,7 @@
                 },
                 y: {
                     validator: function(chrs, maskset, pos, strict, opts) {
-                        if (opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
-                            var dayMonthValue = maskset.buffer.join("").substr(0, 6);
-                            if (dayMonthValue !== opts.leapday) return !0;
-                            var year = parseInt(chrs, 10);
-                            return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
-                        }
-                        return !1;
+                        return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
                     },
                     cardinality: 4,
                     prevalidator: [ {
@@ -1822,15 +1817,9 @@
                                     pos: pos
                                 };
                                 if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2), 
-                                opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
-                                    var dayMonthValue = maskset.buffer.join("").substr(0, 6);
-                                    if (dayMonthValue !== opts.leapday) isValid = !0; else {
-                                        var year = parseInt(chrs, 10);
-                                        isValid = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
-                                    }
-                                } else isValid = !1;
-                                if (isValid) return maskset.buffer[pos - 1] = yearPrefix.charAt(0), maskset.buffer[pos++] = yearPrefix.charAt(1), 
-                                maskset.buffer[pos++] = chrs.charAt(0), {
+                                isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos - 1] = yearPrefix.charAt(0), 
+                                maskset.buffer[pos++] = yearPrefix.charAt(1), maskset.buffer[pos++] = chrs.charAt(0), 
+                                {
                                     refreshFromBuffer: {
                                         start: pos - 3,
                                         end: pos
@@ -2585,7 +2574,11 @@
         }
     }), Inputmask;
 }(jQuery, Inputmask), function($, Inputmask) {
-    return Inputmask.extendAliases({
+    var analyseMaskBase = Inputmask.analyseMask;
+    return Inputmask.analyseMask = function(mask, opts) {
+        var mt = analyseMaskBase.call(this, mask, opts);
+        return mt;
+    }, Inputmask.extendAliases({
         abstractphone: {
             countrycode: "",
             phoneCodes: [],

ファイルの差分が大きいため隠しています
+ 2 - 2
dist/min/inputmask/inputmask.date.extensions.min.js


+ 1 - 1
dist/min/inputmask/inputmask.dependencyLib.min.js

@@ -3,6 +3,6 @@
 * https://github.com/RobinHerbots/jquery.inputmask
 * Copyright (c) 2010 - 2016 Robin Herbots
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-* Version: 3.3.4-60
+* Version: 3.3.4-64
 */
 !function(a){"function"==typeof define&&define.amd?define("inputmask.dependencyLib",["jquery"],a):"object"==typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){return window.dependencyLib=a,a});

ファイルの差分が大きいため隠しています
+ 1 - 1
dist/min/inputmask/inputmask.extensions.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/min/inputmask/inputmask.loader.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/min/inputmask/inputmask.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/min/inputmask/inputmask.numeric.extensions.min.js


ファイルの差分が大きいため隠しています
+ 2 - 2
dist/min/inputmask/inputmask.phone.extensions.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/min/inputmask/inputmask.regex.extensions.min.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/min/inputmask/jquery.inputmask.min.js


ファイルの差分が大きいため隠しています
+ 3 - 3
dist/min/jquery.inputmask.bundle.min.js


+ 84 - 82
js/inputmask.date.extensions.js

@@ -17,6 +17,10 @@
 	}
 }
 (function ($, Inputmask) {
+	function isLeapYear(year) {
+		return isNaN(year) || new Date(year, 2, 0).getDate() === 29;
+	}
+
 	//date & time aliases
 	Inputmask.extendDefinitions({
 		"h": { //hours
@@ -138,6 +142,18 @@
 				}
 				return buffer.join("").substr(start, length);
 			},
+			postValidation: function (buffer, currentResult, opts) {
+				var dayMonthValue, year, bufferStr = buffer.join("");
+				if (opts.mask.indexOf("y") === 0) {
+					year = bufferStr.substr(0, 4);
+					dayMonthValue = bufferStr.substr(4, 11);
+				} else {
+					year = bufferStr.substr(6, 11);
+					dayMonthValue = bufferStr.substr(0, 6);
+				}
+
+				return currentResult && (dayMonthValue !== opts.leapday ? true : isLeapYear(year));
+			},
 			definitions: {
 				"1": { //val1 ~ day or month
 					validator: function (chrs, maskset, pos, strict, opts) {
@@ -212,27 +228,6 @@
 							}
 						}
 
-						//check leap yeap
-						if ((opts.mask.indexOf("2") === opts.mask.length - 1) && isValid) {
-							var dayMonthValue = maskset.buffer.join("").substr(4, 4) + chrs;
-							if (dayMonthValue !== opts.leapday) {
-								return true;
-							} else {
-								var year = parseInt(maskset.buffer.join("").substr(0, 4), 10); //detect leap year
-								if (year % 4 === 0) {
-									if (year % 100 === 0) {
-										if (year % 400 === 0) {
-											return true;
-										} else {
-											return false;
-										}
-									} else {
-										return true;
-									}
-								} else return false;
-							}
-						}
-
 						return isValid;
 					},
 					cardinality: 2,
@@ -259,20 +254,7 @@
 				},
 				"y": { //year
 					validator: function (chrs, maskset, pos, strict, opts) {
-						if (opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
-							var dayMonthValue = maskset.buffer.join("").substr(0, 6);
-							if (dayMonthValue !== opts.leapday) {
-								return true;
-							} else {
-								var year = parseInt(chrs, 10); //detect leap year
-								if (year % 4 === 0) {
-									if (year % 100 === 0) {
-										if (year % 400 === 0) return true;
-										else return false;
-									} else return true;
-								} else return false;
-							}
-						} else return false;
+						return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
 					},
 					cardinality: 4,
 					prevalidator: [{
@@ -317,20 +299,7 @@
 								}
 
 								yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2);
-								if (opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
-									var dayMonthValue = maskset.buffer.join("").substr(0, 6);
-									if (dayMonthValue !== opts.leapday) {
-										isValid = true;
-									} else {
-										var year = parseInt(chrs, 10); //detect leap year
-										if (year % 4 === 0) {
-											if (year % 100 === 0) {
-												if (year % 400 === 0) isValid = true;
-												else isValid = false;
-											} else isValid = true;
-										} else isValid = false;
-									}
-								} else isValid = false;
+								isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
 								if (isValid) {
 									maskset.buffer[pos - 1] = yearPrefix.charAt(0);
 									maskset.buffer[pos++] = yearPrefix.charAt(1);
@@ -365,14 +334,17 @@
 				val2pre: function (separator) {
 					var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
 					return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
-				}, //daypre
+				}
+				, //daypre
 				val2: function (separator) {
 					var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
 					return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
-				}, //day
+				}
+				, //day
 				val1pre: new RegExp("[01]"), //monthpre
 				val1: new RegExp("0[1-9]|1[012]") //month
-			},
+			}
+			,
 			leapday: "02/29/",
 			onKeyDown: function (e, buffer, caretPos, opts) {
 				var $input = $(this);
@@ -382,7 +354,8 @@
 					$input.trigger("setvalue");
 				}
 			}
-		},
+		}
+		,
 		"yyyy/mm/dd": {
 			mask: "y/1/2",
 			placeholder: "yyyy/mm/dd",
@@ -396,49 +369,56 @@
 					$input.trigger("setvalue");
 				}
 			}
-		},
+		}
+		,
 		"dd.mm.yyyy": {
 			mask: "1.2.y",
 			placeholder: "dd.mm.yyyy",
 			leapday: "29.02.",
 			separator: ".",
 			alias: "dd/mm/yyyy"
-		},
+		}
+		,
 		"dd-mm-yyyy": {
 			mask: "1-2-y",
 			placeholder: "dd-mm-yyyy",
 			leapday: "29-02-",
 			separator: "-",
 			alias: "dd/mm/yyyy"
-		},
+		}
+		,
 		"mm.dd.yyyy": {
 			mask: "1.2.y",
 			placeholder: "mm.dd.yyyy",
 			leapday: "02.29.",
 			separator: ".",
 			alias: "mm/dd/yyyy"
-		},
+		}
+		,
 		"mm-dd-yyyy": {
 			mask: "1-2-y",
 			placeholder: "mm-dd-yyyy",
 			leapday: "02-29-",
 			separator: "-",
 			alias: "mm/dd/yyyy"
-		},
+		}
+		,
 		"yyyy.mm.dd": {
 			mask: "y.1.2",
 			placeholder: "yyyy.mm.dd",
 			leapday: ".02.29",
 			separator: ".",
 			alias: "yyyy/mm/dd"
-		},
+		}
+		,
 		"yyyy-mm-dd": {
 			mask: "y-1-2",
 			placeholder: "yyyy-mm-dd",
 			leapday: "-02-29",
 			separator: "-",
 			alias: "yyyy/mm/dd"
-		},
+		}
+		,
 		"datetime": {
 			mask: "1/2/y h:s",
 			placeholder: "dd/mm/yyyy hh:mm",
@@ -450,7 +430,8 @@
 				ampm: new RegExp("^[a|p|A|P][m|M]"),
 				mspre: new RegExp("[0-5]"), //minutes/seconds pre
 				ms: new RegExp("[0-5][0-9]")
-			},
+			}
+			,
 			timeseparator: ":",
 			hourFormat: "24", // or 12
 			definitions: {
@@ -522,7 +503,8 @@
 						}
 
 						return isValid;
-					},
+					}
+					,
 					cardinality: 2,
 					prevalidator: [{
 						validator: function (chrs, maskset, pos, strict, opts) {
@@ -541,7 +523,8 @@
 						},
 						cardinality: 1
 					}]
-				},
+				}
+				,
 				"s": { //seconds || minutes
 					validator: "[0-5][0-9]",
 					cardinality: 2,
@@ -562,24 +545,29 @@
 						},
 						cardinality: 1
 					}]
-				},
+				}
+				,
 				"t": { //am/pm
 					validator: function (chrs, maskset, pos, strict, opts) {
 						return opts.regex.ampm.test(chrs + "m");
-					},
+					}
+					,
 					casing: "lower",
 					cardinality: 1
 				}
-			},
+			}
+			,
 			insertMode: false,
 			autoUnmask: false
-		},
+		}
+		,
 		"datetime12": {
 			mask: "1/2/y h:s t\\m",
 			placeholder: "dd/mm/yyyy hh:mm xm",
 			alias: "datetime",
 			hourFormat: "12"
-		},
+		}
+		,
 		"mm/dd/yyyy hh:mm xm": {
 			mask: "1/2/y h:s t\\m",
 			placeholder: "mm/dd/yyyy hh:mm xm",
@@ -588,14 +576,17 @@
 				val2pre: function (separator) {
 					var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
 					return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
-				},
+				}
+				,
 				val2: function (separator) {
 					var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
 					return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
-				},
+				}
+				,
 				val1pre: new RegExp("[01]"),
 				val1: new RegExp("0[1-9]|1[012]")
-			},
+			}
+			,
 			leapday: "02/29/",
 			onKeyDown: function (e, buffer, caretPos, opts) {
 				var $input = $(this);
@@ -605,58 +596,69 @@
 					$input.trigger("setvalue");
 				}
 			}
-		},
+		}
+		,
 		"hh:mm t": {
 			mask: "h:s t\\m",
 			placeholder: "hh:mm xm",
 			alias: "datetime",
 			hourFormat: "12"
-		},
+		}
+		,
 		"h:s t": {
 			mask: "h:s t\\m",
 			placeholder: "hh:mm xm",
 			alias: "datetime",
 			hourFormat: "12"
-		},
+		}
+		,
 		"hh:mm:ss": {
 			mask: "h:s:s",
 			placeholder: "hh:mm:ss",
 			alias: "datetime",
 			autoUnmask: false
-		},
+		}
+		,
 		"hh:mm": {
 			mask: "h:s",
 			placeholder: "hh:mm",
 			alias: "datetime",
 			autoUnmask: false
-		},
+		}
+		,
 		"date": {
 			alias: "dd/mm/yyyy" // "mm/dd/yyyy"
-		},
+		}
+		,
 		"mm/yyyy": {
 			mask: "1/y",
 			placeholder: "mm/yyyy",
 			leapday: "donotuse",
 			separator: "/",
 			alias: "mm/dd/yyyy"
-		},
+		}
+		,
 		"shamsi": {
 			regex: {
 				val2pre: function (separator) {
 					var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
 					return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "[0-3])");
-				},
+				}
+				,
 				val2: function (separator) {
 					var escapedSeparator = Inputmask.escapeRegex.call(this, separator);
 					return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[1-9]|1[012])" + escapedSeparator + "30)|((0[1-6])" + escapedSeparator + "31)");
-				},
+				}
+				,
 				val1pre: new RegExp("[01]"),
 				val1: new RegExp("0[1-9]|1[012]")
-			},
+			}
+			,
 			yearrange: {
 				minyear: 1300,
 				maxyear: 1499
-			},
+			}
+			,
 			mask: "y/1/2",
 			leapday: "/12/30",
 			placeholder: "yyyy/mm/dd",

+ 1 - 1
js/inputmask.js

@@ -552,7 +552,7 @@
 		if (opts.numericInput) {
 			reverseTokens(maskTokens[0]);
 		}
-		//console.log(JSON.stringify(maskTokens));
+		// console.log(JSON.stringify(maskTokens));
 		return maskTokens;
 	};
 

+ 74 - 22
js/inputmask.phone.extensions.js

@@ -18,35 +18,88 @@
 	}
 }
 (function ($, Inputmask) {
-	Inputmask.extendAliases({
-		"abstractphone": {
-			countrycode: "",
-			phoneCodes: [],
-			mask: function (opts) {
-				function consolidate() {
-					opts.regions = {
-						base: []
-					};
+	var analyseMaskBase = Inputmask.analyseMask;
 
-					//split up in regions
-					$.each(opts.phoneCodes, function (ndx, phoneCode) {
-						var region = phoneCode.region;
-						if (region === undefined)
-							opts.regions.base.push(phoneCode);
-						else {
-							if (opts.regions[region] === undefined) {
-								opts.regions[region] = [];
-								opts.regions.base.push(phoneCode);
-								opts.regions[region].push(phoneCode);
+	function MaskToken(isGroup, isOptional, isQuantifier, isAlternator) {
+		this.matches = [];
+		this.isGroup = isGroup || false;
+		this.isOptional = isOptional || false;
+		this.isQuantifier = isQuantifier || false;
+		this.isAlternator = isAlternator || false;
+		this.quantifier = {
+			min: 1,
+			max: 1
+		};
+	}
+
+	Inputmask.analyseMask = function (mask, opts) {
+		function consolidateAlternateTokens(matches) {
+			var consolidatedTokens = [];
+			$.each(matches, function (ndx, maskToken) {
+				if (maskToken.isAlternator) {
+					var cleanupNdx = [];
+					$.each(maskToken.matches, function (ndx, childToken) {
+						if (childToken && childToken.matches) {
+							if (childToken.matches.length > 0) {
+								if (consolidatedTokens[childToken.matches[0].nativeDef] === undefined && childToken.matches && !childToken.isGroup && !childToken.isOptional && !childToken.isQuantifier && !childToken.isAlternator) {
+									consolidatedTokens[childToken.matches[0].nativeDef] = new MaskToken(false, false, false, true);
+									var alternateToken = consolidatedTokens[childToken.matches[0].nativeDef];
+									var token = new MaskToken();
+									token.matches = childToken.matches.slice(1);
+									alternateToken.matches.push(token);
+									childToken.matches.splice(1, token.matches.length, alternateToken);
+								}
+								else {
+									cleanupNdx.push(ndx);
+									var alternateToken = consolidatedTokens[childToken.matches[0].nativeDef];
+									var token = new MaskToken();
+									token.matches = childToken.matches.slice(1);
+									alternateToken.matches.push(token);
+								}
 							} else {
-								opts.regions[region].push(phoneCode);
+								maskToken.matches.splice(ndx, 1);
 							}
 						}
 					});
+					maskToken.matches = $.map(maskToken.matches, function (match, ndx) {
+						if (cleanupNdx.indexOf(ndx) === -1) return match;
+					});
+				}
+				if (maskToken.matches) {
+					if (maskToken.matches.length === 1) //remove unnecessary nesting
+						matches[ndx] = maskToken.matches[0];
+					else if (maskToken.matches.length > 1) {
+						var prevMatch;
+						$.each(maskToken.matches, function (ndx, match) {
+							if (prevMatch) {
+
+							} else prevMatch = match;
+						});
+					}
+				}
+				if (matches[ndx].matches) {
+					consolidateAlternateTokens(matches[ndx].matches);
 				}
+			});
+		}
 
+		var mt = analyseMaskBase.call(this, mask, opts);
+		if (false && opts.phoneCodes) {
+			console.time("Optimizing...");
+			consolidateAlternateTokens(mt[0].matches);
+			if (mt[0].matches && mt[0].matches.length === 1) //remove unnecessary nesting
+				mt[0] = mt[0].matches[0];
+			console.timeEnd("Optimizing...");
+			console.log(JSON.stringify(mt));
+		}
+		return mt;
+	};
+	Inputmask.extendAliases({
+		"abstractphone": {
+			countrycode: "",
+			phoneCodes: [],
+			mask: function (opts) {
 				opts.definitions = {"#": opts.definitions["9"]};
-				// consolidate();
 				//do some sorting
 				var masks = opts.phoneCodes.sort(function (a, b) {
 					var maska = (a.mask || a).replace(/#/g, "9").replace(/[\)]/, "9").replace(/[\+\(\)#-]/g, ""),
@@ -56,7 +109,6 @@
 
 					return maskbs.indexOf(maskas) === 0 ? -1 : (maskas.indexOf(maskbs) === 0 ? 1 : maska.localeCompare(maskb));
 				});
-				// console.log(JSON.stringify(masks));
 				return masks;
 			},
 			keepStatic: true,

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "jquery.inputmask",
-  "version": "3.3.4-60",
+  "version": "3.3.4-64",
   "description": "jquery.inputmask is a jquery plugin which create an input mask.",
   "main": "./dist/inputmask/inputmask.loader.js",
   "files": [

+ 1 - 1
qunit/tests_phoneru.js

@@ -39,7 +39,7 @@ define([
 					input = expected;
 					//input = input.replace(/\+/g, "");
 					input = input.replace(/\(/g, "");
-					input = input.replace(/\)/g, "");
+					// input = input.replace(/\)/g, "");
 					input = input.replace(/-/g, "");
 
 					$(testmask).val(input);