Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect cursor position and duplicate characters after separator on Android #416

Closed
andrewrota opened this issue Jan 23, 2014 · 27 comments
Assignees
Labels
Milestone

Comments

@andrewrota
Copy link

Demo: http://jsfiddle.net/Tpr6N/2/

JS Code:

$(document).ready(function () {
    $(".input").inputmask({
       "mask": "***-***"
    });
});

Steps to reproduce:

  1. Touch input field to open keyboard
  2. Touch '1' on keyboard. Touch '2' on keyboard. Touch '3' on keyboard.
  3. Touch '4' on keyboard. As the character appears the cursor is not in its proper position following the character. Rather, the cursor is placed before the '4' character.
  4. Touch '5' on keyboard. At this point the cursor is moved past the '4' character, the '5' character appears following the '4' character, and there is an additional '4' character after the '5' as well. Six characters are now in the input field rather than the inputted five characters.

Note: Sometimes this behavior is inconsistent following the above steps. But trying the same thing a second or third time usually ends up causing the bug.

Device: Samsung Galaxy S4 SCH-I545
OS: Android 4.2.4
Browser: Native Android browser

(Don't know if this is considered a duplicate of #368, but it seems like a distinct bug)

@RobinHerbots
Copy link
Owner

@andrewrota,

Can you have a test with this http://jsfiddle.net/Tpr6N/4/

@andrewrota
Copy link
Author

@RobinHerbots Thanks for the quick response. I tested the new version you sent but the behavior is still present.

@RobinHerbots
Copy link
Owner

Can you send the useragent string

2014/1/24 Andrew Rota [email protected]

@RobinHerbots https://github.com/RobinHerbots Thanks for the quick
response. I tested the new version you sent but the behavior is still
present.


Reply to this email directly or view it on GitHubhttps://github.com//issues/416#issuecomment-33229329
.

@andrewrota
Copy link
Author

Mozilla/5.0 (Linux; Android 4.2.2; en-us; SAMSUNG SCH-I545 Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Version/1.0 Chrome/18.0.1025.308 Mobile Safari/535.19

@samspot
Copy link

samspot commented Feb 5, 2014

FYI, I'm seeing this behavior on android 2.3 in this and 2 other plugins, as well as several native JS attempts. Seems to be a browser bug.

@RobinHerbots
Copy link
Owner

@andrewrota,

Can you have some tests on the android stock browsers?

http://jsfiddle.net/Tpr6N/14/
http://jsfiddle.net/Tpr6N/20/

http://jsfiddle.net/UJvN7/

@rizowski
Copy link

@RobinHerbots
This is also happening on Galaxy tablet and phones using Firefox ver 26.01 and 27.01.

User Agent stuff:
Mozilla/5.0 (Android; Mobile; rv:26.0) Gecko/26.0 Firefox/26.0

I am also seeing this sometimes:
TypeError: activeMaskset["tests"][testPos] is undefined (24) jquery.inputmask.js

@RobinHerbots
Copy link
Owner

@andrewrota, @rizowski ,

This issue should be fixed with the latest commits in the 2.5 branch.
Can you have a test with http://jsfiddle.net/UJvN7/

@samspot,

I will have a look at the stock browser in android 2.3 through an emulator.

@andrewrota
Copy link
Author

Yes, I'll give it a try as soon as possible.

@rizowski
Copy link

@RobinHerbots I am not seeing any duplicate characters but it seems the carrot is still being placed in the wrong position after you pass a separator. This is happening in Firefox but not Chrome for a Galaxy phone. This happens in both browsers for a Galaxy Tablet.

For example if I enter in 123456789 for mask of 999-99-9999 results in: 123-56-8974.

  1. 123-|4_-____
  2. 123-5|4-____
  3. 123-56-|74__
  4. 123-56-89|74

Also in Firefox and Chrome for Galaxy tablets and phones I am noticing that if the carrot gets to the end of the mask and you try to delete it wont allow it until you move the carrot in one character. I can create a new bug report for that.

@RobinHerbots
Copy link
Owner

@rizowski ,

Did you clear the cache of the browser? I tested FF27 on my phone and the caret positioning was correct. Can you also submit the useragent strings.

Thx for the feedback!
Robin

@rizowski
Copy link

@RobinHerbots
Yeah I cleared the cache for the tablet and I have just received the phone. I am getting some strange results for http://jsfiddle.net/UJvN7/ on the phone. Like trying to click on the field and it wont let me type anything. I am going to convert it over to a plunker and see if that works any better. It looks like on the tablet it is still doing it.

Galaxy Tablet:

Chrome:

Mozilla/5.0 (Linux; Android 4.1.1; GT-P3113 Build/JRO03C) AppleWebKit/537.36 (KHTML, like gecko) Chrome/27.0.1453.90 Safari/537.36 =>

Firefox:

Mozilla/5.0 (Android; Tablet; rv:26.0) Gecko/26.0 Firefox/26.0 =>

Galaxy Phone:

Chrome:

Mozilla/5.0 (Linux; Android 4.3; Galaxy Nexus Build/JWR67B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36 =>

Firefox:

Mozilla/5.0 (Android; Mobile; rv:26.0) Gecko/26.0 Firefox/26.0 =>

Edit: CodePen: http://codepen.io/rizowski/pen/KfmzA

@rizowski
Copy link

@RobinHerbots

Testing out the phone on codepen worked out well. The issue is still there for Firefox26.01 and it has gone away for Chrome.

@RobinHerbots
Copy link
Owner

http://jsfiddle.net/UJvN7/5 Can this version be tested on FF

@rizowski
Copy link

Entered 123abc and got 123-bca on the Galaxy tablet and phone for FF on both fields

@samspot
Copy link

samspot commented Feb 13, 2014

Similar for me with stock browser on 2.3.3 emulator (with original fiddle):

image

@samspot
Copy link

samspot commented Feb 13, 2014

This is right after it happens, with cursor in between b & a

image

@rizowski
Copy link

So I have been looking over some of the code. There are some places that could be refactored a bit to make it a little easier to read. I was also noticing that when you delete characters for the mobile phone in Firefox and you go past a separator character the caret will jump back to the separator. I get the feeling this is being caused by one of the functions that resets the caret.

Examples of what I am talking about:

123-45-____

  1. 123-45|-____
  2. 123-4_|-____ => It will delete the character and then jump back to the separator. After that it acts like normal and continues to delete without jumping around the mask.

I have also noticed the caret will temporarily jump back to the very end of the mask and then readjust.

123-45-678_
1)123-45-678|_
2) 123-45-67|__ => 123-45-67__| => 123-45-67|__

Hope this helps clears some things up.

@rizowski
Copy link

I think I was able to fix it. It is working on my devices with switching 1121 line to false instead of true. A pull request has been made.

@RobinHerbots
Copy link
Owner

See comment pull request #435

A last fiddle http://jsfiddle.net/UJvN7/15/

@RobinHerbots
Copy link
Owner

@RobinHerbots
Copy link
Owner

#465

@JCMais
Copy link

JCMais commented May 20, 2014

Just a heads up, this is not reproducible on Chrome for Android 4.4.2 (Moto G).

Typing "jonathan" in the above script, outputs the following:

compositionstart |||| compositionupdate |||| input j |||| keydown j |||| keyup j |||| compositionupdate j |||| input jo |||| keydown jo |||| keyup jo |||| compositionupdate jo |||| input jo |||| keydown jo |||| keyup jo |||| compositionupdate jo |||| input jon |||| keydown jon |||| keyup jon |||| compositionupdate jon |||| input jona |||| keydown jona |||| keyup jona |||| compositionupdate jona |||| input jona |||| keydown jona |||| keyup jona |||| compositionupdate jona |||| input jonat |||| keydown jonat |||| keyup jonat |||| compositionupdate jonat |||| input jonath |||| keydown jonath |||| keyup jonath |||| compositionupdate jonath |||| input jonath |||| keydown jonath |||| keyup jonath |||| compositionupdate jonath |||| input jonatha |||| keydown jonatha |||| keyup jonatha |||| compositionupdate jonatha |||| input jonathan |||| keydown jonathan |||| keyup jonathan |||| compositionend jonathan |||| input jonathan ||||

@RobinHerbots
Copy link
Owner

@RobinHerbots
Copy link
Owner

@RobinHerbots
Copy link
Owner

originalEvent: [object CompositionEvent] ||| type: compositionstart ||| isDefaultPrevented: function returnFalse() { return false; } ||| timeStamp: 1400697466262 ||| jQuery1910650616864906624: true ||| which: 0 ||| view: [object Window] ||| target: [object HTMLInputElement] ||| shiftKey: undefined ||| relatedTarget: undefined ||| metaKey: false ||| eventPhase: 2 ||| currentTarget: [object HTMLInputElement] ||| ctrlKey: undefined ||| cancelable: true ||| bubbles: true ||| altKey: undefined ||| delegateTarget: [object HTMLInputElement] ||| handleObj: [object Object] ||| data: undefined ||| isPropagationStopped: function returnFalse() { return false; } ||| isImmediatePropagationStopped: function returnFalse() { return false; } ||| preventDefault: function () { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( !e ) { return; } // If preventDefault exists, run it on the original event if ( e.preventDefault ) { e.preventDefault(); // Support: IE // Otherwise set the returnValue property of the original event to false } else { e.returnValue = false; } } ||| stopPropagation: function () { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( !e ) { return; } // If stopPropagation exists, run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // Support: IE // Set the cancelBubble property of the original event to true e.cancelBubble = true; } ||| stopImmediatePropagation: function () { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); } ||| ========== originalEvent: [object CompositionEvent] ||| type: compositionupdate ||| isDefaultPrevented: function returnFalse() { return false; } ||| timeStamp: 1400697466322 ||| jQuery1910650616864906624: true ||| which: 0 ||| view: [object Window] ||| target: [object HTMLInputElement] ||| shiftKey: undefined ||| relatedTarget: undefined ||| metaKey: false ||| eventPhase: 2 ||| currentTarget: [object HTMLInputElement] ||| ctrlKey: undefined ||| cancelable: true ||| bubbles: true ||| altKey: undefined ||| delegateTarget: [object HTMLInputElement] ||| handleObj: [object Object] ||| data: undefined ||| isPropagationStopped: function returnFalse() { return false; } ||| isImmediatePropagationStopped: function returnFalse() { return false; } ||| preventDefault: function () { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( !e ) { return; } // If preventDefault exists, run it on the original event if ( e.preventDefault ) { e.preventDefault(); // Support: IE // Otherwise set the returnValue property of the original event to false } else { e.returnValue = false; } } ||| stopPropagation: function () { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( !e ) { return; } // If stopPropagation exists, run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // Support: IE // Set the cancelBubble property of the original event to true e.cancelBubble = true; } ||| stopImmediatePropagation: function () { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); } ||| ========== originalEvent: [object Event] ||| type: input ||| isDefaultPrevented: function returnFalse() { return false; } ||| timeStamp: 1400697466351 ||| jQuery1910650616864906624: true ||| which: undefined ||| view: undefined ||| target: [object HTMLInputElement] ||| shiftKey: undefined ||| relatedTarget: undefined ||| metaKey: false ||| eventPhase: 2 ||| currentTarget: [object HTMLInputElement] ||| ctrlKey: undefined ||| cancelable: false ||| bubbles: true ||| altKey: undefined ||| delegateTarget: [object HTMLInputElement] ||| handleObj: [object Object] ||| data: undefined ||| isPropagationStopped: function returnFalse() { return false; } ||| isImmediatePropagationStopped: function returnFalse() { return false; } ||| preventDefault: function () { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( !e ) { return; } // If preventDefault exists, run it on the original event if ( e.preventDefault ) { e.preventDefault(); // Support: IE // Otherwise set the returnValue property of the original event to false } else { e.returnValue = false; } } ||| stopPropagation: function () { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( !e ) { return; } // If stopPropagation exists, run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // Support: IE // Set the cancelBubble property of the original event to true e.cancelBubble = true; } ||| stopImmediatePropagation: function () { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); } ||| ========== originalEvent: [object CompositionEvent] ||| type: compositionend ||| isDefaultPrevented: function returnFalse() { return false; } ||| timeStamp: 1400697469685 ||| jQuery1910650616864906624: true ||| which: 0 ||| view: [object Window] ||| target: [object HTMLInputElement] ||| shiftKey: undefined ||| relatedTarget: undefined ||| metaKey: false ||| eventPhase: 2 ||| currentTarget: [object HTMLInputElement] ||| ctrlKey: undefined ||| cancelable: true ||| bubbles: true ||| altKey: undefined ||| delegateTarget: [object HTMLInputElement] ||| handleObj: [object Object] ||| data: undefined ||| isPropagationStopped: function returnFalse() { return false; } ||| isImmediatePropagationStopped: function returnFalse() { return false; } ||| preventDefault: function () { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( !e ) { return; } // If preventDefault exists, run it on the original event if ( e.preventDefault ) { e.preventDefault(); // Support: IE // Otherwise set the returnValue property of the original event to false } else { e.returnValue = false; } } ||| stopPropagation: function () { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( !e ) { return; } // If stopPropagation exists, run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // Support: IE // Set the cancelBubble property of the original event to true e.cancelBubble = true; } ||| stopImmediatePropagation: function () { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); } ||| ========== originalEvent: [object Event] ||| type: input ||| isDefaultPrevented: function returnFalse() { return false; } ||| timeStamp: 1400697469735 ||| jQuery1910650616864906624: true ||| which: undefined ||| view: undefined ||| target: [object HTMLInputElement] ||| shiftKey: undefined ||| relatedTarget: undefined ||| metaKey: false ||| eventPhase: 2 ||| currentTarget: [object HTMLInputElement] ||| ctrlKey: undefined ||| cancelable: false ||| bubbles: true ||| altKey: undefined ||| delegateTarget: [object HTMLInputElement] ||| handleObj: [object Object] ||| data: undefined ||| isPropagationStopped: function returnFalse() { return false; } ||| isImmediatePropagationStopped: function returnFalse() { return false; } ||| preventDefault: function () { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( !e ) { return; } // If preventDefault exists, run it on the original event if ( e.preventDefault ) { e.preventDefault(); // Support: IE // Otherwise set the returnValue property of the original event to false } else { e.returnValue = false; } } ||| stopPropagation: function () { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( !e ) { return; } // If stopPropagation exists, run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // Support: IE // Set the cancelBubble property of the original event to true e.cancelBubble = true; } ||| stopImmediatePropagation: function () { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); } ||| ==========

@RobinHerbots
Copy link
Owner

see #465

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants