8 Polymer.IronResizableBehavior,
9 Polymer.IronMenubarBehavior
15 * If true, ink ripple effect is disabled.
23 * If true, the bottom bar to indicate the selected tab will not be shown.
31 * If true, the slide effect for the bottom bar is disabled.
39 * If true, tabs are scrollable and the tab width is based on the label width.
47 * If true, dragging on the tabs to scroll is disabled.
55 * If true, scroll buttons (left/right arrow) will be hidden for scrollable tabs.
63 * If true, the tabs are aligned to bottom (the selection bar appears at the top).
71 * Gets or sets the selected element. The default is to use the index of the item.
113 'iron-resize': '_onResize',
114 'iron-select': '_onIronSelect',
115 'iron-deselect': '_onIronDeselect'
118 _computeScrollButtonClass: function(hideThisButton, scrollable, hideScrollButtons) {
119 if (!scrollable || hideScrollButtons) {
123 if (hideThisButton) {
124 return 'not-visible';
130 _computeTabsContentClass: function(scrollable) {
131 return scrollable ? 'scrollable' : 'horizontal layout';
134 _computeSelectionBarClass: function(noBar, alignBottom) {
137 } else if (alignBottom) {
138 return 'align-bottom';
142 // TODO(cdata): Add `track` response back in when gesture lands.
144 _onResize: function() {
145 this.debounce('_onResize', function() {
147 this._tabChanged(this.selectedItem);
151 _onIronSelect: function(event) {
152 this._tabChanged(event.detail.item, this._previousTab);
153 this._previousTab = event.detail.item;
154 this.cancelDebouncer('tab-changed');
157 _onIronDeselect: function(event) {
158 this.debounce('tab-changed', function() {
159 this._tabChanged(null, this._previousTab);
160 // See polymer/polymer#1305
164 get _tabContainerScrollSize () {
167 this.$.tabsContainer.scrollWidth -
168 this.$.tabsContainer.offsetWidth
172 _scroll: function() {
175 if (!this.scrollable) {
179 scrollLeft = this.$.tabsContainer.scrollLeft;
181 this._leftHidden = scrollLeft === 0;
182 this._rightHidden = scrollLeft === this._tabContainerScrollSize;
185 _onLeftScrollButtonDown: function() {
186 this._holdJob = setInterval(this._scrollToLeft.bind(this), this._holdDelay);
189 _onRightScrollButtonDown: function() {
190 this._holdJob = setInterval(this._scrollToRight.bind(this), this._holdDelay);
193 _onScrollButtonUp: function() {
194 clearInterval(this._holdJob);
195 this._holdJob = null;
198 _scrollToLeft: function() {
199 this.$.tabsContainer.scrollLeft -= this._step;
202 _scrollToRight: function() {
203 this.$.tabsContainer.scrollLeft += this._step;
206 _tabChanged: function(tab, old) {
208 this._positionBar(0, 0);
212 var r = this.$.tabsContent.getBoundingClientRect();
214 var tabRect = tab.getBoundingClientRect();
215 var tabOffsetLeft = tabRect.left - r.left;
218 width: this._calcPercent(tabRect.width, w),
219 left: this._calcPercent(tabOffsetLeft, w)
222 if (this.noSlide || old == null) {
223 // position bar directly without animation
224 this._positionBar(this._pos.width, this._pos.left);
228 var oldRect = old.getBoundingClientRect();
229 var oldIndex = this.items.indexOf(old);
230 var index = this.items.indexOf(tab);
233 // bar animation: expand
234 this.$.selectionBar.classList.add('expand');
236 if (oldIndex < index) {
237 this._positionBar(this._calcPercent(tabRect.left + tabRect.width - oldRect.left, w) - m,
240 this._positionBar(this._calcPercent(oldRect.left + oldRect.width - tabRect.left, w) - m,
241 this._calcPercent(tabOffsetLeft, w) + m);
244 if (this.scrollable) {
245 this._scrollToSelectedIfNeeded(tabRect.width, tabOffsetLeft);
249 _scrollToSelectedIfNeeded: function(tabWidth, tabOffsetLeft) {
250 var l = tabOffsetLeft - this.$.tabsContainer.scrollLeft;
252 this.$.tabsContainer.scrollLeft += l;
254 l += (tabWidth - this.$.tabsContainer.offsetWidth);
256 this.$.tabsContainer.scrollLeft += l;
261 _calcPercent: function(w, w0) {
265 _positionBar: function(width, left) {
272 'translate3d(' + left + '%, 0, 0) scaleX(' + (width / 100) + ')',
273 this.$.selectionBar);
276 _onBarTransitionEnd: function(e) {
277 var cl = this.$.selectionBar.classList;
278 // bar animation: expand -> contract
279 if (cl.contains('expand')) {
282 this._positionBar(this._pos.width, this._pos.left);
283 // bar animation done
284 } else if (cl.contains('contract')) {
285 cl.remove('contract');