Service workers: Allow HTTPS pages arrived at via HTTP redirect to use SW
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components-chromium / more-routing / more-route-selection-extracted.js
blobb3ea3ab5cf19691423b44a8ce8c41352fa54b759
1 Polymer({
3     is: 'more-route-selection',
5     behaviors: [
6       MoreRouting.ContextAware,
7     ],
9     properties: {
11       /**
12        * Routes to select from, as either a path expression or route name.
13        *
14        * You can either specify routes via this attribute, or as child nodes
15        * to this element, but not both.
16        *
17        * @type {String|Array<string|MoreRouting.Route>}
18        */
19       routes: {
20         type:     String,
21         observer: '_routesChanged',
22       },
24       /**
25        * The selected `MoreRouting.Route` object, or `null`.
26        *
27        * @type {MoreRouting.Route}
28        */
29       selectedRoute: {
30         type:     Object,
31         value:    null,
32         readOnly: true,
33         notify:   true,
34       },
36       /**
37        * The index of the selected route (relative to `routes`). -1 when there
38        * is no active route.
39        */
40       selectedIndex: {
41         type:     Number,
42         value:    -1,
43         readOnly: true,
44         notify:   true,
45       },
47       /**
48        * The _full_ path expression of the selected route, or `null`.
49        */
50       selectedPath: {
51         type:     String,
52         readOnly: true,
53         notify:   true,
54       },
56       /**
57        * The params of the selected route, or an empty object if no route.
58        */
59       selectedParams: {
60         type:     Object,
61         readOnly: true,
62         notify:   true,
63       },
65     },
67     /**
68      * @event more-route-change fires when a new route is selected.
69      * @detail {{
70      *   newRoute:  MoreRouting.Route, oldRoute: MoreRouting.Route,
71      *   newIndex:  number,  oldIndex:  number,
72      *   newPath:   ?string, oldPath:   ?string,
73      *   newParams: Object,  oldParams: Object,
74      * }}
75      */
77     routingReady: function() {
78       this._routesChanged();
79     },
81     _routesChanged: function() {
82       if (!this.routingIsReady) return;
83       var routes = this.routes || [];
84       if (typeof routes === 'string') {
85         routes = routes.split(/\s+/);
86       }
87       this._routeInfo = this._sortIndexes(routes.map(function(route, index) {
88         return {
89           model: MoreRouting.getRoute(route, this.parentRoute),
90           index: index,
91         };
92       }.bind(this)));
94       this._observeRoutes();
95       this._evaluate();
96     },
98     /**
99      * Tracks changes to the routes.
100      */
101     _observeRoutes: function() {
102       if (this._routeListeners) {
103         for (var i = 0, listener; listener = this._routeListeners[i]; i++) {
104           listener.close();
105         }
106       }
108       this._routeListeners = this._routeInfo.map(function(routeInfo) {
109         return routeInfo.model.__subscribe(this._evaluate.bind(this));
110       }.bind(this));
111     },
113     _evaluate: function() {
114       var newIndex = -1;
115       var newRoute = null;
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;
122           break;
123         }
124       }
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,
144       });
145     },
146     /**
147      * We want the most specific routes to match first, so we must create a
148      * mapping of indexes within `routes` that map
149      */
150     _sortIndexes: function(routeInfo) {
151       return routeInfo.sort(function(a, b) {
152         if (!a.model) {
153           return 1;
154         } else if (!b.model) {
155           return -1;
156         // Routes with more path parts are most definitely more specific.
157         } else if (a.model.depth < b.model.depth) {
158           return 1;
159         } if (a.model.depth > b.model.depth) {
160           return -1;
161         } else {
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) {
166             return -1;
167           } else if (a.model.numParams > b.model.numParams) {
168             return 1;
169           } else {
170             // Equally specific; we fall back to the default (and hopefully
171             // stable) sort order.
172             return 0;
173           }
174         }
175       });
176     },
178   });