diff --git a/js/utils/tap.js b/js/utils/tap.js index ebf7075e908..36234d5a96b 100644 --- a/js/utils/tap.js +++ b/js/utils/tap.js @@ -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(); } diff --git a/test/unit/utils/tap.unit.js b/test/unit/utils/tap.unit.js index b5fd1cb5e35..3c20c9dda6e 100644 --- a/test/unit/utils/tap.unit.js +++ b/test/unit/utils/tap.unit.js @@ -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: {