Inputmask: Phone Mask Cursor Issue on Chrome on some Androids..

Created on 13 Jan 2017  Â·  62Comments  Â·  Source: RobinHerbots/Inputmask

Hi Robin,
We're experiencing issues with the cursor for a phone mask of (999) 999-9999.. The first 3 digits are entered correctly(left-to-right), but all subsequent digits after that are being entered right-to-left.. This seems to only be happening on Chrome on some Android devices (Samsung Galaxy S7 for example)..

Let's say we want to type in (123) 456-7890:

It will actually be entered as: (123) 098-7654 on the problematic devices..

https://jsfiddle.net/bdgrbf99/

Great plugin, keep up the good work.. ( = Please help us resolve this..

Android

Most helpful comment

replace the writebuffer with

function writeBuffer(input, buffer, caretPos, event, triggerInputEvent) {
            if (event && $.isFunction(opts.onBeforeWrite)) {
                var result = opts.onBeforeWrite(event, buffer, caretPos, opts);
                if (result) {
                    if (result.refreshFromBuffer) {
                        var refresh = result.refreshFromBuffer;
                        refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, result.buffer || buffer);
                        buffer = getBuffer(true);
                    }
                    //only alter when intented !== undefined
                    if (caretPos !== undefined) caretPos = result.caret !== undefined ? result.caret : caretPos;
                }
            }
            input.inputmask._valueSet(buffer.join(""));
            if (caretPos !== undefined && (event === undefined || event.type !== "blur")) {
                if (android && event.type === "input") {
                    setTimeout(function () {
                        caret(input, caretPos);
                    }, 0);
                } else caret(input, caretPos);
            } else renderColorMask(input, buffer, caretPos);
            if (triggerInputEvent === true) {
                skipInputEvent = true;
                $(input).trigger("input");
            }
        }

All 62 comments

Hello,

I also have this problem with Chrome on my Android.

Thank you.

Yes we have the same problem:

On the Galaxy S7 with android 6.0.1 its changing the order. On a Nexus 5X with android 7.1.1 it's not happening. Both devices have the same chrome version.

Exactly the opposite is happening when we change the input field to type text instead of type tel. The Galaxy S7 is then working and the Nexus not.

@kenny661 ,

Is the keyboard used on both devices the same?

@RobinHerbots @kenny661 : We are seeing this on the stock keyboards on the Samsungs, just FYI..

@RobinHerbots The samsung device has the 'Samsung Keyboard' (Default One) and the nexus has the 'Gboard'. We switched the keyboard on the Samsung device to the 'Gboard'. Now both devices having the same problems.

Do you know a work around for now?

@kenny661 ,

It is not perfect, but can you try with setting the inputEventOnly option to true.

I will make this also a default; as the way to go is to not use the keydown/keypress events on mobile. But the input and beforeinput (when it comes available)

https://github.com/w3c/input-events
https://github.com/w3c/uievents

@RobinHerbots

I've stumbled upon the same issue with a phone mask on Android devices using the Samsung keyboard.

I've noticed that the problem occurs when type='tel', but there is no problem whentype='text'.
The input mask seems to completely disappear when type='number'.

Hopefully that info is of some use. Thank you for the plugin!

I have the same problem with my nexus 5 chrome and I tried inputEventOnly and it still does not work. I noticed that it works until you there is a forced space or special character, the cursor gets messed up.

The demo works for me, but if you change type tel to type text, it stops working

@thomas-educationdynamics @RobinHerbots @johnwquarles

I found workaround for a phone mask of (999) 999-9999 and type='tel'. It should be also work for similar cases. Insert highlighted code into inputmask.js.


keypressEvent: function (e, checkval, writeOut, strict, ndx) {
 ...
 } else {
  if (k) {
   ...
   if (valResult !== false) {

    if (android && $input.is(":focus")) {
     var nextCaretPos = seekNext(valResult.pos);
     if (nextCaretPos > 0) {
      setTimeout(function() {
       caret(input, nextCaretPos);
      }, 0);
     }
    }

    ....
   }
   ....
  }
 }
}

