UNPKG

five-bells-visualization

Version:
354 lines (287 loc) 10 kB
<!-- Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> <!-- `paper-tabs` is a `core-selector` styled to look like tabs. Tabs make it easy to explore and switch between different views or functional aspects of an app, or to browse categorized data sets. Use `selected` property to get or set the selected tab. Example: <paper-tabs selected="0"> <paper-tab>TAB 1</paper-tab> <paper-tab>TAB 2</paper-tab> <paper-tab>TAB 3</paper-tab> </paper-tabs> See <a href="#paper-tab">paper-tab</a> for more information about `paper-tab`. A common usage for `paper-tabs` is to use it along with `core-pages` to switch between different views. <paper-tabs selected="{{selected}}"> <paper-tab>Tab 1</paper-tab> <paper-tab>Tab 2</paper-tab> <paper-tab>Tab 3</paper-tab> </paper-tabs> <core-pages selected="{{selected}}"> <div>Page 1</div> <div>Page 2</div> <div>Page 3</div> </core-pages> `paper-tabs` adapt to mobile/narrow layout when there is a `core-narrow` class set on itself or any of its ancestors. To use links in tabs, add `link` attribute to `paper-tabs` and put an `<a>` element in `paper-tab`. Example: <paper-tabs selected="0" link> <paper-tab> <a href="#link1" horizontal center-center layout>TAB ONE</a> </paper-tab> <paper-tab> <a href="#link2" horizontal center-center layout>TAB TWO</a> </paper-tab> <paper-tab> <a href="#link3" horizontal center-center layout>TAB THREE</a> </paper-tab> </paper-tabs> Styling tabs: To change the sliding bar color: paper-tabs.pink::shadow #selectionBar { background-color: #ff4081; } To change the ink ripple color: paper-tabs.pink paper-tab::shadow #ink { color: #ff4081; } @group Paper Elements @element paper-tabs @extends core-selector @mixins Polymer.CoreResizable https://github.com/polymer/core-resizable @homepage github.io --> <link rel="import" href="../core-selector/core-selector.html"> <link rel="import" href="../paper-icon-button/paper-icon-button.html"> <link rel="import" href="../core-resizable/core-resizable.html"> <link rel="import" href="paper-tab.html"> <polymer-element name="paper-tabs" extends="core-selector" attributes="noink nobar noslide scrollable hideScrollButton alignBottom" role="tablist" horizontal center layout> <template> <link rel="stylesheet" href="paper-tabs.css"> <div class="scroll-button" hidden?="{{!scrollable || hideScrollButton}}"> <paper-icon-button icon="chevron-left" class="{{ {hidden: leftHidden} | tokenList }}" on-down="{{holdLeft}}" on-up="{{releaseHold}}"></paper-icon-button> </div> <div id="tabsContainer" class="{{ {scrollable: scrollable} | tokenList }}" flex on-scroll="{{scroll}}" on-trackstart="{{trackStart}}"> <div id="tabsContent" horizontal layout?="{{!scrollable}}"> <shadow></shadow> <div id="selectionBar" hidden?="{{nobar}}" class="{{ {alignBottom: alignBottom} | tokenList }}" on-transitionend="{{barTransitionEnd}}"></div> </div> </div> <div class="scroll-button" hidden?="{{!scrollable || hideScrollButton}}"> <paper-icon-button icon="chevron-right" class="{{ {hidden: rightHidden} | tokenList }}" on-down="{{holdRight}}" on-up="{{releaseHold}}"></paper-icon-button> </div> </template> <script> Polymer(Polymer.mixin({ /** * If true, ink ripple effect is disabled. * * @attribute noink * @type boolean * @default false */ noink: false, /** * If true, the bottom bar to indicate the selected tab will not be shown. * * @attribute nobar * @type boolean * @default false */ nobar: false, /** * If true, the slide effect for the bottom bar is disabled. * * @attribute noslide * @type boolean * @default false */ noslide: false, /** * If true, tabs are scrollable and the tab width is based on the label width. * * @attribute scrollable * @type boolean * @default false */ scrollable: false, /** * If true, dragging on the tabs to scroll is disabled. * * @attribute disableDrag * @type boolean * @default false */ disableDrag: false, /** * If true, scroll buttons (left/right arrow) will be hidden for scrollable tabs. * * @attribute hideScrollButton * @type boolean * @default false */ hideScrollButton: false, /** * If true, the tabs are aligned to bottom (the selection bar appears at the top). * @attribute alignBottom @type boolean @default false */ alignBottom: false, eventDelegates: { 'core-resize': 'resizeHandler' }, activateEvent: 'tap', step: 10, holdDelay: 10, ready: function() { this.super(); this._trackxHandler = this.trackx.bind(this); Polymer.addEventListener(this.$.tabsContainer, 'trackx', this._trackxHandler); this._tabsObserver = new MutationObserver(this.updateBar.bind(this)); }, domReady: function() { this.async('resizeHandler'); this._tabsObserver.observe(this, {childList: true, subtree: true, characterData: true}); }, attached: function() { this.resizableAttachedHandler(); }, detached: function() { Polymer.removeEventListener(this.$.tabsContainer, 'trackx', this._trackxHandler); this._tabsObserver.disconnect(); this.resizableDetachedHandler(); }, trackStart: function(e) { if (!this.scrollable || this.disableDrag) { return; } var t = e.target; if (t && t.cancelRipple) { t.cancelRipple(); } this._startx = this.$.tabsContainer.scrollLeft; e.preventTap(); }, trackx: function(e) { if (!this.scrollable || this.disableDrag) { return; } this.$.tabsContainer.scrollLeft = this._startx - e.dx; }, resizeHandler: function() { this.scroll(); this.updateBar(); }, scroll: function() { if (!this.scrollable) { return; } var tc = this.$.tabsContainer; var l = tc.scrollLeft; this.leftHidden = l === 0; this.rightHidden = l === Math.max(0, (tc.scrollWidth - tc.clientWidth)); }, holdLeft: function() { this.holdJob = setInterval(this.scrollToLeft.bind(this), this.holdDelay); }, holdRight: function() { this.holdJob = setInterval(this.scrollToRight.bind(this), this.holdDelay); }, releaseHold: function() { clearInterval(this.holdJob); this.holdJob = null; }, scrollToLeft: function() { this.$.tabsContainer.scrollLeft -= this.step; }, scrollToRight: function() { this.$.tabsContainer.scrollLeft += this.step; }, /** * Invoke this to update the size and position of the bottom bar. Usually * you only need to call this if the `paper-tabs` is initially hidden and * later becomes visible. * * @method updateBar */ updateBar: function() { this.async('selectedItemChanged'); }, selectedItemChanged: function(old) { var oldIndex = this.selectedIndex; this.super(arguments); var s = this.$.selectionBar.style; if (!this.selectedItem) { s.width = 0; s.left = 0; return; } var r = this.$.tabsContent.getBoundingClientRect(); this._w = r.width; this._l = r.left; r = this.selectedItem.getBoundingClientRect(); this._sw = r.width; this._sl = r.left; this._sOffsetLeft = this._sl - this._l; if (this.noslide || old == null) { this.positionBarForSelected(); return; } var oldRect = old.getBoundingClientRect(); var m = 5; this.$.selectionBar.classList.add('expand'); if (oldIndex < this.selectedIndex) { s.width = this.calcPercent(this._sl + this._sw - oldRect.left) - m + '%'; this._transitionCounter = 1; } else { s.width = this.calcPercent(oldRect.left + oldRect.width - this._sl) - m + '%'; s.left = this.calcPercent(this._sOffsetLeft) + m + '%'; this._transitionCounter = 2; } if (this.scrollable) { this.scrollToSelectedIfNeeded(); } }, scrollToSelectedIfNeeded: function() { var scrollLeft = this.$.tabsContainer.scrollLeft; // scroll to selected if needed if (this._sOffsetLeft + this._sw < scrollLeft || this._sOffsetLeft - scrollLeft > this.$.tabsContainer.offsetWidth) { this.$.tabsContainer.scrollLeft = this._sOffsetLeft; } }, positionBarForSelected: function() { var s = this.$.selectionBar.style; s.width = this.calcPercent(this._sw) + '%'; s.left = this.calcPercent(this._sOffsetLeft) + '%'; }, calcPercent: function(w) { return 100 * w / this._w; }, barTransitionEnd: function(e) { this._transitionCounter--; var cl = this.$.selectionBar.classList; if (cl.contains('expand') && !this._transitionCounter) { cl.remove('expand'); cl.add('contract'); this.positionBarForSelected(); } else if (cl.contains('contract')) { cl.remove('contract'); } } }, Polymer.CoreResizable)); </script> </polymer-element>