From 2bca0eebc9059e8170fc49b1935a23e6fc8bc268 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Thu, 10 May 2018 15:10:03 -0700 Subject: [PATCH] Only disable tabs for "disablable" elements Fixes #5190 --- lib/utils/gestures.html | 15 +++- test/unit/gestures-elements.html | 76 ++++++++++++++++++-- test/unit/gestures.html | 116 +++++++++++++++++++++---------- 3 files changed, 164 insertions(+), 43 deletions(-) diff --git a/lib/utils/gestures.html b/lib/utils/gestures.html index 2a05daa462..a948ac3a7e 100644 --- a/lib/utils/gestures.html +++ b/lib/utils/gestures.html @@ -113,6 +113,19 @@ 'select': true }; + /** @type {!Object} */ + const canBeDisabled = { + 'button': true, + 'command': true, + 'fieldset': true, + 'input': true, + 'keygen': true, + 'optgroup': true, + 'option': true, + 'select': true, + 'textarea': true + }; + /** * @param {HTMLElement} el Element to check labelling status * @return {boolean} element can have labels @@ -1058,7 +1071,7 @@ let dy = Math.abs(e.clientY - this.info.y); // find original target from `preventer` for TouchEvents, or `e` for MouseEvents let t = Gestures._findOriginalTarget(/** @type {Event} */(preventer || e)); - if (!t || t.disabled) { + if (!t || (canBeDisabled[t.localName] && t.disabled)) { return; } // dx,dy can be NaN if `click` has been simulated and there was no `down` for `start` diff --git a/test/unit/gestures-elements.html b/test/unit/gestures-elements.html index 15b7abeb1a..a6ea460c3f 100644 --- a/test/unit/gestures-elements.html +++ b/test/unit/gestures-elements.html @@ -244,24 +244,92 @@ + + + + + + + \ No newline at end of file diff --git a/test/unit/gestures.html b/test/unit/gestures.html index b1a001bdd4..a691526bea 100644 --- a/test/unit/gestures.html +++ b/test/unit/gestures.html @@ -615,44 +615,84 @@ }); }); - test('disabled elements don\'t fire taps', function() { - let el = document.createElement('x-disabled-tap'); - document.body.appendChild(el); - // tap an element with disabled attribute - let target = el.$.disabled; - // simulate the event sequence of a touch on the screen - let touches = [{ - clientX: 0, - clientY: 0, - identifier: 1, - // target is set to the element with `addEventListener`, which is `target` - target - }]; - let touchstart = new CustomEvent('touchstart', {bubbles: true, composed: true}); - touchstart.changedTouches = touchstart.touches = touches; - target.dispatchEvent(touchstart); - let touchend = new CustomEvent('touchend', {bubbles: true, composed: true}); - touchend.touches = touchend.changedTouches = touches; - target.dispatchEvent(touchend); - assert.equal(el.taps.length, 0); - // tap an element with a disabled ancestor - target = el.$.nested; - // simulate the event sequence of a touch on the screen - touches = [{ - clientX: 0, - clientY: 0, - identifier: 1, - // target is set to the element with `addEventListener`, which is `target` - target - }]; - touchstart = new CustomEvent('touchstart', {bubbles: true, composed: true}); - touchstart.changedTouches = touchstart.touches = touches; - target.dispatchEvent(touchstart); - touchend = new CustomEvent('touchend', {bubbles: true, composed: true}); - touchend.touches = touchend.changedTouches = touches; - target.dispatchEvent(touchend); - assert.equal(el.taps.length, 1); - document.body.removeChild(el); + suite('disabled', function() { + test('click() function works as expected on disabled elements', function() { + Polymer.Gestures.resetMouseCanceller(); + let el = document.createElement('x-disabled-tap'); + document.body.appendChild(el); + el.$.disabled.click(); + el.$.nested.click(); + el.$.disabledEl.click(); + assert.deepEqual(el.taps, ['button#nested', 'x-disabled#disabledEl']); + document.body.removeChild(el); + }); + + test('disabled elements don\'t fire taps', function() { + let el = document.createElement('x-disabled-tap'); + document.body.appendChild(el); + // tap an element with disabled attribute + let target = el.$.disabled; + // simulate the event sequence of a touch on the screen + let touches = [{ + clientX: 0, + clientY: 0, + identifier: 1, + // target is set to the element with `addEventListener`, which is `target` + target + }]; + let touchstart = new CustomEvent('touchstart', {bubbles: true, composed: true}); + touchstart.changedTouches = touchstart.touches = touches; + target.dispatchEvent(touchstart); + let touchend = new CustomEvent('touchend', {bubbles: true, composed: true}); + touchend.touches = touchend.changedTouches = touches; + target.dispatchEvent(touchend); + assert.deepEqual(el.taps, []); + + // tap an element with a disabled ancestor + target = el.$.nested; + // simulate the event sequence of a touch on the screen + touches = [{ + clientX: 0, + clientY: 0, + identifier: 1, + // target is set to the element with `addEventListener`, which is `target` + target + }]; + touchstart = new CustomEvent('touchstart', {bubbles: true, composed: true}); + touchstart.changedTouches = touchstart.touches = touches; + target.dispatchEvent(touchstart); + touchend = new CustomEvent('touchend', {bubbles: true, composed: true}); + touchend.touches = touchend.changedTouches = touches; + target.dispatchEvent(touchend); + assert.deepEqual(el.taps, ['button#nested']); + + // tap a custom element with a `disabled` property + target = el.$.disabledEl; + // simulate the event sequence of a touch on the screen + touches = [{ + clientX: 0, + clientY: 0, + identifier: 1, + // target is set to the element with `addEventListener`, which is `target` + target + }]; + touchstart = new CustomEvent('touchstart', {bubbles: true, composed: true}); + touchstart.changedTouches = touchstart.touches = touches; + target.dispatchEvent(touchstart); + touchend = new CustomEvent('touchend', {bubbles: true, composed: true}); + touchend.touches = touchend.changedTouches = touches; + target.dispatchEvent(touchend); + assert.deepEqual(el.taps, ['button#nested', 'x-disabled#disabledEl']); + document.body.removeChild(el); + }); + + test('test all "disablable" elements', function() { + const el = document.createElement('all-disabled'); + document.body.appendChild(el); + el.tapAll(); + assert.deepEqual(el.taps, ['div']); + document.body.removeChild(el); + }) }); });