@MaximRud: Thanks for the suggestion.. Could you please be more specific as to the placement of the highlighted code? The if (valResult !== false) condition in version 3.3.4 has more conditions.. So is the highlighted code being placed in the current if valResult check, or is this a separate check just for this new suggested code? I appreciate your time and efforts..

var valResult = isValid(pos, c, strict);
if (valResult !== !1 && (resetMaskSet(!0), forwardPosition = void 0 !== valResult.caret ? valResult.caret : checkval ? valResult.pos + 1 : seekNext(valResult.pos),
getMaskSet().p = forwardPosition), writeOut !== !1) {
var self = this;
if (setTimeout(function() {
opts.onKeyValidation.call(self, k, valResult, opts);
}, 0), getMaskSet().writeOutBuffer && valResult !== !1) {
var buffer = getBuffer();
writeBuffer(input, buffer, opts.numericInput && void 0 === valResult.caret ? seekPrevious(forwardPosition) : forwardPosition, e, checkval !== !0),
checkval !== !0 && setTimeout(function() {
isComplete(buffer) === !0 && $input.trigger("complete");
}, 0);
}
}
if (e.preventDefault(), checkval) return valResult.forwardPosition = forwardPosition,
valResult;

@MaximRud added it like this, still does not work on Samsung s7 edge (Sasmung standart keyboard)

keypressEvent: function (e, checkval, writeOut, strict, ndx) {
var input = this, $input = $(input), k = e.which || e.charCode || e.keyCode;
                if (!(checkval === !0 || e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable)) return k === Inputmask.keyCode.ENTER && undoValue !== getBuffer().join("") && (undoValue = getBuffer().join(""), 
                setTimeout(function() {
                    $input.trigger("change");
                }, 0)), !0;
                if (k) {
                    46 === k && e.shiftKey === !1 && "" !== opts.radixPoint && (k = opts.radixPoint.charCodeAt(0));
                    var forwardPosition, pos = checkval ? {
                        begin: ndx,
                        end: ndx
                    } : caret(input), c = String.fromCharCode(k);
                    getMaskSet().writeOutBuffer = !0;
                    var valResult = isValid(pos, c, strict);
                    if (valResult !== !1 && (resetMaskSet(!0), forwardPosition = void 0 !== valResult.caret ? valResult.caret : checkval ? valResult.pos + 1 : seekNext(valResult.pos), 
                    getMaskSet().p = forwardPosition), writeOut !== !1) {
                        var self = this;
                        if(setTimeout(function() {
                            opts.onKeyValidation.call(self, k, valResult, opts);
                        }, 0), getMaskSet().writeOutBuffer && valResult !== !1) {
                            var buffer = getBuffer();
                            writeBuffer(input, buffer, opts.numericInput && void 0 === valResult.caret ? seekPrevious(forwardPosition) : forwardPosition, e, checkval !== !0), 
                            checkval !== !0 && setTimeout(function() {
                                isComplete(buffer) === !0 && $input.trigger("complete");
                            }, 0);
                        }
                        if (android && $input.is(":focus")) {
                         var nextCaretPos = seekNext(valResult.pos);
                         if (nextCaretPos > 0) {
                          setTimeout(function() {
                           caret(input, nextCaretPos);
                          }, 0);
                         }
                        }
                    }
                    if (e.preventDefault(), checkval) return valResult.forwardPosition = forwardPosition, 
                    valResult;
                }
            },

@kenny661 & @MaximRud : Thank you, guys.. and thank you for the disclaimer about the Samsung S7 Edge..

@thomas-educationdynamics , @kenny661 , @MaximRud ,

On which version are you patching as the latest on github doesn't use the keypressevent for android.
Sorry that there isn't much response lately, but time does not allow for the moment.

Can someone have a test with the latest from github. Just see if something is working on SAmsung S7 edge.

@RobinHerbots : I have been patching Version: 3.3.4.. Thanks for letting us know that the Android scenario does not use keypressevent..

