Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 cr.define('settings', function() { | 5 cr.define('settings', function() { |
| 6 /** | 6 /** |
| 7 * Class for navigable routes. May only be instantiated within this file. | 7 * Class for navigable routes. May only be instantiated within this file. |
| 8 * @constructor | 8 * @constructor |
| 9 * @param {string} path | 9 * @param {string} path |
| 10 * @private | 10 * @private |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 var getRouteForPath = function(path) { | 285 var getRouteForPath = function(path) { |
| 286 // TODO(tommycli): Use Object.values once Closure compilation supports it. | 286 // TODO(tommycli): Use Object.values once Closure compilation supports it. |
| 287 var matchingKey = Object.keys(Route).find(function(key) { | 287 var matchingKey = Object.keys(Route).find(function(key) { |
| 288 return Route[key].path == path; | 288 return Route[key].path == path; |
| 289 }); | 289 }); |
| 290 | 290 |
| 291 return Route[matchingKey] || null; | 291 return Route[matchingKey] || null; |
| 292 }; | 292 }; |
| 293 | 293 |
| 294 /** | 294 /** |
| 295 * The current active route. This may only be updated via the global | 295 * The current active route. This updated only by settings.navigateTo. |
| 296 * function settings.navigateTo. | |
| 297 * @private {!settings.Route} | 296 * @private {!settings.Route} |
| 298 */ | 297 */ |
| 299 var currentRoute_ = (function() { | 298 var currentRoute_ = (function() { |
| 300 var route = getRouteForPath(window.location.pathname); | 299 var route = getRouteForPath(window.location.pathname); |
| 301 if (route) | 300 if (route) |
| 302 return route; | 301 return route; |
| 303 | 302 |
| 304 // Reset the URL path to '/' if the user navigates to a nonexistent URL. | 303 // Reset the URL path to '/' if the user navigates to a nonexistent URL. |
| 305 window.history.replaceState(undefined, '', Route.BASIC.path); | 304 window.history.replaceState({}, '', Route.BASIC.path); |
| 306 return Route.BASIC; | 305 return Route.BASIC; |
| 307 })(); | 306 })(); |
| 308 | 307 |
| 309 /** | 308 /** |
| 309 * The current query parameters. This updated only by settings.navigateTo. | |
| 310 * @private {!Object} | |
|
stevenjb
2016/08/02 22:17:17
Can/should we type this?
tommycli
2016/08/02 22:46:34
Done. I changed it to use the URLSearchParams type
| |
| 311 */ | |
| 312 var currentQueryParameters_ = (function() { | |
| 313 if (window.location.search.length < 2) | |
| 314 return {}; | |
| 315 | |
| 316 var params = {}; | |
| 317 window.location.search.substring(1).split('&').forEach(function(pair) { | |
|
Dan Beam
2016/08/02 21:44:50
OH NO YOU DI'NT
https://developer.mozilla.org/en-
tommycli
2016/08/02 22:46:33
Thanks! I ended up using the URLSearchParams type
| |
| 318 var [key, value] = pair.split('=').map(decodeURIComponent); | |
| 319 params[key] = value; | |
| 320 }); | |
| 321 window.history.replaceState(params, '', currentRoute_.path); | |
| 322 return params; | |
| 323 })(); | |
| 324 | |
| 325 /** | |
| 310 * Helper function to set the current route and notify all observers. | 326 * Helper function to set the current route and notify all observers. |
| 311 * @param {!settings.Route} route | 327 * @param {!settings.Route} route |
| 328 * @param {!Object} queryParameters | |
| 312 */ | 329 */ |
| 313 var setCurrentRoute = function(route) { | 330 var setCurrentRoute = function(route, queryParameters) { |
| 314 currentRoute_ = route; | 331 currentRoute_ = route; |
| 332 currentQueryParameters_ = queryParameters; | |
| 315 for (var observer of routeObservers_) | 333 for (var observer of routeObservers_) |
| 316 observer.currentRouteChanged(); | 334 observer.currentRouteChanged(); |
| 317 }; | 335 }; |
| 318 | 336 |
| 319 /** @return {!settings.Route} */ | 337 /** @return {!settings.Route} */ |
| 320 var getCurrentRoute = function() { return currentRoute_; }; | 338 var getCurrentRoute = function() { return currentRoute_; }; |
| 321 | 339 |
| 340 /** @return {!Object} */ | |
| 341 var getQueryParameters = function() { return currentQueryParameters_; }; | |
| 342 | |
| 322 /** | 343 /** |
| 323 * Navigates to a canonical route and pushes a new history entry. | 344 * Navigates to a canonical route and pushes a new history entry. |
| 324 * @param {!settings.Route} route | 345 * @param {!settings.Route} route |
| 346 * @param {Object=} opt_dynamicParameters A new history entry is always pushed | |
| 347 * when this parameter is truthy, even when the parameters are unchanged. | |
| 325 * @private | 348 * @private |
| 326 */ | 349 */ |
| 327 var navigateTo = function(route) { | 350 var navigateTo = function(route, opt_dynamicParameters) { |
| 328 if (assert(route) == currentRoute_) | 351 if (assert(route) == currentRoute_ && !opt_dynamicParameters) |
| 329 return; | 352 return; |
| 330 | 353 |
| 331 window.history.pushState(undefined, '', route.path); | 354 var queryString = ''; |
| 332 setCurrentRoute(route); | 355 if (opt_dynamicParameters) { |
| 356 queryString = '?' + Object.keys(opt_dynamicParameters).map(function(key) { | |
| 357 var value = opt_dynamicParameters[key]; | |
| 358 assert(typeof value == 'string', | |
| 359 'Non-string dynamic parameter values cannot be correctly ' + | |
| 360 'serialized and deserialized from the URL query string.'); | |
| 361 | |
| 362 return encodeURIComponent(key) + '=' + encodeURIComponent(value); | |
| 363 }).join('&'); | |
| 364 } | |
| 365 | |
| 366 setCurrentRoute(route, opt_dynamicParameters || {}); | |
| 367 window.history.pushState( | |
| 368 currentQueryParameters_, '', route.path + queryString); | |
| 333 }; | 369 }; |
| 334 | 370 |
| 335 window.addEventListener('popstate', function(event) { | 371 window.addEventListener('popstate', function(event) { |
| 336 // On pop state, do not push the state onto the window.history again. | 372 // On pop state, do not push the state onto the window.history again. |
| 337 setCurrentRoute(getRouteForPath(window.location.pathname) || Route.BASIC); | 373 setCurrentRoute(getRouteForPath(window.location.pathname) || Route.BASIC, |
| 374 event.state || {}); | |
| 338 }); | 375 }); |
| 339 | 376 |
| 340 return { | 377 return { |
| 341 Route: Route, | 378 Route: Route, |
| 342 RouteObserverBehavior: RouteObserverBehavior, | 379 RouteObserverBehavior: RouteObserverBehavior, |
| 343 getRouteForPath: getRouteForPath, | 380 getRouteForPath: getRouteForPath, |
| 344 getCurrentRoute: getCurrentRoute, | 381 getCurrentRoute: getCurrentRoute, |
| 382 getQueryParameters: getQueryParameters, | |
| 345 navigateTo: navigateTo, | 383 navigateTo: navigateTo, |
| 346 }; | 384 }; |
| 347 }); | 385 }); |
| OLD | NEW |