ソースを参照

add androidHack

Robin Herbots 9 年 前
コミット
598edd4051

+ 1 - 0
README.md

@@ -27,6 +27,7 @@ Highlights:
 - value formatting / validating without input element
 - AMD/CommonJS support
 - dependencyLibs: vanilla javascript, jQuery, jqlite
+- [Android support](README_android.md)
 
 Demo page see [http://robinherbots.github.io/Inputmask](http://robinherbots.github.io/Inputmask)
 

+ 46 - 0
README_android.md

@@ -0,0 +1,46 @@
+#Android support
+
+Have a read thought the different android issues. (Android Information #465)
+
+Bottomline, the problem is the predictive text functionality.  There is no way to prevent or control the input, which gives undesired results
+and side effects in the inputmask.  I tried several ways multiple times.  Compositionevents, inputevent only masking, all with partial success.
+The behavior also changes with the keyboard used. (google keyboard, samsung keyboard, ...)
+
+In general, masks which only accepts numeric input tend to work even with predictive text enabled.  Inputmasks with alphanumeric input will all fail.
+
+The solution would be a way to control (or hint) the predictive text or to disable it.
+When browsers would implement the inputmode attribute, disabling will be possible.
+[Inputmode html spec](https://html.spec.whatwg.org/multipage/forms.html#input-modalities:-the-inputmode-attribute)
+[Inputmode chromestatus](https://www.chromestatus.com/feature/6225984592281600)
+
+##The workaround, the patchwork, the bad and ugly ;-)
+
+This is not enabled by default, because I find that the developer should be aware of what it does and what you need to take into account when using this hack.
+
+What it does.
+- changes the input type to password => disabled predictive text
+- enables the colorMask option which creates a div which is positioned above the input.
+So we type in the hidden password input and render the mask in the created div.
+Be aware that by changing the type to password that all css you targeted for type=text will not be applied anymore.
+You will need to adapt your css for it.  It is possible that the div is not well positioned.  If so, open an issue for it with a jsfiddle.
+
+To enable the workaround add the androidHack option to your individual masks or globally by setting defaults.
+You should set the option to "rtfm".
+
+```
+Inputmask("myfancymask", {androidHack: "rtfm"}).mask(selector);
+
+Inputmask.extendDefaults({ androidHack: "rtfm" });
+```
+
+##Reporting android related issues
+
+Before you submit an issue related to Android.  Test the issue with and without predictive text enabled.
+
+If the issue also occurs with predictive text disabled you may create an issue for it on Github.
+Otherwise, retry the issue on a desktop browser and add the colorMask: true option.
+If the problem is still there you may submit an issue.
+
+Always include a jsfiddle or alike to ease reproducing the problem.
+
+When the issue only occurs due to predictive text I cannot solve it, until browsers start implementing the inputmode attribute on inputs.

+ 1 - 1
bower.json

@@ -1,6 +1,6 @@
 {
   "name": "jquery.inputmask",
-  "version": "3.3.4-37",
+  "version": "3.3.4-38",
   "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-37",
+  "version": "3.3.4-38",
   "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-37",
+  "version": "3.3.4-38",
   "type": "library",
   "keywords": ["jquery", "plugins", "input", "form", "inputmask", "mask"],
   "homepage": "http://robinherbots.github.io/jquery.inputmask",

+ 1 - 1
dist/inputmask/inputmask.date.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-37
+* Version: 3.3.4-38
 */
 !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.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-37
+* Version: 3.3.4-38
 */
 !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-37
+* Version: 3.3.4-38
 */
 !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);

+ 11 - 7
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-37
+* Version: 3.3.4-38
 */
 !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);
@@ -1168,13 +1168,15 @@
                 colorMask.style.lineHeight = colorMask.style.height, colorMask.style.border = "";
             }
             var offset = $(input).position(), computedStyle = (input.ownerDocument.defaultView || window).getComputedStyle(input, null), parentNode = input.parentNode;
-            colorMask = document.createElement("div");
+            colorMask = document.createElement("div"), document.body.appendChild(colorMask);
             for (var style in computedStyle) colorMask.style[style] = computedStyle[style];
-            position(), parentNode.insertBefore(colorMask, input.nextSibling), $(window).on("resize", function(e) {
+            position(), $(window).on("resize", function(e) {
                 offset = $(input).position(), computedStyle = (input.ownerDocument.defaultView || window).getComputedStyle(input, null), 
                 position();
-            }), EventRuler.off(input, "mouseenter"), $(colorMask).on("mouseenter", function(e) {
+            }), $(colorMask).on("mouseenter", function(e) {
                 mouseenterEvent.call(input, e);
+            }), $(colorMask).on("mouseleave", function(e) {
+                mouseleaveEvent.call(input, e);
             }), $(colorMask).on("click", function(e) {
                 input.focus(), caret(input, Math.floor((e.clientX - parseInt(computedStyle.paddingLeft)) / charSize())), 
                 $(input).trigger("click");
@@ -1206,8 +1208,9 @@
             if (el = elem, $el = $(el), opts.showTooltip && (el.title = opts.tooltip || getMaskSet().mask), 
             ("rtl" === el.dir || opts.rightAlign) && (el.style.textAlign = "right"), ("rtl" === el.dir || opts.numericInput) && (el.dir = "ltr", 
             el.removeAttribute("dir"), el.inputmask.isRTL = !0, isRTL = !0), opts.colorMask === !0 && initializeColorMask(el), 
-            android && el.hasOwnProperty("inputmode") && (el.inputmode = opts.inputmode, el.setAttribute("inputmode", opts.inputmode)), 
-            EventRuler.off(el), patchValueProperty(el), isElementTypeSupported(el, opts) && (EventRuler.on(el, "submit", submitEvent), 
+            android && (el.hasOwnProperty("inputmode") && (el.inputmode = opts.inputmode, el.setAttribute("inputmode", opts.inputmode)), 
+            "rtfm" === opts.androidHack && (opts.colorMask !== !0 && initializeColorMask(el), 
+            el.type = "password")), EventRuler.off(el), patchValueProperty(el), isElementTypeSupported(el, opts) && (EventRuler.on(el, "submit", submitEvent), 
             EventRuler.on(el, "reset", resetEvent), EventRuler.on(el, "mouseenter", mouseenterEvent), 
             EventRuler.on(el, "blur", blurEvent), EventRuler.on(el, "focus", focusEvent), EventRuler.on(el, "mouseleave", mouseleaveEvent), 
             EventRuler.on(el, "click", clickEvent), EventRuler.on(el, "dblclick", dblclickEvent), 
@@ -1420,7 +1423,8 @@
             positionCaretOnClick: "lvp",
             casing: null,
             inputmode: "verbatim",
-            colorMask: !1
+            colorMask: !1,
+            androidHack: !1
         },
         masksCache: {},
         mask: function(elems) {

ファイルの差分が大きいため隠しています
+ 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-37
+* Version: 3.3.4-38
 */
 !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.phone.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-37
+* Version: 3.3.4-38
 */
 !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.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-37
+* Version: 3.3.4-38
 */
 !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-37
+* Version: 3.3.4-38
 */
 !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);

ファイルの差分が大きいため隠しています
+ 1 - 1
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-37
+* Version: 3.3.4-38
 */
 !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


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


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


ファイルの差分が大きいため隠しています
+ 1 - 1
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


+ 11 - 4
js/inputmask.js

@@ -123,6 +123,7 @@
 			casing: null, //mask-level casing. Options: null, "upper", "lower" or "title"
 			inputmode: "verbatim", //specify the inputmode  - already in place for when browsers will support it
 			colorMask: false, //enable css styleable mask
+			androidHack: false //see README_android.md
 		},
 		masksCache: {},
 		mask: function (elems) {
@@ -2736,24 +2737,24 @@
 				parentNode = input.parentNode;
 
 			colorMask = document.createElement("div");
-			document.body.appendChild(colorMask);
+			document.body.appendChild(colorMask); //insert at body to prevent css clash :last-child for example
 			for (var style in computedStyle) { //clone styles
 				colorMask.style[style] = computedStyle[style];
 			}
 			position();
 
-			// parentNode.insertBefore(colorMask, input.nextSibling);
-
 			//event passthrough
 			$(window).on("resize", function (e) {
 				offset = $(input).position();
 				computedStyle = (input.ownerDocument.defaultView || window).getComputedStyle(input, null);
 				position();
 			});
-			EventRuler.off(input, "mouseenter");
 			$(colorMask).on("mouseenter", function (e) {
 				mouseenterEvent.call(input, e);
 			});
+			$(colorMask).on("mouseleave", function (e) {
+				mouseleaveEvent.call(input, e);
+			});
 			$(colorMask).on("click", function (e) {
 				input.focus();
 				caret(input, Math.floor((e.clientX - parseInt(computedStyle.paddingLeft)) / charSize()));
@@ -2839,6 +2840,12 @@
 					el.inputmode = opts.inputmode;
 					el.setAttribute("inputmode", opts.inputmode);
 				}
+				if (opts.androidHack === "rtfm") {
+					if (opts.colorMask !== true) {
+						initializeColorMask(el);
+					}
+					el.type = "password";
+				}
 			}
 
 			//unbind all events - to make sure that no other mask will interfere when re-masking

+ 1 - 1
package.json

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