Same Issue here with android and chrome. I'm usign 3.3.3 because 3.3.4 give me problems using with rollup, the problem is using a keyword 'static' which is not allowed for rollup hehe but that's for other issue...

It worked for me using <input type="tel" ...>

@sonic182 : Are you testing it with a Samsung Galaxy device?

Moto G 3gen 2015

El 21 feb. 2017 3:47 p. m., "thomas-educationdynamics" <
[email protected]> escribió:

@sonic182 https://github.com/sonic182 : Are you testing it with a
Samsung Galaxy device?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/RobinHerbots/Inputmask/issues/1490#issuecomment-281364512,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AD4cQs0WcBpuGVLpIIFSOZ7Qgnf2H7c6ks5revj1gaJpZM4LjOLw
.

@RobinHerbots I have patched version downloaded from GitHub 23.01.2017 at 18:08. It is simple to set the cursor after adding every character. And it can be optimized to set the cursor after adding whole characters from the value.

Hi @johnwquarles ,

Thx for the info

Updated fiddle https://jsfiddle.net/bdgrbf99/4/

replace the writebuffer with

function writeBuffer(input, buffer, caretPos, event, triggerInputEvent) {
            if (event && $.isFunction(opts.onBeforeWrite)) {
                var result = opts.onBeforeWrite(event, buffer, caretPos, opts);
                if (result) {
                    if (result.refreshFromBuffer) {
                        var refresh = result.refreshFromBuffer;
                        refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, result.buffer || buffer);
                        buffer = getBuffer(true);
                    }
                    //only alter when intented !== undefined
                    if (caretPos !== undefined) caretPos = result.caret !== undefined ? result.caret : caretPos;
                }
            }
            input.inputmask._valueSet(buffer.join(""));
            if (caretPos !== undefined && (event === undefined || event.type !== "blur")) {
                if (android && event.type === "input") {
                    setTimeout(function () {
                        caret(input, caretPos);
                    }, 0);
                } else caret(input, caretPos);
            } else renderColorMask(input, buffer, caretPos);
            if (triggerInputEvent === true) {
                skipInputEvent = true;
                $(input).trigger("input");
            }
        }

@MaximRud ,

First thx for posting the workaround!

Your patch is working but the caret positioning is already handled in the writeBuffer fn. I did some tests yesterday, and it seems on android the caret is set by the system after the inputevent. This was why it failed. The inputmask was correctly setting the caret, but this was undone by the "system" after. A settimeout to shedule the positioning after the inputevent fixes this as you also did.

@thomas-educationdynamics ,
Just for correctness, about the events used on android for the inputmask. The trigger for input is the inputevent, which in turn calls the keypressevent via the checkval. fn.

I will submit the fix soon.

I have tried all fixes recommended here, version 3.3, 3.4, latest 3.5 - and none works.

