Commit 72e1b53f authored by Anand K. Mistry's avatar Anand K. Mistry Committed by Commit Bot

Use 'pointerdown' instead of 'mousedown' in cr-searchable-dropdown

IronScrollManager, used by the iron-dropdown element, is capturing
'touchstart' events and canceling the default action when touching
outside the dropdown. This is causing the 'mousedown' event to be
suppressed, preventing the 'mousedown' listener from working on
touchscreens. Listening for the 'pointerdown' event instead bypasses
this issue since the event does not appear to be canceled like
'mousedown'.

Bug: 1004984
Change-Id: I23dbd203baffcdd9b9f9b61a58adf7b930cfe4da
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1847459
Commit-Queue: Anand Mistry <amistry@chromium.org>
Reviewed-by: default avatarDemetrios Papadopoulos <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704937}
parent 72a444b4
...@@ -52,6 +52,15 @@ suite('cr-searchable-drop-down', function() { ...@@ -52,6 +52,15 @@ suite('cr-searchable-drop-down', function() {
MockInteractions.keyDownOn(searchInput, 'Tab', [], 'Tab'); MockInteractions.keyDownOn(searchInput, 'Tab', [], 'Tab');
} }
function pointerDown(element) {
element.dispatchEvent(new PointerEvent('pointerdown', {
bubbles: true,
cancelable: true,
composed: true,
buttons: 1,
}));
}
function getSelectedElement() { function getSelectedElement() {
return dropDown.shadowRoot.querySelector('[selected_]'); return dropDown.shadowRoot.querySelector('[selected_]');
} }
...@@ -152,7 +161,7 @@ suite('cr-searchable-drop-down', function() { ...@@ -152,7 +161,7 @@ suite('cr-searchable-drop-down', function() {
assertTrue(dropDown.$$('iron-dropdown').opened); assertTrue(dropDown.$$('iron-dropdown').opened);
assertNotEquals('dog', dropDown.value); assertNotEquals('dog', dropDown.value);
MockInteractions.downAndUp(outsideElement, null, null); pointerDown(outsideElement);
assertNotEquals('dog', dropDown.value); assertNotEquals('dog', dropDown.value);
assertFalse(dropDown.$$('iron-dropdown').opened); assertFalse(dropDown.$$('iron-dropdown').opened);
}); });
......
...@@ -97,15 +97,18 @@ Polymer({ ...@@ -97,15 +97,18 @@ Polymer({
'mousemove': 'onMouseMove_', 'mousemove': 'onMouseMove_',
}, },
/** @private {number} */
openDropdownTimeoutId_: 0,
/** @override */ /** @override */
attached: function() { attached: function() {
this.mouseDownListener_ = this.onMouseDown_.bind(this); this.pointerDownListener_ = this.onPointerDown_.bind(this);
document.addEventListener('mousedown', this.mouseDownListener_); document.addEventListener('pointerdown', this.pointerDownListener_);
}, },
/** @override */ /** @override */
detached: function() { detached: function() {
document.removeEventListener('mousedown', this.mouseDownListener_); document.removeEventListener('pointerdown', this.pointerDownListener_);
}, },
/** /**
...@@ -131,10 +134,29 @@ Polymer({ ...@@ -131,10 +134,29 @@ Polymer({
/** @private */ /** @private */
closeDropdown_: function() { closeDropdown_: function() {
if (this.openDropdownTimeoutId_) {
clearTimeout(this.openDropdownTimeoutId_);
}
this.$$('iron-dropdown').close(); this.$$('iron-dropdown').close();
this.opened_ = false; this.opened_ = false;
}, },
/**
* Enqueues a task to open the iron-dropdown. Any pending task is canceled and
* a new task is enqueued.
* @private
*/
enqueueOpenDropdown_: function() {
if (this.opened_) {
return;
}
if (this.openDropdownTimeoutId_) {
clearTimeout(this.openDropdownTimeoutId_);
}
this.openDropdownTimeoutId_ = setTimeout(this.openDropdown_.bind(this));
},
/** /**
* @param {!Array<string>} oldValue * @param {!Array<string>} oldValue
* @param {!Array<string>} newValue * @param {!Array<string>} newValue
...@@ -184,7 +206,7 @@ Polymer({ ...@@ -184,7 +206,7 @@ Polymer({
* @param {!Event} event * @param {!Event} event
* @private * @private
*/ */
onMouseDown_: function(event) { onPointerDown_: function(event) {
if (this.readonly) { if (this.readonly) {
return; return;
} }
...@@ -199,8 +221,12 @@ Polymer({ ...@@ -199,8 +221,12 @@ Polymer({
// Prevent any other field from gaining focus due to this event. // Prevent any other field from gaining focus due to this event.
event.preventDefault(); event.preventDefault();
} else if (paths.includes(searchInput)) { } else if (paths.includes(searchInput)) {
// A click on the search input should open the dropdown. // A click on the search input should open the dropdown. Opening the
this.openDropdown_(); // dropdown is done on a new task because when the IronDropdown element is
// opened, it may capture and cancel the touch event, preventing the
// searchInput field from receiving focus. Replacing iron-dropdown
// (crbug.com/1013408) will eliminate the need for this work around.
this.enqueueOpenDropdown_();
} else { } else {
// A click outside either the search input or dropdown should close the // A click outside either the search input or dropdown should close the
// dropdown. Implicitly, the search input has lost focus at this point. // dropdown. Implicitly, the search input has lost focus at this point.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment