Commit ca625808 authored by Gavin Williams's avatar Gavin Williams Committed by Commit Bot

Close dropdown on blur

Using on-blur simplifies closing the dropdown for clicks registered
outside of print preview. And now that we don't have to specifically
listen for clicks outside of print preview, on-click can be used
instead of pointerdown.

Bug: 1059607
Change-Id: I9225ec9e06e3197b9f2eae4ac078b29fa232a791
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2303368
Commit-Queue: Gavin Williams <gavinwill@chromium.org>
Reviewed-by: default avatarRebekah Potter <rbpotter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790384}
parent 68425b08
...@@ -100,7 +100,8 @@ ...@@ -100,7 +100,8 @@
width: 100%; width: 100%;
} }
</style> </style>
<div id="destination-dropdown" on-keydown="onKeyDown_" tabindex="0"> <div id="destination-dropdown" on-keydown="onKeyDown_" tabindex="0"
on-blur="onBlur_" on-click="onClick_">
<div id="destination-display-container"> <div id="destination-display-container">
<div id="destination-icon-box"> <div id="destination-icon-box">
<iron-icon icon="[[destinationIcon]]" <iron-icon icon="[[destinationIcon]]"
...@@ -122,7 +123,7 @@ ...@@ -122,7 +123,7 @@
<div slot="dropdown-content"> <div slot="dropdown-content">
<template is="dom-repeat" items="[[itemList]]"> <template is="dom-repeat" items="[[itemList]]">
<button id="[[item.key]]" tabindex="-1" value="[[item.key]]" <button id="[[item.key]]" tabindex="-1" value="[[item.key]]"
on-click="onSelect_" on-click="onSelect_" on-blur="onBlur_"
class$="list-item [[getHighlightedClass_(item.key, class$="list-item [[getHighlightedClass_(item.key,
highlightedIndex_)]]"> highlightedIndex_)]]">
<printer-status-icon-cros icon-location="[[IconLocation.DROPDOWN]]" <printer-status-icon-cros icon-location="[[IconLocation.DROPDOWN]]"
...@@ -134,25 +135,25 @@ ...@@ -134,25 +135,25 @@
</button> </button>
</template> </template>
<button on-click="onSelect_" tabindex="-1" value="[[pdfDestinationKey]]" <button on-click="onSelect_" tabindex="-1" value="[[pdfDestinationKey]]"
hidden$="[[pdfPrinterDisabled]]" hidden$="[[pdfPrinterDisabled]]" on-blur="onBlur_"
class$="list-item [[getHighlightedClass_(pdfDestinationKey, class$="list-item [[getHighlightedClass_(pdfDestinationKey,
highlightedIndex_)]]"> highlightedIndex_)]]">
$i18n{printToPDF} $i18n{printToPDF}
</button> </button>
<button on-click="onSelect_" tabindex="-1" <button on-click="onSelect_" tabindex="-1" on-blur="onBlur_"
value="[[driveDestinationKey]]" hidden$="[[!driveDestinationKey]]" value="[[driveDestinationKey]]" hidden$="[[!driveDestinationKey]]"
class$="list-item [[getHighlightedClass_(driveDestinationKey, class$="list-item [[getHighlightedClass_(driveDestinationKey,
highlightedIndex_)]]"> highlightedIndex_)]]">
$i18n{printToGoogleDrive} $i18n{printToGoogleDrive}
</button> </button>
<button on-click="onSelect_" tabindex="-1" value="noDestinations" <button on-click="onSelect_" tabindex="-1" value="noDestinations"
hidden$="[[!noDestinations]]" hidden$="[[!noDestinations]]" on-blur="onBlur_"
class$="list-item [[getHighlightedClass_('noDestinations', class$="list-item [[getHighlightedClass_('noDestinations',
highlightedIndex_)]]"> highlightedIndex_)]]">
$i18n{noDestinationsMessage} $i18n{noDestinationsMessage}
</button> </button>
<button on-click="onSelect_" tabindex="-1" value="seeMore" <button on-click="onSelect_" tabindex="-1" value="seeMore"
aria-label$="[[i18n(seeMoreDestinationsLabel)]]" aria-label$="[[i18n(seeMoreDestinationsLabel)]]" on-blur="onBlur_"
class$="list-item [[getHighlightedClass_('seeMore', class$="list-item [[getHighlightedClass_('seeMore',
highlightedIndex_)]]"> highlightedIndex_)]]">
$i18n{seeMore} $i18n{seeMore}
......
...@@ -68,17 +68,10 @@ Polymer({ ...@@ -68,17 +68,10 @@ Polymer({
/** @override */ /** @override */
attached() { attached() {
this.pointerDownListener_ = event => this.onPointerDown_(event);
document.addEventListener('pointerdown', this.pointerDownListener_);
this.updateTabIndex_(); this.updateTabIndex_();
this.IconLocation = IconLocation; this.IconLocation = IconLocation;
}, },
/** @override */
detached() {
document.removeEventListener('pointerdown', this.pointerDownListener_);
},
/** /**
* Enqueues a task to refit the iron-dropdown if it is open. * Enqueues a task to refit the iron-dropdown if it is open.
* @private * @private
...@@ -130,28 +123,20 @@ Polymer({ ...@@ -130,28 +123,20 @@ Polymer({
this.highlightedIndex_ = this.getButtonListFromDropdown_().indexOf(item); this.highlightedIndex_ = this.getButtonListFromDropdown_().indexOf(item);
}, },
/** /** @private */
* @param {!Event} event onClick_(event) {
* @private
*/
onPointerDown_(event) {
const paths = event.composedPath();
const dropdown = const dropdown =
/** @type {!IronDropdownElement} */ (this.$$('iron-dropdown')); /** @type {!IronDropdownElement} */ (this.$$('iron-dropdown'));
const destinationDropdown =
/** @type {!Element} */ (this.$$('#destination-dropdown'));
// Exit if path includes |dropdown| because event will be handled by // Exit if path includes |dropdown| because event will be handled by
// onSelect_. // onSelect_.
if (paths.includes(dropdown)) { if (event.composedPath().includes(dropdown)) {
return; return;
} }
if (!paths.includes(destinationDropdown) || dropdown.opened) { if (dropdown.opened) {
this.closeDropdown_(); this.closeDropdown_();
return; return;
} }
this.openDropdown_(); this.openDropdown_();
}, },
...@@ -171,9 +156,6 @@ Polymer({ ...@@ -171,9 +156,6 @@ Polymer({
event.stopPropagation(); event.stopPropagation();
const dropdown = this.$$('iron-dropdown'); const dropdown = this.$$('iron-dropdown');
switch (event.code) { switch (event.code) {
case 'Tab':
this.closeDropdown_();
break;
case 'ArrowUp': case 'ArrowUp':
case 'ArrowDown': case 'ArrowDown':
this.onArrowKeyPress_(event.code); this.onArrowKeyPress_(event.code);
...@@ -307,4 +289,17 @@ Polymer({ ...@@ -307,4 +289,17 @@ Polymer({
'highlighted' : 'highlighted' :
''; '';
}, },
/**
* Close the dropdown when focus is lost except when an item in the dropdown
* is the element that received the focus.
* @param {!Event} event
* @private
*/
onBlur_(event) {
if (!this.getButtonListFromDropdown_().includes(
/** @type {!Element} */ (event.relatedTarget))) {
this.closeDropdown_();
}
},
}); });
...@@ -20,7 +20,6 @@ destination_dropdown_cros_test.suiteName = ...@@ -20,7 +20,6 @@ destination_dropdown_cros_test.suiteName =
destination_dropdown_cros_test.TestNames = { destination_dropdown_cros_test.TestNames = {
CorrectListItems: 'correct list items', CorrectListItems: 'correct list items',
ClickCloses: 'click closes dropdown', ClickCloses: 'click closes dropdown',
TabCloses: 'tab closes dropdown',
HighlightedAfterUpDown: 'highlighted after keyboard press up and down', HighlightedAfterUpDown: 'highlighted after keyboard press up and down',
DestinationChangeAfterUpDown: DestinationChangeAfterUpDown:
'destination changes after keyboard press up and down', 'destination changes after keyboard press up and down',
...@@ -48,22 +47,17 @@ suite(destination_dropdown_cros_test.suiteName, function() { ...@@ -48,22 +47,17 @@ suite(destination_dropdown_cros_test.suiteName, function() {
} }
function clickDropdown() { function clickDropdown() {
dropdown.$$('#destination-dropdown') dropdown.$$('#destination-dropdown').click();
.dispatchEvent(new PointerEvent('pointerdown', { }
bubbles: true,
cancelable: true, function clickDropdownFocus() {
composed: true, dropdown.$$('#destination-dropdown').click();
buttons: 1, dropdown.$$('#destination-dropdown').focus();
}));
} }
function clickOutsideDropdown() { function clickOutsideDropdown() {
document.body.dispatchEvent(new PointerEvent('pointerdown', { document.body.click();
bubbles: true, dropdown.$$('#destination-dropdown').blur();
cancelable: true,
composed: true,
buttons: 1,
}));
} }
function down() { function down() {
...@@ -79,10 +73,6 @@ suite(destination_dropdown_cros_test.suiteName, function() { ...@@ -79,10 +73,6 @@ suite(destination_dropdown_cros_test.suiteName, function() {
keyDownOn(dropdown.$$('#destination-dropdown'), 'Enter', [], 'Enter'); keyDownOn(dropdown.$$('#destination-dropdown'), 'Enter', [], 'Enter');
} }
function tab() {
keyDownOn(dropdown.$$('#destination-dropdown'), 'Tab', [], 'Tab');
}
/** @return {?Element} */ /** @return {?Element} */
function getHighlightedElement() { function getHighlightedElement() {
return dropdown.$$('.highlighted'); return dropdown.$$('.highlighted');
...@@ -140,33 +130,21 @@ suite(destination_dropdown_cros_test.suiteName, function() { ...@@ -140,33 +130,21 @@ suite(destination_dropdown_cros_test.suiteName, function() {
dropdown.value = destinationOne; dropdown.value = destinationOne;
const ironDropdown = dropdown.$$('iron-dropdown'); const ironDropdown = dropdown.$$('iron-dropdown');
clickDropdown(); clickDropdownFocus();
assertTrue(ironDropdown.opened); assertTrue(ironDropdown.opened);
getList()[0].click(); getList()[0].click();
assertFalse(ironDropdown.opened); assertFalse(ironDropdown.opened);
clickDropdown(); clickDropdownFocus();
assertTrue(ironDropdown.opened); assertTrue(ironDropdown.opened);
// Click outside dropdown to close the dropdown. // Clicking outside the dropdown will cause it to lose focus and close.
// This will verify on-blur closes the dropdown.
clickOutsideDropdown(); clickOutsideDropdown();
assertFalse(ironDropdown.opened); assertFalse(ironDropdown.opened);
}); });
test(assert(destination_dropdown_cros_test.TestNames.TabCloses), function() {
const destinationOne = createDestination('One', DestinationOrigin.CROS);
setItemList([destinationOne]);
dropdown.value = destinationOne;
const ironDropdown = dropdown.$$('iron-dropdown');
clickDropdown();
assertTrue(ironDropdown.opened);
tab();
assertFalse(ironDropdown.opened);
});
test( test(
assert(destination_dropdown_cros_test.TestNames.HighlightedAfterUpDown), assert(destination_dropdown_cros_test.TestNames.HighlightedAfterUpDown),
function() { function() {
......
...@@ -181,3 +181,23 @@ TEST_F( ...@@ -181,3 +181,23 @@ TEST_F(
this.runMochaTest( this.runMochaTest(
scaling_settings_interactive_test.TestNames.AutoFocusInput); scaling_settings_interactive_test.TestNames.AutoFocusInput);
}); });
GEN('#if defined(OS_CHROMEOS)');
// eslint-disable-next-line no-var
var PrintPreviewDestinationDropdownCrosTest =
class extends PrintPreviewInteractiveUITest {
/** @override */
get browsePreload() {
return 'chrome://print/test_loader.html?module=print_preview/destination_dropdown_cros_test.js';
}
/** @override */
get suiteName() {
return destination_dropdown_cros_test.suiteName;
}
};
TEST_F('PrintPreviewDestinationDropdownCrosTest', 'ClickCloses', function() {
this.runMochaTest(destination_dropdown_cros_test.TestNames.ClickCloses);
});
GEN('#endif');
...@@ -1142,14 +1142,6 @@ TEST_F( ...@@ -1142,14 +1142,6 @@ TEST_F(
destination_dropdown_cros_test.TestNames.CorrectListItems); destination_dropdown_cros_test.TestNames.CorrectListItems);
}); });
TEST_F('PrintPreviewDestinationDropdownCrosTest', 'ClickCloses', function() {
this.runMochaTest(destination_dropdown_cros_test.TestNames.ClickCloses);
});
TEST_F('PrintPreviewDestinationDropdownCrosTest', 'TabCloses', function() {
this.runMochaTest(destination_dropdown_cros_test.TestNames.TabCloses);
});
TEST_F( TEST_F(
'PrintPreviewDestinationDropdownCrosTest', 'HighlightedAfterUpDown', 'PrintPreviewDestinationDropdownCrosTest', 'HighlightedAfterUpDown',
function() { function() {
......
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