Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: chrome/browser/resources/settings/settings_page/settings_router.js

Issue 2156413002: Settings Router Refactor: Migrate to settings.Route.navigateTo calls. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix chromeos tests Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @typedef {{
7 * dialog: (string|undefined),
8 * page: string,
9 * section: string,
10 * subpage: !Array<string>,
11 * }}
12 */
13 var SettingsRoute;
14
15 /** @typedef {SettingsRoute|{url: string}} */
16 var CanonicalRoute;
17
18 /** @typedef {SettingsRoute|{inHistory: boolean}} */
19 var HistoricRoute;
20
21 /**
22 * @fileoverview 6 * @fileoverview
23 * 'settings-router' is a simple router for settings. Its responsibilities: 7 * 'settings-router' is a simple router for settings. Its responsibilities:
24 * - Update the URL when the routing state changes. 8 * - Update the URL when the routing state changes.
25 * - Initialize the routing state with the initial URL. 9 * - Initialize the routing state with the initial URL.
26 * - Process and validate all routing state changes. 10 * - Process and validate all routing state changes.
27 * 11 *
28 * Example: 12 * Example:
29 * 13 *
30 * <settings-router current-route="{{currentRoute}}"> 14 * <settings-router current-route="{{currentRoute}}">
31 * </settings-router> 15 * </settings-router>
32 */ 16 */
33 Polymer({ 17 Polymer({
34 is: 'settings-router', 18 is: 'settings-router',
35 19
36 properties: { 20 properties: {
37 /** 21 /**
38 * The current active route. This is reflected to the URL. Updates to this 22 * The current active route. This may only be updated via the global
39 * property should replace the whole object. 23 * function settings.navigateTo.
40 * 24 *
41 * currentRoute.page refers to top-level pages such as Basic and Advanced. 25 * currentRoute.page refers to top-level pages such as Basic and Advanced.
42 * 26 *
43 * currentRoute.section is only non-empty when the user is on a subpage. If 27 * currentRoute.section is only non-empty when the user is on a subpage. If
44 * the user is on Basic, for instance, this is an empty string. 28 * the user is on Basic, for instance, this is an empty string.
45 * 29 *
46 * currentRoute.subpage is an Array. The last element is the actual subpage 30 * currentRoute.subpage is an Array. The last element is the actual subpage
47 * the user is on. The previous elements are the ancestor subpages. This 31 * the user is on. The previous elements are the ancestor subpages. This
48 * enables support for multiple paths to the same subpage. This is used by 32 * enables support for multiple paths to the same subpage. This is used by
49 * both the Back button and the Breadcrumb to determine ancestor subpages. 33 * both the Back button and the Breadcrumb to determine ancestor subpages.
50 * @type {SettingsRoute} 34 * @type {!settings.Route}
51 */ 35 */
52 currentRoute: { 36 currentRoute: {
53 notify: true, 37 notify: true,
54 observer: 'currentRouteChanged_',
55 type: Object, 38 type: Object,
56 value: function() { 39 value: function() {
57 var initialRoute = this.canonicalRoutes_[0]; 40 return this.getRouteFor_(window.location.pathname);
58
59 // Take the current URL, find a matching pre-defined route, and
60 // initialize the currentRoute to that pre-defined route.
61 for (var i = 0; i < this.canonicalRoutes_.length; ++i) {
62 var canonicalRoute = this.canonicalRoutes_[i];
63 if (canonicalRoute.url == window.location.pathname) {
64 initialRoute = canonicalRoute;
65 break;
66 }
67 }
68
69 return {
70 page: initialRoute.page,
71 section: initialRoute.section,
72 subpage: initialRoute.subpage,
73 dialog: initialRoute.dialog,
74 };
75 },
76 },
77
78 /**
79 * Page titles for the currently active route. Updated by the currentRoute
80 * property observer.
81 * @type {{pageTitle: string}}
82 */
83 currentRouteTitles: {
84 notify: true,
85 type: Object,
86 value: function() {
87 return {
88 pageTitle: '',
89 };
90 }, 41 },
91 }, 42 },
92 }, 43 },
93 44
94
95 /**
96 * @private {!Array<!CanonicalRoute>}
97 * The 'url' property is not accessible to other elements.
98 */
99 canonicalRoutes_: Object.keys(settings.Route).map(function(key) {
100 return settings.Route[key];
101 }),
102
103 /** 45 /**
104 * Sets up a history popstate observer. 46 * Sets up a history popstate observer.
47 * @override
105 */ 48 */
106 created: function() { 49 created: function() {
107 window.addEventListener('popstate', function(event) { 50 window.addEventListener('popstate', function(event) {
108 if (event.state && event.state.page) 51 // On pop state, do not push the state onto the window.history again.
109 this.currentRoute = event.state; 52 this.currentRoute = this.getRouteFor_(window.location.pathname);
110 }.bind(this)); 53 }.bind(this));
54
55 assert(!settings.navigateTo,
56 'settings.navigateTo already defined. There may only be one ' +
michaelpg 2016/07/20 19:48:23 using another namespace to enforce a singleton see
tommycli 2016/07/20 20:33:30 Well... the intent is to really prevent the global
57 'instance of settings-router.');
58 settings.navigateTo = this.navigateTo_.bind(this);
111 }, 59 },
112 60
113 /** 61 /**
114 * Is called when another element modifies the route. This observer validates 62 * Returns the matching canonical route, or the default route if none matches.
115 * the route change against the pre-defined list of routes, and updates the 63 * @param {string} path
116 * URL appropriately. 64 * @return {!settings.Route}
117 * @param {!SettingsRoute} newRoute Where we're headed.
118 * @param {!SettingsRoute|undefined} oldRoute Where we've been.
119 * @private 65 * @private
120 */ 66 */
121 currentRouteChanged_: function(newRoute, oldRoute) { 67 getRouteFor_: function(path) {
122 for (var i = 0; i < this.canonicalRoutes_.length; ++i) { 68 var matchingKeys = Object.keys(settings.Route).filter(function(key) {
michaelpg 2016/07/20 19:48:23 .find
tommycli 2016/07/20 20:33:30 Done.
123 var canonicalRoute = this.canonicalRoutes_[i]; 69 return settings.Route[key].url == path;
124 if (canonicalRoute.page == newRoute.page && 70 });
125 canonicalRoute.section == newRoute.section &&
126 canonicalRoute.dialog == newRoute.dialog &&
127 canonicalRoute.subpage.length == newRoute.subpage.length &&
128 canonicalRoute.subpage.every(function(value, index) {
129 return value == newRoute.subpage[index];
130 })) {
131 // Update the property containing the titles for the current route.
132 this.currentRouteTitles = {
133 pageTitle: loadTimeData.getString(canonicalRoute.page + 'PageTitle'),
134 };
135 71
136 // If we are restoring a state from history, don't push it again. 72 if (matchingKeys.length == 0)
137 if (/** @type {HistoricRoute} */(newRoute).inHistory) 73 return settings.Route.BASIC;
138 return;
139 74
140 // Mark routes persisted in history as already stored in history. 75 assert(matchingKeys.length == 1, 'Duplicate routes for: ' + path);
michaelpg 2016/07/20 19:48:23 rely on testing for this instead
tommycli 2016/07/20 20:33:30 Done.
141 var historicRoute = /** @type {HistoricRoute} */({ 76 return settings.Route[matchingKeys[0]];
142 inHistory: true, 77 },
143 page: newRoute.page,
144 section: newRoute.section,
145 subpage: newRoute.subpage,
146 dialog: newRoute.dialog,
147 });
148 78
149 // Push the current route to the history state, so when the user 79 /**
150 // navigates with the browser back button, we can recall the route. 80 * Navigates to a canonical route.
151 if (oldRoute) { 81 * @param {!settings.Route} route
152 window.history.pushState(historicRoute, document.title, 82 * @private
153 canonicalRoute.url); 83 */
154 } else { 84 navigateTo_: function(route) {
155 // For the very first route (oldRoute will be undefined), we replace 85 window.history.pushState(undefined, document.title, route.url);
156 // the existing state instead of pushing a new one. This is to allow 86 this.currentRoute = route;
157 // the user to use the browser back button to exit Settings entirely.
158 window.history.replaceState(historicRoute, document.title);
159 }
160
161 return;
162 }
163 }
164
165 assertNotReached('Route not found: ' + JSON.stringify(newRoute));
166 }, 87 },
167 }); 88 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698