Commit bfd9716d authored by stevenjb's avatar stevenjb Committed by Commit bot

MD Settings: Fix subpage navigation focus for bluetooth+internet

This CL:
* Fixes the subpage arrow for bluetooth and focus it correctly.
* Provides focus logic for internet-page -> internet-subpage ->
  internet-detail-page.
* Fixes keyboard navigation to details page from cr-network-list-item

BUG=714350
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:closure_compilation

Review-Url: https://codereview.chromium.org/2841873004
Cr-Commit-Position: refs/heads/master@{#467783}
parent 32d29a10
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
<template> <template>
<style include="settings-shared"> <style include="settings-shared">
</style> </style>
<settings-animated-pages id="pages" section="bluetooth"> <settings-animated-pages id="pages" section="bluetooth"
focus-config="[[focusConfig_]]">
<neon-animatable route-path="default"> <neon-animatable route-path="default">
<div id="bluetoothDevices" <div id="bluetoothDevices"
class="settings-box two-line" actionable on-tap="onTap_"> class="settings-box two-line" actionable on-tap="onTap_">
...@@ -32,7 +33,7 @@ ...@@ -32,7 +33,7 @@
pref="[[prefs.cros.device.allow_bluetooth]]" pref="[[prefs.cros.device.allow_bluetooth]]"
hidden="[[prefs.cros.device.allow_bluetooth.value]]"> hidden="[[prefs.cros.device.allow_bluetooth.value]]">
</cr-policy-pref-indicator> </cr-policy-pref-indicator>
<template is="dom-if" if="[[bluetoothEnabled_]]"> <template is="dom-if" if="[[bluetoothToggleState_]]">
<button class="subpage-arrow" is="paper-icon-button-light" <button class="subpage-arrow" is="paper-icon-button-light"
on-tap="onSubpageArrowTap_" on-tap="onSubpageArrowTap_"
aria-label="$i18n{bluetoothPageTitle}" aria-label="$i18n{bluetoothPageTitle}"
......
...@@ -65,6 +65,18 @@ Polymer({ ...@@ -65,6 +65,18 @@ Polymer({
notify: true, notify: true,
}, },
/** @private {!Map<string, string>} */
focusConfig_: {
type: Object,
value: function() {
var map = new Map();
map.set(
settings.Route.BLUETOOTH_DEVICES.path,
'#bluetoothDevices .subpage-arrow');
return map;
},
},
/** /**
* Interface for bluetooth calls. May be overriden by tests. * Interface for bluetooth calls. May be overriden by tests.
* @type {Bluetooth} * @type {Bluetooth}
......
...@@ -144,6 +144,9 @@ Polymer({ ...@@ -144,6 +144,9 @@ Polymer({
*/ */
networksChangedListener_: null, networksChangedListener_: null,
/** @private {boolean} */
didSetFocus_: false,
/** /**
* settings.RouteObserverBehavior * settings.RouteObserverBehavior
* @param {!settings.Route} route * @param {!settings.Route} route
...@@ -180,6 +183,7 @@ Polymer({ ...@@ -180,6 +183,7 @@ Polymer({
ConnectionState: CrOnc.ConnectionState.NOT_CONNECTED, ConnectionState: CrOnc.ConnectionState.NOT_CONNECTED,
Name: {Active: name}, Name: {Active: name},
}; };
this.didSetFocus_ = false;
this.getNetworkDetails_(); this.getNetworkDetails_();
}, },
...@@ -216,6 +220,16 @@ Polymer({ ...@@ -216,6 +220,16 @@ Polymer({
// Update the detail page title. // Update the detail page title.
this.parentNode.pageTitle = CrOnc.getNetworkName(this.networkProperties); this.parentNode.pageTitle = CrOnc.getNetworkName(this.networkProperties);
// Focus a button once the initial state is set.
if (!this.didSetFocus_) {
this.didSetFocus_ = true;
var button = this.$$('#buttonDiv .primary-button:not([hidden])');
if (!button)
button = this.$$('#buttonDiv .secondary-button:not([hidden])');
assert(button); // At least one button will always be visible.
button.focus();
}
}, },
/** @private */ /** @private */
...@@ -549,7 +563,8 @@ Polymer({ ...@@ -549,7 +563,8 @@ Polymer({
this.networkingPrivate.startActivate(this.guid); this.networkingPrivate.startActivate(this.guid);
}, },
/** @const {string} */ CR_EXPAND_BUTTON_TAG: 'CR-EXPAND-BUTTON', /** @const {string} */
CR_EXPAND_BUTTON_TAG: 'CR-EXPAND-BUTTON',
/** /**
* @param {Event} event * @param {Event} event
......
...@@ -30,7 +30,8 @@ ...@@ -30,7 +30,8 @@
width: 24px; width: 24px;
} }
</style> </style>
<settings-animated-pages id="pages" section="internet"> <settings-animated-pages id="pages" section="internet"
focus-config="[[focusConfig_]]">
<neon-animatable route-path="default"> <neon-animatable route-path="default">
<network-summary default-network="{{defaultNetwork}}" <network-summary default-network="{{defaultNetwork}}"
device-states="{{deviceStates}}" device-states="{{deviceStates}}"
......
...@@ -88,7 +88,18 @@ Polymer({ ...@@ -88,7 +88,18 @@ Polymer({
return []; return [];
} }
}, },
/** @private {!Map<string, string>} */
focusConfig_: {
type: Object,
value: function() {
return new Map();
},
}, },
},
/** @private {string} Type of last detail page visited. */
detailType_: '',
// Element event listeners // Element event listeners
listeners: { listeners: {
...@@ -110,13 +121,13 @@ Polymer({ ...@@ -110,13 +121,13 @@ Polymer({
/** @override */ /** @override */
attached: function() { attached: function() {
this.onExtensionAddedListener_ = this.onExtensionAddedListener_ || this.onExtensionAddedListener_ =
this.onExtensionAdded_.bind(this); this.onExtensionAddedListener_ || this.onExtensionAdded_.bind(this);
chrome.management.onInstalled.addListener(this.onExtensionAddedListener_); chrome.management.onInstalled.addListener(this.onExtensionAddedListener_);
chrome.management.onEnabled.addListener(this.onExtensionAddedListener_); chrome.management.onEnabled.addListener(this.onExtensionAddedListener_);
this.onExtensionRemovedListener_ = this.onExtensionRemovedListener_ || this.onExtensionRemovedListener_ =
this.onExtensionRemoved_.bind(this); this.onExtensionRemovedListener_ || this.onExtensionRemoved_.bind(this);
chrome.management.onUninstalled.addListener( chrome.management.onUninstalled.addListener(
this.onExtensionRemovedListener_); this.onExtensionRemovedListener_);
...@@ -146,9 +157,10 @@ Polymer({ ...@@ -146,9 +157,10 @@ Polymer({
/** /**
* settings.RouteObserverBehavior * settings.RouteObserverBehavior
* @param {!settings.Route} route * @param {!settings.Route} route
* @param {!settings.Route} oldRoute
* @protected * @protected
*/ */
currentRouteChanged: function(route) { currentRouteChanged: function(route, oldRoute) {
if (route == settings.Route.INTERNET_NETWORKS) { if (route == settings.Route.INTERNET_NETWORKS) {
// Handle direct navigation to the networks page, // Handle direct navigation to the networks page,
// e.g. chrome://settings/internet/networks?type=WiFi // e.g. chrome://settings/internet/networks?type=WiFi
...@@ -163,7 +175,29 @@ Polymer({ ...@@ -163,7 +175,29 @@ Polymer({
var type = queryParams.get('type'); var type = queryParams.get('type');
if (type) if (type)
this.knownNetworksType_ = type; this.knownNetworksType_ = type;
} else if (
route != settings.Route.INTERNET && route != settings.Route.BASIC) {
// If we are navigating to a non internet section, do not set focus.
return;
} }
if (!settings.Route.INTERNET.contains(oldRoute))
return;
// Focus the subpage arrow where appropriate.
var selector;
if (route == settings.Route.INTERNET_NETWORKS) {
// iron-list makes the correct timing to focus an item in the list
// very complicated, and the item may not exist, so just focus the
// entire list for now.
selector = '* /deep/ #networkList';
} else if (this.detailType_) {
selector = '* /deep/ #' + this.detailType_ + ' /deep/ .subpage-arrow';
}
if (selector && this.querySelector(selector))
this.focusConfig_.set(oldRoute.path, selector);
else
this.focusConfig_.delete(oldRoute.path);
}, },
/** /**
...@@ -184,6 +218,7 @@ Polymer({ ...@@ -184,6 +218,7 @@ Polymer({
* @private * @private
*/ */
onShowDetail_: function(event) { onShowDetail_: function(event) {
this.detailType_ = event.detail.Type;
var params = new URLSearchParams; var params = new URLSearchParams;
params.append('guid', event.detail.GUID); params.append('guid', event.detail.GUID);
params.append('type', event.detail.Type); params.append('type', event.detail.Type);
...@@ -197,6 +232,7 @@ Polymer({ ...@@ -197,6 +232,7 @@ Polymer({
* @private * @private
*/ */
onShowNetworks_: function(event) { onShowNetworks_: function(event) {
this.detailType_ = event.detail.Type;
var params = new URLSearchParams; var params = new URLSearchParams;
params.append('type', event.detail.Type); params.append('type', event.detail.Type);
this.subpageType_ = event.detail.Type; this.subpageType_ = event.detail.Type;
...@@ -216,6 +252,7 @@ Polymer({ ...@@ -216,6 +252,7 @@ Polymer({
* @private * @private
*/ */
onShowKnownNetworks_: function(event) { onShowKnownNetworks_: function(event) {
this.detailType_ = event.detail.Type;
var params = new URLSearchParams; var params = new URLSearchParams;
params.append('type', event.detail.Type); params.append('type', event.detail.Type);
this.knownNetworksType_ = event.detail.type; this.knownNetworksType_ = event.detail.type;
...@@ -329,8 +366,8 @@ Polymer({ ...@@ -329,8 +366,8 @@ Polymer({
* @private * @private
*/ */
deviceIsEnabled_: function(deviceState) { deviceIsEnabled_: function(deviceState) {
return !!deviceState && deviceState.State == return !!deviceState &&
chrome.networkingPrivate.DeviceStateType.ENABLED; deviceState.State == chrome.networkingPrivate.DeviceStateType.ENABLED;
}, },
/** /**
......
...@@ -47,8 +47,8 @@ Polymer({ ...@@ -47,8 +47,8 @@ Polymer({
/** @override */ /** @override */
created: function() { created: function() {
// Observe the light DOM so we know when it's ready. // Observe the light DOM so we know when it's ready.
this.lightDomObserver_ = Polymer.dom(this).observeNodes( this.lightDomObserver_ =
this.lightDomChanged_.bind(this)); Polymer.dom(this).observeNodes(this.lightDomChanged_.bind(this));
}, },
/** @override */ /** @override */
...@@ -71,13 +71,17 @@ Polymer({ ...@@ -71,13 +71,17 @@ Polymer({
// Only handle iron-select events from neon-animatable elements and the // Only handle iron-select events from neon-animatable elements and the
// given whitelist of settings-subpage instances. // given whitelist of settings-subpage instances.
if (!e.detail.item.matches( var whitelist = 'settings-subpage#site-settings, ' +
'neon-animatable, ' +
'settings-subpage#site-settings, ' +
'settings-subpage[route-path=\"' + 'settings-subpage[route-path=\"' +
settings.Route.SITE_SETTINGS_COOKIES.path + '\"]')) { settings.Route.SITE_SETTINGS_COOKIES.path + '\"]';
// <if expr="chromeos">
whitelist += ', settings-subpage[route-path=\"' +
settings.Route.INTERNET_NETWORKS.path + '\"]';
// </if>
if (!e.detail.item.matches('neon-animatable, ' + whitelist))
return; return;
}
var selector = this.focusConfig.get(this.previousRoute_.path); var selector = this.focusConfig.get(this.previousRoute_.path);
if (selector) { if (selector) {
...@@ -124,8 +128,7 @@ Polymer({ ...@@ -124,8 +128,7 @@ Polymer({
if (!this.queuedRouteChange_) if (!this.queuedRouteChange_)
return; return;
this.async(this.currentRouteChanged.bind( this.async(this.currentRouteChanged.bind(
this, this, this.queuedRouteChange_.newRoute,
this.queuedRouteChange_.newRoute,
this.queuedRouteChange_.oldRoute)); this.queuedRouteChange_.oldRoute));
}, },
...@@ -203,8 +206,8 @@ Polymer({ ...@@ -203,8 +206,8 @@ Polymer({
return; return;
// Set the subpage's id for use by neon-animated-pages. // Set the subpage's id for use by neon-animated-pages.
var subpage = /** @type {{_content: DocumentFragment}} */(template)._content var subpage = /** @type {{_content: DocumentFragment}} */ (template)
.querySelector('settings-subpage'); ._content.querySelector('settings-subpage');
subpage.setAttribute('route-path', routePath); subpage.setAttribute('route-path', routePath);
// Carry over the 'no-search' attribute from the template to the stamped // Carry over the 'no-search' attribute from the template to the stamped
......
...@@ -101,7 +101,8 @@ ...@@ -101,7 +101,8 @@
type="chrome_html" /> type="chrome_html" />
<structure name="IDR_SETTINGS_CR_SETTINGS_ANIMATED_PAGES_JS" <structure name="IDR_SETTINGS_CR_SETTINGS_ANIMATED_PAGES_JS"
file="settings_page/settings_animated_pages.js" file="settings_page/settings_animated_pages.js"
type="chrome_html" /> type="chrome_html"
preprocess="true" />
<structure name="IDR_SETTINGS_APPEARANCE_BROWSER_PROXY_HTML" <structure name="IDR_SETTINGS_APPEARANCE_BROWSER_PROXY_HTML"
file="appearance_page/appearance_browser_proxy.html" file="appearance_page/appearance_browser_proxy.html"
type="chrome_html" /> type="chrome_html" />
......
<link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_network_icon.html"> <link rel="import" href="chrome://resources/cr_elements/network/cr_network_icon.html">
...@@ -87,6 +88,9 @@ ...@@ -87,6 +88,9 @@
<template is="dom-if" <template is="dom-if"
if="[[isSubpageButtonVisible_(networkState, showButtons)]]"> if="[[isSubpageButtonVisible_(networkState, showButtons)]]">
<div id="subpageDiv" class="layout horizontal"> <div id="subpageDiv" class="layout horizontal">
<!-- iron-list captures 'enter' so handle it here explicitly. -->
<iron-a11y-keys keys="enter" on-keys-pressed="fireShowDetails_">
</iron-a11y-keys>
<button class="subpage-arrow" is="paper-icon-button-light" <button class="subpage-arrow" is="paper-icon-button-light"
on-tap="fireShowDetails_" tabindex$="[[tabindex]]" on-tap="fireShowDetails_" tabindex$="[[tabindex]]"
aria-label$="[[ariaLabel]]"> aria-label$="[[ariaLabel]]">
......
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