Remove LOAD_SUB_FRAME load flag.
[chromium-blink-merge.git] / third_party / polymer / components / paper-tabs / paper-tabs.html
blobbc664f1019dec7819b162128442475377ec32168
1 <!--
2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3 This code may only be used under the BSD style license found at http://polymer.github.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/CONTRIBUTORS.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/PATENTS.txt
8 -->
10 <!--
11 `paper-tabs` is a `core-selector` styled to look like tabs. Tabs make it easy to
12 explore and switch between different views or functional aspects of an app, or
13 to browse categorized data sets.
15 Use `selected` property to get or set the selected tab.
17 Example:
19 <paper-tabs selected="0">
20 <paper-tab>TAB 1</paper-tab>
21 <paper-tab>TAB 2</paper-tab>
22 <paper-tab>TAB 3</paper-tab>
23 </paper-tabs>
25 See <a href="#paper-tab">paper-tab</a> for more information about
26 `paper-tab`.
28 A common usage for `paper-tabs` is to use it along with `core-pages` to switch
29 between different views.
31 <paper-tabs selected="{{selected}}">
32 <paper-tab>Tab 1</paper-tab>
33 <paper-tab>Tab 2</paper-tab>
34 <paper-tab>Tab 3</paper-tab>
35 </paper-tabs>
37 <core-pages selected="{{selected}}">
38 <div>Page 1</div>
39 <div>Page 2</div>
40 <div>Page 3</div>
41 </core-pages>
43 `paper-tabs` adapt to mobile/narrow layout when there is a `core-narrow` class set
44 on itself or any of its ancestors.
46 To use links in tabs, add `link` attribute to `paper-tabs` and put an `<a>`
47 element in `paper-tab`.
49 Example:
51 <paper-tabs selected="0" link>
52 <paper-tab>
53 <a href="#link1" horizontal center-center layout>TAB ONE</a>
54 </paper-tab>
55 <paper-tab>
56 <a href="#link2" horizontal center-center layout>TAB TWO</a>
57 </paper-tab>
58 <paper-tab>
59 <a href="#link3" horizontal center-center layout>TAB THREE</a>
60 </paper-tab>
61 </paper-tabs>
63 Styling tabs:
65 To change the sliding bar color:
67 paper-tabs.pink::shadow #selectionBar {
68 background-color: #ff4081;
71 To change the ink ripple color:
73 paper-tabs.pink paper-tab::shadow #ink {
74 color: #ff4081;
77 @group Paper Elements
78 @element paper-tabs
79 @extends core-selector
80 @homepage github.io
81 -->
83 <link rel="import" href="../core-selector/core-selector.html">
84 <link rel="import" href="../paper-icon-button/paper-icon-button.html">
85 <link rel="import" href="../core-resizable/core-resizable.html">
86 <link rel="import" href="paper-tab.html">
88 <polymer-element name="paper-tabs" extends="core-selector" attributes="noink nobar noslide scrollable hideScrollButton" role="tablist" horizontal center layout>
89 <template>
91 <link rel="stylesheet" href="paper-tabs.css">
93 <div class="scroll-button" hidden?="{{!scrollable || hideScrollButton}}">
94 <paper-icon-button icon="chevron-left" class="{{ {hidden: leftHidden} | tokenList }}" on-down="{{holdLeft}}" on-up="{{releaseHold}}"></paper-icon-button>
95 </div>
97 <div id="tabsContainer" class="{{ {scrollable: scrollable} | tokenList }}" flex on-scroll="{{scroll}}" on-trackstart="{{trackStart}}">
99 <div id="tabsContent" horizontal layout?="{{!scrollable}}">
100 <shadow></shadow>
101 <div id="selectionBar" hidden?="{{nobar}}" on-transitionend="{{barTransitionEnd}}"></div>
102 </div>
104 </div>
106 <div class="scroll-button" hidden?="{{!scrollable || hideScrollButton}}">
107 <paper-icon-button icon="chevron-right" class="{{ {hidden: rightHidden} | tokenList }}" on-down="{{holdRight}}" on-up="{{releaseHold}}"></paper-icon-button>
108 </div>
110 </template>
111 <script>
113 Polymer(Polymer.mixin({
116 * If true, ink ripple effect is disabled.
118 * @attribute noink
119 * @type boolean
120 * @default false
122 noink: false,
125 * If true, the bottom bar to indicate the selected tab will not be shown.
127 * @attribute nobar
128 * @type boolean
129 * @default false
131 nobar: false,
134 * If true, the slide effect for the bottom bar is disabled.
136 * @attribute noslide
137 * @type boolean
138 * @default false
140 noslide: false,
143 * If true, tabs are scrollable and the tab width is based on the label width.
145 * @attribute scrollable
146 * @type boolean
147 * @default false
149 scrollable: false,
152 * If true, dragging on the tabs to scroll is disabled.
154 * @attribute disableDrag
155 * @type boolean
156 * @default false
158 disableDrag: false,
161 * If true, scroll buttons (left/right arrow) will be hidden for scrollable tabs.
163 * @attribute hideScrollButton
164 * @type boolean
165 * @default false
167 hideScrollButton: false,
169 eventDelegates: {
170 'core-resize': 'resizeHandler'
173 activateEvent: 'tap',
175 step: 10,
177 holdDelay: 10,
179 ready: function() {
180 this.super();
181 this._trackxHandler = this.trackx.bind(this);
182 Polymer.addEventListener(this.$.tabsContainer, 'trackx', this._trackxHandler);
183 this._tabsObserver = new MutationObserver(this.updateBar.bind(this));
186 domReady: function() {
187 this.async('resizeHandler');
188 this._tabsObserver.observe(this, {childList: true, subtree: true, characterData: true});
191 attached: function() {
192 this.resizableAttachedHandler();
195 detached: function() {
196 Polymer.removeEventListener(this.$.tabsContainer, 'trackx', this._trackxHandler);
197 this._tabsObserver.disconnect();
198 this.resizableDetachedHandler();
201 trackStart: function(e) {
202 if (!this.scrollable || this.disableDrag) {
203 return;
205 var t = e.target;
206 if (t && t.cancelRipple) {
207 t.cancelRipple();
209 this._startx = this.$.tabsContainer.scrollLeft;
210 e.preventTap();
213 trackx: function(e) {
214 if (!this.scrollable || this.disableDrag) {
215 return;
217 this.$.tabsContainer.scrollLeft = this._startx - e.dx;
220 resizeHandler: function() {
221 this.scroll();
222 this.updateBar();
225 scroll: function() {
226 if (!this.scrollable) {
227 return;
229 var tc = this.$.tabsContainer;
230 var l = tc.scrollLeft;
231 this.leftHidden = l === 0;
232 this.rightHidden = l === (tc.scrollWidth - tc.clientWidth);
235 holdLeft: function() {
236 this.holdJob = setInterval(this.scrollToLeft.bind(this), this.holdDelay);
239 holdRight: function() {
240 this.holdJob = setInterval(this.scrollToRight.bind(this), this.holdDelay);
243 releaseHold: function() {
244 clearInterval(this.holdJob);
245 this.holdJob = null;
248 scrollToLeft: function() {
249 this.$.tabsContainer.scrollLeft -= this.step;
252 scrollToRight: function() {
253 this.$.tabsContainer.scrollLeft += this.step;
257 * Invoke this to update the size and position of the bottom bar. Usually
258 * you only need to call this if the `paper-tabs` is initially hidden and
259 * later becomes visible.
261 * @method updateBar
263 updateBar: function() {
264 this.async('selectedItemChanged');
267 selectedItemChanged: function(old) {
268 var oldIndex = this.selectedIndex;
269 this.super(arguments);
270 var s = this.$.selectionBar.style;
272 if (!this.selectedItem) {
273 s.width = 0;
274 s.left = 0;
275 return;
278 var r = this.$.tabsContent.getBoundingClientRect();
279 this._w = r.width;
280 this._l = r.left;
282 r = this.selectedItem.getBoundingClientRect();
283 this._sw = r.width;
284 this._sl = r.left;
285 this._sOffsetLeft = this._sl - this._l;
287 if (this.noslide || old == null) {
288 this.positionBarForSelected();
289 return;
292 var oldRect = old.getBoundingClientRect();
294 var m = 5;
295 this.$.selectionBar.classList.add('expand');
296 if (oldIndex < this.selectedIndex) {
297 s.width = this.calcPercent(this._sl + this._sw - oldRect.left) - m + '%';
298 this._transitionCounter = 1;
299 } else {
300 s.width = this.calcPercent(oldRect.left + oldRect.width - this._sl) - m + '%';
301 s.left = this.calcPercent(this._sOffsetLeft) + m + '%';
302 this._transitionCounter = 2;
304 if (this.scrollable) {
305 this.scrollToSelectedIfNeeded();
309 scrollToSelectedIfNeeded: function() {
310 var scrollLeft = this.$.tabsContainer.scrollLeft;
311 // scroll to selected if needed
312 if (this._sOffsetLeft + this._sw < scrollLeft ||
313 this._sOffsetLeft - scrollLeft > this.$.tabsContainer.offsetWidth) {
314 this.$.tabsContainer.scrollLeft = this._sOffsetLeft;
318 positionBarForSelected: function() {
319 var s = this.$.selectionBar.style;
320 s.width = this.calcPercent(this._sw) + '%';
321 s.left = this.calcPercent(this._sOffsetLeft) + '%';
324 calcPercent: function(w) {
325 return 100 * w / this._w;
328 barTransitionEnd: function(e) {
329 this._transitionCounter--;
330 var cl = this.$.selectionBar.classList;
331 if (cl.contains('expand') && !this._transitionCounter) {
332 cl.remove('expand');
333 cl.add('contract');
334 this.positionBarForSelected();
335 } else if (cl.contains('contract')) {
336 cl.remove('contract');
340 }, Polymer.CoreResizable));
342 </script>
343 </polymer-element>