OLD | NEW |
| (Empty) |
1 <!-- | |
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.g
ithub.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/CONTRI
BUTORS.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/PATEN
TS.txt | |
8 --> | |
9 <link rel="import" href="../polymer/polymer.html"> | |
10 | |
11 <link rel="import" href="more-route-context-aware.html"> | |
12 <link rel="import" href="more-route-selection.html"> | |
13 | |
14 <!-- | |
15 TODO(nevir): Document. | |
16 | |
17 TODO(nevir): Support child addition/removal/reorder. | |
18 --> | |
19 <dom-module id="more-route-selector"> | |
20 <template> | |
21 <more-route-selection | |
22 id="selection" | |
23 routes="[[routes]]" | |
24 on-more-route-change="_onMoreRouteChange"> | |
25 </more-route-selection> | |
26 <content></content> | |
27 </template> | |
28 </dom-module> | |
29 <script> | |
30 Polymer({ | |
31 | |
32 is: 'more-route-selector', | |
33 | |
34 behaviors: [ | |
35 MoreRouting.ContextAware, | |
36 ], | |
37 | |
38 properties: { | |
39 | |
40 /** | |
41 * The attribute to read route expressions from (on children). | |
42 */ | |
43 routeAttribute: { | |
44 type: String, | |
45 value: 'route', | |
46 }, | |
47 | |
48 /** | |
49 * The routes managed by this element (inferred from the items that are | |
50 * defined by the selector it targets). | |
51 */ | |
52 routes: { | |
53 type: Array, | |
54 readOnly: true, | |
55 notify: true, | |
56 }, | |
57 | |
58 /** | |
59 * The selected `MoreRouting.Route` object, or `null`. | |
60 * | |
61 * @type {MoreRouting.Route} | |
62 */ | |
63 selectedRoute: { | |
64 type: Object, | |
65 value: null, | |
66 readOnly: true, | |
67 notify: true, | |
68 }, | |
69 | |
70 /** | |
71 * The index of the selected route (relative to `routes`). -1 when there | |
72 * is no active route. | |
73 */ | |
74 selectedIndex: { | |
75 type: Number, | |
76 value: -1, | |
77 readOnly: true, | |
78 notify: true, | |
79 }, | |
80 | |
81 /** | |
82 * The _full_ path expression of the selected route, or `null`. | |
83 */ | |
84 selectedPath: { | |
85 type: String, | |
86 readOnly: true, | |
87 notify: true, | |
88 }, | |
89 | |
90 /** | |
91 * The params of the selected route, or an empty object if no route. | |
92 */ | |
93 selectedParams: { | |
94 type: Object, | |
95 readOnly: true, | |
96 notify: true, | |
97 }, | |
98 | |
99 }, | |
100 | |
101 /** | |
102 * @event more-route-selected fires when a new route is selected. | |
103 * @param {{ | |
104 * newRoute: MoreRouting.Route, oldRoute: MoreRouting.Route, | |
105 * newIndex: number, oldIndex: number, | |
106 * newPath: ?string, oldPath: ?string, | |
107 * newParams: Object, oldParams: Object, | |
108 * }} | |
109 */ | |
110 | |
111 attached: function() { | |
112 this._managedSelector = this._findTargetSelector(); | |
113 if (!this._managedSelector) { | |
114 console.warn(this, 'was built without a selector to manage. It will do not
hing.'); | |
115 return; | |
116 } | |
117 | |
118 this._managedSelector.addEventListener( | |
119 'selected-item-changed', this._onSelectedItemChanged.bind(this)); | |
120 this._updateRoutes(); | |
121 }, | |
122 | |
123 /** | |
124 * Handle a change in selected item, driven by the targeted selector. | |
125 * | |
126 * Note that this will fail if a route is chosen that requires params not | |
127 * defined by the current URL. | |
128 */ | |
129 _onSelectedItemChanged: function(event) { | |
130 if (this._settingSelection) return; | |
131 var route = this._routeForItem(event.detail.value); | |
132 if (!route) return; | |
133 route.navigateTo(); | |
134 }, | |
135 | |
136 _updateRoutes: function() { | |
137 var routes = []; | |
138 if (this._managedSelector) { | |
139 routes = this._managedSelector.items.map(this._routeForItem.bind(this)); | |
140 } | |
141 this._setRoutes(routes); | |
142 }, | |
143 | |
144 _onMoreRouteChange: function(event) { | |
145 if (!this._managedSelector) return; | |
146 | |
147 var selected = ''; | |
148 | |
149 var index = this.routes.indexOf(event.detail.newRoute); | |
150 var attrForSelected = this._managedSelector.attrForSelected; | |
151 if (!attrForSelected) { | |
152 selected = index; | |
153 } else { | |
154 var item = this._managedSelector.items[index]; | |
155 if (item) | |
156 selected = item[attrForSelected] || item.getAttribute(attrForSelected); | |
157 } | |
158 | |
159 // Make sure that we don't turn around and re-navigate | |
160 this._settingSelection = true; | |
161 this._managedSelector.select(selected); | |
162 this._settingSelection = false; | |
163 }, | |
164 | |
165 _findTargetSelector: function() { | |
166 var children = Polymer.dom(this).children; | |
167 if (children.length !== 1) { | |
168 console.error(this, 'expects only a single selector child'); | |
169 return null; | |
170 } | |
171 | |
172 var child = children[0]; | |
173 if ('selected' in child && 'items' in child) { | |
174 return child; | |
175 } else { | |
176 console.error(this, 'can only manage children that are selectors'); | |
177 return null; | |
178 } | |
179 }, | |
180 | |
181 _routeForItem: function(item) { | |
182 if (!item) return null; | |
183 if (item.moreRouteContext && item.moreRouteContext instanceof MoreRouting.Ro
ute) { | |
184 return item.moreRouteContext; | |
185 } | |
186 | |
187 if (!item.hasAttribute(this.routeAttribute)) { | |
188 console.warn(item, 'is missing a context route or "' + this.routeAttribute
+ '" attribute'); | |
189 return null; | |
190 } | |
191 var expression = item.getAttribute(this.routeAttribute); | |
192 var route = MoreRouting.getRoute(expression, this.parentRoute); | |
193 // Associate the route w/ its element while we're here. | |
194 item.moreRouteContext = route; | |
195 | |
196 return route; | |
197 }, | |
198 | |
199 }); | |
200 </script> | |
OLD | NEW |