3 is: 'more-route-selection',
6 MoreRouting.ContextAware,
12 * Routes to select from, as either a path expression or route name.
14 * You can either specify routes via this attribute, or as child nodes
15 * to this element, but not both.
17 * @type {String|Array<string|MoreRouting.Route>}
21 observer: '_routesChanged',
25 * The selected `MoreRouting.Route` object, or `null`.
27 * @type {MoreRouting.Route}
37 * The index of the selected route (relative to `routes`). -1 when there
48 * The _full_ path expression of the selected route, or `null`.
57 * The params of the selected route, or an empty object if no route.
68 * @event more-route-change fires when a new route is selected.
70 * newRoute: MoreRouting.Route, oldRoute: MoreRouting.Route,
71 * newIndex: number, oldIndex: number,
72 * newPath: ?string, oldPath: ?string,
73 * newParams: Object, oldParams: Object,
77 routingReady: function() {
78 this._routesChanged();
81 _routesChanged: function() {
82 if (!this.routingIsReady) return;
83 var routes = this.routes || [];
84 if (typeof routes === 'string') {
85 routes = routes.split(/\s+/);
87 this._routeInfo = this._sortIndexes(routes.map(function(route, index) {
89 model: MoreRouting.getRoute(route, this.parentRoute),
94 this._observeRoutes();
99 * Tracks changes to the routes.
101 _observeRoutes: function() {
102 if (this._routeListeners) {
103 for (var i = 0, listener; listener = this._routeListeners[i]; i++) {
108 this._routeListeners = this._routeInfo.map(function(routeInfo) {
109 return routeInfo.model.__subscribe(this._evaluate.bind(this));
113 _evaluate: function() {
116 var oldIndex = this.selectedIndex;
118 for (var i = 0, routeInfo; routeInfo = this._routeInfo[i]; i++) {
119 if (routeInfo.model && routeInfo.model.active) {
120 newIndex = routeInfo.index;
121 newRoute = routeInfo.model;
125 if (newIndex === oldIndex) return;
127 var oldRoute = this.selectedRoute;
128 var oldPath = this.selectedPath;
129 var oldParams = this.selectedParams;
131 var newPath = newRoute ? newRoute.fullPath : null;
132 var newParams = newRoute ? newRoute.params : {};
134 this._setSelectedRoute(newRoute);
135 this._setSelectedIndex(newIndex);
136 this._setSelectedPath(newPath);
137 this._setSelectedParams(newParams);
139 this.fire('more-route-change', {
140 newRoute: newRoute, oldRoute: oldRoute,
141 newIndex: newIndex, oldIndex: oldIndex,
142 newPath: newPath, oldPath: oldPath,
143 newParams: newParams, oldParams: oldParams,
147 * We want the most specific routes to match first, so we must create a
148 * mapping of indexes within `routes` that map
150 _sortIndexes: function(routeInfo) {
151 return routeInfo.sort(function(a, b) {
154 } else if (!b.model) {
156 // Routes with more path parts are most definitely more specific.
157 } else if (a.model.depth < b.model.depth) {
159 } if (a.model.depth > b.model.depth) {
163 // Also, routes with fewer params are more specific. For example
164 // `/users/foo` is more specific than `/users/:id`.
165 if (a.model.numParams < b.model.numParams) {
167 } else if (a.model.numParams > b.model.numParams) {
170 // Equally specific; we fall back to the default (and hopefully
171 // stable) sort order.