OLD | NEW |
| (Empty) |
1 | |
2 | |
3 Polymer({ | |
4 | |
5 is: 'paper-tabs', | |
6 | |
7 behaviors: [ | |
8 Polymer.IronResizableBehavior, | |
9 Polymer.IronMenubarBehavior | |
10 ], | |
11 | |
12 properties: { | |
13 | |
14 /** | |
15 * If true, ink ripple effect is disabled. | |
16 */ | |
17 noink: { | |
18 type: Boolean, | |
19 value: false | |
20 }, | |
21 | |
22 /** | |
23 * If true, the bottom bar to indicate the selected tab will not be shown. | |
24 */ | |
25 noBar: { | |
26 type: Boolean, | |
27 value: false | |
28 }, | |
29 | |
30 /** | |
31 * If true, the slide effect for the bottom bar is disabled. | |
32 */ | |
33 noSlide: { | |
34 type: Boolean, | |
35 value: false | |
36 }, | |
37 | |
38 /** | |
39 * If true, tabs are scrollable and the tab width is based on the label wi
dth. | |
40 */ | |
41 scrollable: { | |
42 type: Boolean, | |
43 value: false | |
44 }, | |
45 | |
46 /** | |
47 * If true, dragging on the tabs to scroll is disabled. | |
48 */ | |
49 disableDrag: { | |
50 type: Boolean, | |
51 value: false | |
52 }, | |
53 | |
54 /** | |
55 * If true, scroll buttons (left/right arrow) will be hidden for scrollabl
e tabs. | |
56 */ | |
57 hideScrollButtons: { | |
58 type: Boolean, | |
59 value: false | |
60 }, | |
61 | |
62 /** | |
63 * If true, the tabs are aligned to bottom (the selection bar appears at t
he top). | |
64 */ | |
65 alignBottom: { | |
66 type: Boolean, | |
67 value: false | |
68 }, | |
69 | |
70 /** | |
71 * Gets or sets the selected element. The default is to use the index of t
he item. | |
72 */ | |
73 selected: { | |
74 type: String, | |
75 notify: true | |
76 }, | |
77 | |
78 selectable: { | |
79 type: String, | |
80 value: 'paper-tab' | |
81 }, | |
82 | |
83 _step: { | |
84 type: Number, | |
85 value: 10 | |
86 }, | |
87 | |
88 _holdDelay: { | |
89 type: Number, | |
90 value: 1 | |
91 }, | |
92 | |
93 _leftHidden: { | |
94 type: Boolean, | |
95 value: false | |
96 }, | |
97 | |
98 _rightHidden: { | |
99 type: Boolean, | |
100 value: false | |
101 }, | |
102 | |
103 _previousTab: { | |
104 type: Object | |
105 } | |
106 }, | |
107 | |
108 hostAttributes: { | |
109 role: 'tablist' | |
110 }, | |
111 | |
112 listeners: { | |
113 'iron-resize': '_onResize', | |
114 'iron-select': '_onIronSelect', | |
115 'iron-deselect': '_onIronDeselect' | |
116 }, | |
117 | |
118 _computeScrollButtonClass: function(hideThisButton, scrollable, hideScrollBu
ttons) { | |
119 if (!scrollable || hideScrollButtons) { | |
120 return 'hidden'; | |
121 } | |
122 | |
123 if (hideThisButton) { | |
124 return 'not-visible'; | |
125 } | |
126 | |
127 return ''; | |
128 }, | |
129 | |
130 _computeTabsContentClass: function(scrollable) { | |
131 return scrollable ? 'scrollable' : 'horizontal layout'; | |
132 }, | |
133 | |
134 _computeSelectionBarClass: function(noBar, alignBottom) { | |
135 if (noBar) { | |
136 return 'hidden'; | |
137 } else if (alignBottom) { | |
138 return 'align-bottom'; | |
139 } | |
140 }, | |
141 | |
142 // TODO(cdata): Add `track` response back in when gesture lands. | |
143 | |
144 _onResize: function() { | |
145 this.debounce('_onResize', function() { | |
146 this._scroll(); | |
147 this._tabChanged(this.selectedItem); | |
148 }, 10); | |
149 }, | |
150 | |
151 _onIronSelect: function(event) { | |
152 this._tabChanged(event.detail.item, this._previousTab); | |
153 this._previousTab = event.detail.item; | |
154 this.cancelDebouncer('tab-changed'); | |
155 }, | |
156 | |
157 _onIronDeselect: function(event) { | |
158 this.debounce('tab-changed', function() { | |
159 this._tabChanged(null, this._previousTab); | |
160 // See polymer/polymer#1305 | |
161 }, 1); | |
162 }, | |
163 | |
164 get _tabContainerScrollSize () { | |
165 return Math.max( | |
166 0, | |
167 this.$.tabsContainer.scrollWidth - | |
168 this.$.tabsContainer.offsetWidth | |
169 ); | |
170 }, | |
171 | |
172 _scroll: function() { | |
173 var scrollLeft; | |
174 | |
175 if (!this.scrollable) { | |
176 return; | |
177 } | |
178 | |
179 scrollLeft = this.$.tabsContainer.scrollLeft; | |
180 | |
181 this._leftHidden = scrollLeft === 0; | |
182 this._rightHidden = scrollLeft === this._tabContainerScrollSize; | |
183 }, | |
184 | |
185 _onLeftScrollButtonDown: function() { | |
186 this._holdJob = setInterval(this._scrollToLeft.bind(this), this._holdDelay
); | |
187 }, | |
188 | |
189 _onRightScrollButtonDown: function() { | |
190 this._holdJob = setInterval(this._scrollToRight.bind(this), this._holdDela
y); | |
191 }, | |
192 | |
193 _onScrollButtonUp: function() { | |
194 clearInterval(this._holdJob); | |
195 this._holdJob = null; | |
196 }, | |
197 | |
198 _scrollToLeft: function() { | |
199 this.$.tabsContainer.scrollLeft -= this._step; | |
200 }, | |
201 | |
202 _scrollToRight: function() { | |
203 this.$.tabsContainer.scrollLeft += this._step; | |
204 }, | |
205 | |
206 _tabChanged: function(tab, old) { | |
207 if (!tab) { | |
208 this._positionBar(0, 0); | |
209 return; | |
210 } | |
211 | |
212 var r = this.$.tabsContent.getBoundingClientRect(); | |
213 var w = r.width; | |
214 var tabRect = tab.getBoundingClientRect(); | |
215 var tabOffsetLeft = tabRect.left - r.left; | |
216 | |
217 this._pos = { | |
218 width: this._calcPercent(tabRect.width, w), | |
219 left: this._calcPercent(tabOffsetLeft, w) | |
220 }; | |
221 | |
222 if (this.noSlide || old == null) { | |
223 // position bar directly without animation | |
224 this._positionBar(this._pos.width, this._pos.left); | |
225 return; | |
226 } | |
227 | |
228 var oldRect = old.getBoundingClientRect(); | |
229 var oldIndex = this.items.indexOf(old); | |
230 var index = this.items.indexOf(tab); | |
231 var m = 5; | |
232 | |
233 // bar animation: expand | |
234 this.$.selectionBar.classList.add('expand'); | |
235 | |
236 if (oldIndex < index) { | |
237 this._positionBar(this._calcPercent(tabRect.left + tabRect.width - oldRe
ct.left, w) - m, | |
238 this._left); | |
239 } else { | |
240 this._positionBar(this._calcPercent(oldRect.left + oldRect.width - tabRe
ct.left, w) - m, | |
241 this._calcPercent(tabOffsetLeft, w) + m); | |
242 } | |
243 | |
244 if (this.scrollable) { | |
245 this._scrollToSelectedIfNeeded(tabRect.width, tabOffsetLeft); | |
246 } | |
247 }, | |
248 | |
249 _scrollToSelectedIfNeeded: function(tabWidth, tabOffsetLeft) { | |
250 var l = tabOffsetLeft - this.$.tabsContainer.scrollLeft; | |
251 if (l < 0) { | |
252 this.$.tabsContainer.scrollLeft += l; | |
253 } else { | |
254 l += (tabWidth - this.$.tabsContainer.offsetWidth); | |
255 if (l > 0) { | |
256 this.$.tabsContainer.scrollLeft += l; | |
257 } | |
258 } | |
259 }, | |
260 | |
261 _calcPercent: function(w, w0) { | |
262 return 100 * w / w0; | |
263 }, | |
264 | |
265 _positionBar: function(width, left) { | |
266 this._width = width; | |
267 this._left = left; | |
268 this.transform( | |
269 'translate3d(' + left + '%, 0, 0) scaleX(' + (width / 100) + ')', | |
270 this.$.selectionBar); | |
271 }, | |
272 | |
273 _onBarTransitionEnd: function(e) { | |
274 var cl = this.$.selectionBar.classList; | |
275 // bar animation: expand -> contract | |
276 if (cl.contains('expand')) { | |
277 cl.remove('expand'); | |
278 cl.add('contract'); | |
279 this._positionBar(this._pos.width, this._pos.left); | |
280 // bar animation done | |
281 } else if (cl.contains('contract')) { | |
282 cl.remove('contract'); | |
283 } | |
284 } | |
285 | |
286 }); | |
287 | |
OLD | NEW |