2 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
3 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
5 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
6 Code distributed by Google as part of the polymer project is also
7 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9 <link rel=
"import" href=
"../polymer/polymer.html">
11 <link rel=
"import" href=
"more-route-context-aware.html">
12 <link rel=
"import" href=
"route.html">
15 TODO(nevir): Document.
21 is
: 'more-route-selection',
24 MoreRouting
.ContextAware
,
30 * Routes to select from, as either a path expression or route name.
32 * You can either specify routes via this attribute, or as child nodes
33 * to this element, but not both.
35 * @type {String|Array<string|MoreRouting.Route>}
39 observer
: '_routesChanged',
43 * The selected `MoreRouting.Route` object, or `null`.
45 * @type {MoreRouting.Route}
55 * The index of the selected route (relative to `routes`). -1 when there
66 * The _full_ path expression of the selected route, or `null`.
75 * The params of the selected route, or an empty object if no route.
86 * @event more-route-change fires when a new route is selected.
88 * newRoute: MoreRouting.Route, oldRoute: MoreRouting.Route,
89 * newIndex: number, oldIndex: number,
90 * newPath: ?string, oldPath: ?string,
91 * newParams: Object, oldParams: Object,
95 routingReady: function() {
96 this._routesChanged();
99 _routesChanged: function() {
100 if (!this.routingIsReady
) return;
101 var routes
= this.routes
|| [];
102 if (typeof routes
=== 'string') {
103 routes
= routes
.split(/\s+/);
105 this._routeInfo
= this._sortIndexes(routes
.map(function(route
, index
) {
107 model
: MoreRouting
.getRoute(route
, this.parentRoute
),
112 this._observeRoutes();
117 * Tracks changes to the routes.
119 _observeRoutes: function() {
120 if (this._routeListeners
) {
121 for (var i
= 0, listener
; listener
= this._routeListeners
[i
]; i
++) {
126 this._routeListeners
= this._routeInfo
.map(function(routeInfo
) {
127 return routeInfo
.model
.__subscribe(this._evaluate
.bind(this));
131 _evaluate: function() {
134 var oldIndex
= this.selectedIndex
;
136 for (var i
= 0, routeInfo
; routeInfo
= this._routeInfo
[i
]; i
++) {
137 if (routeInfo
.model
&& routeInfo
.model
.active
) {
138 newIndex
= routeInfo
.index
;
139 newRoute
= routeInfo
.model
;
143 if (newIndex
=== oldIndex
) return;
145 var oldRoute
= this.selectedRoute
;
146 var oldPath
= this.selectedPath
;
147 var oldParams
= this.selectedParams
;
149 var newPath
= newRoute
? newRoute
.fullPath
: null;
150 var newParams
= newRoute
? newRoute
.params
: {};
152 this._setSelectedRoute(newRoute
);
153 this._setSelectedIndex(newIndex
);
154 this._setSelectedPath(newPath
);
155 this._setSelectedParams(newParams
);
157 this.fire('more-route-change', {
158 newRoute
: newRoute
, oldRoute
: oldRoute
,
159 newIndex
: newIndex
, oldIndex
: oldIndex
,
160 newPath
: newPath
, oldPath
: oldPath
,
161 newParams
: newParams
, oldParams
: oldParams
,
165 * We want the most specific routes to match first, so we must create a
166 * mapping of indexes within `routes` that map
168 _sortIndexes: function(routeInfo
) {
169 return routeInfo
.sort(function(a
, b
) {
172 } else if (!b
.model
) {
174 // Routes with more path parts are most definitely more specific.
175 } else if (a
.model
.depth
< b
.model
.depth
) {
177 } if (a
.model
.depth
> b
.model
.depth
) {
181 // Also, routes with fewer params are more specific. For example
182 // `/users/foo` is more specific than `/users/:id`.
183 if (a
.model
.numParams
< b
.model
.numParams
) {
185 } else if (a
.model
.numParams
> b
.model
.numParams
) {
188 // Equally specific; we fall back to the default (and hopefully
189 // stable) sort order.