mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix(tap): Prevent different input focus after 300ms delay
If a text input is located in the same area as a button which was just tapped, which was probably because of a view transition, the text input gets focus 300ms later. This is an issue on Android because it also fires off a mousedown event. Resolved by remembering the touchend target then checking if it’s different from the mousedown target. Closes #1370
This commit is contained in:
@@ -66,6 +66,7 @@ var tapMouseResetTimer;
|
||||
var tapPointerMoved;
|
||||
var tapPointerStart;
|
||||
var tapTouchFocusedInput;
|
||||
var tapLastTouchTarget;
|
||||
|
||||
var TAP_RELEASE_TOLERANCE = 6; // how much the coordinates can be off between start/end, but still a click
|
||||
|
||||
@@ -259,7 +260,7 @@ function tapMouseDown(e) {
|
||||
console.log('mousedown', 'stop event');
|
||||
e.stopPropagation();
|
||||
|
||||
if( !ionic.tap.isTextInput(e.target) ) {
|
||||
if( !ionic.tap.isTextInput(e.target) || tapLastTouchTarget !== e.target ) {
|
||||
// If you preventDefault on a text input then you cannot move its text caret/cursor.
|
||||
// Allow through only the text input default. However, without preventDefault on an
|
||||
// input the 300ms delay can change focus on inputs after the keyboard shows up.
|
||||
@@ -336,8 +337,13 @@ function tapTouchEnd(e) {
|
||||
tapEnableTouchEvents();
|
||||
if( !tapHasPointerMoved(e) ) {
|
||||
tapClick(e);
|
||||
|
||||
if( e.target.tagName === 'SELECT' ) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
tapLastTouchTarget = e.target;
|
||||
tapTouchCancel();
|
||||
}
|
||||
|
||||
|
||||
@@ -405,6 +405,26 @@ describe('Ionic Tap', function() {
|
||||
expect( e.dispatchedEvent ).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should preventDefault on touchend when the target is a select', function() {
|
||||
var e = {
|
||||
target: document.createElement('select'),
|
||||
clientX: 100, clientY: 100,
|
||||
dispatchEvent: function(){ this.dispatchedEvent = true; },
|
||||
preventDefault:function(){ this.preventedDefault = true; }
|
||||
};
|
||||
tapTouchEnd(e);
|
||||
expect( e.preventedDefault ).toEqual(true);
|
||||
|
||||
e = {
|
||||
target: document.createElement('div'),
|
||||
clientX: 100, clientY: 100,
|
||||
dispatchEvent: function(){ this.dispatchedEvent = true; },
|
||||
preventDefault:function(){ this.preventedDefault = true; }
|
||||
};
|
||||
tapTouchEnd(e);
|
||||
expect( e.preventedDefault ).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should cancel click when mousemove coordinates goes too far from mousedown coordinates', function() {
|
||||
var e = { clientX: 100, clientY: 100 };
|
||||
tapMouseDown(e);
|
||||
@@ -442,6 +462,27 @@ describe('Ionic Tap', function() {
|
||||
expect( e.isTapHandled ).toEqual(false);
|
||||
});
|
||||
|
||||
it('Should preventDefault on mousedown if touchend target is different than mousedown target', function() {
|
||||
tapLastTouchTarget = null;
|
||||
|
||||
var touchEndEvent = {
|
||||
target: document.createElement('button'),
|
||||
clientX: 100, clientY: 100,
|
||||
preventDefault: function(){ this.defaultedPrevented = true; }
|
||||
};
|
||||
tapTouchEnd(touchEndEvent);
|
||||
expect( tapLastTouchTarget ).toEqual(touchEndEvent.target);
|
||||
|
||||
var mouseDownEvent = {
|
||||
target: document.createElement('textarea'),
|
||||
clientX: 100, clientY: 100,
|
||||
preventDefault: function(){ this.defaultedPrevented = true; },
|
||||
stopPropagation: function(){ this.stoppedPropagation = true; }
|
||||
};
|
||||
tapMouseDown(mouseDownEvent);
|
||||
expect( mouseDownEvent.defaultedPrevented ).toEqual(true);
|
||||
});
|
||||
|
||||
it('Should tapClick with touchend and fire immediately', function() {
|
||||
var e = {
|
||||
target: {
|
||||
|
||||
Reference in New Issue
Block a user