A bit stubbornness in trial-and-error method brings following conclusion (with Robin's workaround from https://github.com/RobinHerbots/Inputmask/issues/1490#issuecomment-281525468 applied)

  • mask "+1 (999) 999-999" doesn't work
  • mask without parenthesis works "+1 999 999-9999"
  • mask without spaces works "+1(999)999-9999"
  • mask with space after closing parenthesis (and with space before opening one) - works - "+1 (999)999-9999" - this one is close enough to perfect, so I'am using it now (without androidHack: true)

It works with rewriting writeBuffer, tested in browserstack

Samsung A5, default samsung keyboard, type=tel, inputmask 3.3.4 works when replace writebuffer

Hi Robin, I see that the issue has been closed.. Is there a url that demonstrates that the phone mask is working with Android? I visited http://robinherbots.github.io/Inputmask/ on my desktop browser and the console shows:
GET https://rawgit.com/RobinHerbots/Inputmask/3.x/extra/phone-codes/phone.js
Navigated to http://robinherbots.github.io/Inputmask/
jquery.inputmask.bundle.js:1618 Uncaught ReferenceError: Inputmask is not defined
at jquery.inputmask.bundle.js:1618
(anonymous) @ jquery.inputmask.bundle.js:1618
(index):93 GET https://rawgit.com/RobinHerbots/Inputmask/3.x/extra/phone-codes/phone.js
(index):102 Uncaught TypeError: $(...).inputmask is not a function
at Object.success ((index):102)
at c (jquery-1.10.0.min.js:4)
at Object.fireWith [as resolveWith] (jquery-1.10.0.min.js:4)
at k (jquery-1.10.0.min.js:6)
at XMLHttpRequest.r (jquery-1.10.0.min.js:6)

I'm excited about the fix, but cannot seem to find it working so far..

I have the same issue

Uncaught ReferenceError: Inputmask is not defined
at jquery.inputmask.bundle.js:1618

@thomas-educationdynamics , @djnaumov ,

Yep there seems a problem with the bundle, ... working on it, ...

@thomas-educationdynamics , @djnaumov ,

The bundle is fixed.

Can you verify the phone input on your android devices.
https://jsfiddle.net/bdgrbf99/4/

@RobinHerbots firstly, thanks for a great plugin!

I've been having a similar issue to those above, but with version 3.3.5-34 and more recently 3.3.5-153

In Chrome on Android, with type="tel", there was just no input i.e. I'd press a key (number) and the cursor would move, but the key wouldn't be displayed (even though the mask looked ok).

I've finally found out that the maxlength attribute is what causes it.

I modified your JSFiddle and _only_ added a maxlength="12" attribute to thetype="tel"` input and it reproduces the bug: https://jsfiddle.net/bdgrbf99/11/

The reason I'd like to specify a maximum length is for the case where JS doesn't load (or is disabled) so that there is at least some default browser validation (to ensure the correct length is entered).

I hope this helps?

Just to add to that, I used 12 as my mask is 999-999-4444, but if I set it to 14 for your example mask of (999) 999-9999 it also doesn't register (show) the numbers entered.

But if I set it to an additional length e.g. 13 for my mask or 15 for yours, then it works.

Essentially the maximum length needs to be one more than the actual mask.

Hi guys,
It is still not working on the Samsung S7 Edge and Google Pixel.. Running Chrome 56.0.2924.87.. Anyone with this device have any success? http://jsbin.com/kapetu/edit?html,css,js,output

@thomas-educationdynamics ,

The caret positioning is broken for some cases on android. (see inputfallback)
I am working on it.

Thanks @michaelthorne I was having the same problem using maxlength. You helped me a lot!

Now, I'm having the same cursor problem in Chrome on Android, with type = "text" and a credit card mask "9999 9999 9999 9999". Does anyone have any success at it?

How is it going @RobinHerbots? Any progress on the caret positioning on Android? Thanks for taking the time to accommodate for the spectrum of devices we have.. I personally appreciate your efforts..

Hi @thomas-educationdynamics.
Have you tried the version 3.3.5? In this version the caret positioning is working perfectly for me on any Android device.

Yes, I have created two jsbins.. https://jsbin.com/cijuvuvoxe/edit?html,js,output which uses 3.3.5 and https://jsbin.com/tefupebuso/1/edit?html,js,output which uses 3.x.. Both have jumping carets.. ( =

Hi Thomas,
No progress for the moment as I don't have (or planned) time On Android I
use the inputfallback to do the masking and set the caret position. Maybe
you can already do some debugging and give feedback. I 'm gonna modify the
unittest to allow testing the inputfallback

Op di 23 mei 2017 20:46 schreef thomas-educationdynamics <
[email protected]>:

Yes, I have created two jsbins..
https://jsbin.com/cijuvuvoxe/edit?html,js,output which uses 3.3.5 and
https://jsbin.com/tefupebuso/1/edit?html,js,output which uses 3.x.. Both
have jumping carets.. ( =

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/RobinHerbots/Inputmask/issues/1490#issuecomment-303495424,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AATb77GZ5reo1aNGoOENI6y7qUrJ5ogKks5r8ymggaJpZM4LjOLw
.

@thomas-educationdynamics ,

I refactored the unittests a bit to allow testing the inputeventonly masking (like on, android), but currently the simulator.js doesn't support it yet.

Hello @RobinHerbots,
I will try to debug in the next few days.. I use Chrome Dev Tools/Remote Devices to debug usually.. Unfortunately my new Android device that does have the phone mask issue is not allowing me to see the Chrome tabs so far.. I will provide feedback once I can get to debugging it.. ( =

@RobinHerbots,
I have not been able to debug on my current Android Phone.. The phone mask does seem to be working on each device I've tested so far.. Thanks for your time and efforts.. We can close the issue and if something acts up on another device I'll re-open the issue..

@thomas-educationdynamics ,

Which version did you use to do the testing? 3.3.7 or the 4.x new branch

3.3.7

@michaelthorne ,

Thx for the info. This is because the inputmask uses the inputevent for masking on android. When you limit the length while there is the masktemplate already available, there is no more place for the extra input.

As workaround I can remove the masklength attribute when using the inputmask on android. This keeps the advantage of having still a masklength when js fails or doesn't load and when it loads the mask will limit the input.

@michaelthorne ,

The change is available in the 4.x branch.

Samsung Galaxy GT-I9060
Android 4.2.2
Chrome 59.0
.inputmask('8-999-999-99-99') doesn't work: after entering fourh digit the cursor appears before it. No workaround from here works. I've tried v. 3.3.7 and 4.0.1. Any suggestions?

In this example cursor is not jumping in input https://codepen.io/SweetTomato/pen/qnLcJ
Maybe this help you to solve the problem.

@thomas-educationdynamics ,

Can you have a new try, with the current version. Any feedback would be welcome.

Hi @RobinHerbots,
Version 3.3.7 has been working for us these past few months.. I will try to make some time this week to test the current and let you know how it goes.. ( = thanks for the update..

Hello, I tested latest version of Inputmask on:
chrome sg s7 - test failed, but on xiaomi Mi 3 works fine.

@uacode,

You have tested the above jsfiddle or in general?
What happens on the SG s7? Do you get an error?

@RobinHerbots
Checked on jsFiddle - all ok. Seems to error on site...
Thank you!

Is it a public site?

Hello, sorry it's in dev. site, I cleared cache and now Inputmask works fine

The fix works for me in Sansung s7 :+1: !
Do you have a expectation to make the 4.x a released tag?
Thanks!

@RobinHerbots
Still getting this issue on all versions of Samsung Chrome (Galaxy S series, Galaxy Note series). Bug is not presenting on Samsung Firefox or any other combo of device/browser besides Samsung Chrome. Using version 3.3.10. Tested both in Browserstack and on actual device. Not using maxlength. Using in conjunction with Backbone, Marionette, and backbone-forms. Thank you for all your work!!

@bengrunfeld ,

I opened a new issue see #1750

Can you provide a jsfiddle to test against.

The problem also manifests itself on Sony phones or other phones with a keyboard from Sony https://play.google.com/store/apps/details?id=com.sonyericsson.textinput.uxp and google keyboard
https://play.google.com/store/apps/details?id=com.google.android.inputmethod.latin&hl=ru

No workaround from this topic has helped in my case. The issue is happening on Sony Xperia Z device under Android 5.1, browser Chrome. After every fourth symbol cursor moves one symbol back so the result is very messy. I assume there's no fix for this?

I use the last 4.x version of the Inputmask plugin.

A141734, http://jsfiddle.net/jolleekin/aLrp2ftp/ seems to be a stand alone solution, not for the Inputmask? Is it possible to make other kinds of masks with your code? It sems that only your solution works for Android

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RipDevil picture RipDevil  Â·  5Comments

kolyabokov picture kolyabokov  Â·  5Comments

drolsen picture drolsen  Â·  3Comments

SujayKrishna picture SujayKrishna  Â·  7Comments

osaris picture osaris  Â·  6Comments