2 Copyright 2014 The Chromium Authors. All rights reserved.
3 Use of this source code is governed by a BSD-style license that can be
4 found in the LICENSE file.
8 Handles navigations by showing the appropriate ct-view. Use the "default" attribute on a ct-view to show
9 that view when no view matches the current path.
10 pathPrefix: The prefix of the path that is not used for navigation, if any.
11 defaultPath: If specified, the root URL will be routed using defaultPath, without changing the actual URL.
12 Gives the app a "landing page."
14 <polymer-element name="ct-router" attributes="pathPrefix defaultPath">
19 /* Position the container so it captures its absolutely postioned children. */
23 <content select="ct-view"></content>
26 Polymer('ct-router', {
33 this._routeChanged = this._routeChanged.bind(this);
34 this._handleNavigate = this._handleNavigate.bind(this);
35 // This ensures we can run from any subdirectory.
36 this.pathPrefix = document.location.pathname + '/';
39 attached: function() {
40 // Use setTimeout instead of this.async since raf won't fire in
41 // background tabs and we want to bootstrap the inital view even
43 setTimeout(this._replaceInitialUrl.bind(this), 0);
44 window.addEventListener('popstate', this._routeChanged);
45 document.addEventListener('navigate', this._handleNavigate);
47 this.defaultView = this.querySelector('ct-view[default]');
48 if (!this.defaultView)
49 this.defaultView = this.querySelector('ct-view');
52 detached: function() {
53 window.removeEventListener('popstate', this._routeChanged);
54 document.removeEventListener('navigate', this._handleNavigate);
57 _replaceInitialUrl: function() {
58 var url = window.location.pathname + window.location.search + window.location.hash;
59 if (url.startsWith(this.pathPrefix))
60 url = url.replace(this.pathPrefix, '');
61 // Multiple slashes at the beginning of the URL would be interpreted as another domain.
62 url = url.replace(/^\/\/+/, '/');
63 window.history.replaceState(null, null, url);
67 _handleNavigate: function(event) {
68 var historyFn = event.detail.replaceState ? window.history.replaceState : window.history.pushState;
69 historyFn.call(window.history, null, null, event.detail.url);
70 this.async(this._routeChanged);
73 _routeChanged: function() {
74 var path = window.location.pathname;
75 if (path == this.currentPath)
77 this.currentPath = path;
78 var views = this.querySelectorAll('ct-view').array();
79 for (var i = 0; i < views.length; ++i) {
80 var nextView = views[i].showView(path);
83 this._swapViews(nextView);
86 this._swapViews(this.defaultView.showView(this.defaultPath));
89 _swapViews: function(nextView) {
91 this.activeView.hidden = true;
92 this.activeView = nextView;
93 this.activeView.hidden = false;