Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Tools / GardeningServer / ui / ct-router.html
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" 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."
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 children. */
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.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);
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>