OLD | NEW |
| (Empty) |
1 <!-- | |
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. | |
5 --> | |
6 | |
7 <!-- | |
8 Handles navigations by showing the appropriate ct-view. Use the "default" attrib
ute 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, withou
t changing the actual URL. | |
12 Gives the app a "landing page." | |
13 --> | |
14 <polymer-element name="ct-router" attributes="pathPrefix defaultPath"> | |
15 <template> | |
16 <style> | |
17 :host { | |
18 display: block; | |
19 /* Position the container so it captures its absolutely postioned childr
en. */ | |
20 position: relative; | |
21 } | |
22 </style> | |
23 <content select="ct-view"></content> | |
24 </template> | |
25 <script> | |
26 Polymer('ct-router', { | |
27 activeView: null, | |
28 pathPrefix: '', | |
29 currentPath: '', | |
30 defaultPath: '/', | |
31 | |
32 created: function() { | |
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 + '/'; | |
37 }, | |
38 | |
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 | |
42 // for those tabs. | |
43 setTimeout(this._replaceInitialUrl.bind(this), 0); | |
44 window.addEventListener('popstate', this._routeChanged); | |
45 document.addEventListener('navigate', this._handleNavigate); | |
46 | |
47 this.defaultView = this.querySelector('ct-view[default]'); | |
48 if (!this.defaultView) | |
49 this.defaultView = this.querySelector('ct-view'); | |
50 }, | |
51 | |
52 detached: function() { | |
53 window.removeEventListener('popstate', this._routeChanged); | |
54 document.removeEventListener('navigate', this._handleNavigate); | |
55 }, | |
56 | |
57 _replaceInitialUrl: function() { | |
58 var url = window.location.pathname + window.location.search + window.loc
ation.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); | |
64 this._routeChanged(); | |
65 }, | |
66 | |
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); | |
71 }, | |
72 | |
73 _routeChanged: function() { | |
74 var path = window.location.pathname; | |
75 if (path == this.currentPath) | |
76 return; | |
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); | |
81 if (!nextView) | |
82 continue; | |
83 this._swapViews(nextView); | |
84 return; | |
85 } | |
86 this._swapViews(this.defaultView.showView(this.defaultPath)); | |
87 }, | |
88 | |
89 _swapViews: function(nextView) { | |
90 if (this.activeView) | |
91 this.activeView.hidden = true; | |
92 this.activeView = nextView; | |
93 this.activeView.hidden = false; | |
94 } | |
95 }); | |
96 </script> | |
97 </polymer-element> | |
OLD | NEW |