|
| 1 | +window.addEventListener('WebComponentsReady', function () { |
| 2 | + const tagName = 'hx-tabset'; |
| 3 | + const template = document.createElement('template'); |
| 4 | + |
| 5 | + template.innerHTML = ` |
| 6 | + <style>${require('./HxTabset.less')}</style> |
| 7 | + ${require('./HxTabset.html')} |
| 8 | + `; |
| 9 | + |
| 10 | + class HxTabset extends HTMLElement { |
| 11 | + static get is () { |
| 12 | + return tagName; |
| 13 | + } |
| 14 | + |
| 15 | + static get observedAttributes () { |
| 16 | + return ['selected']; |
| 17 | + } |
| 18 | + |
| 19 | + constructor () { |
| 20 | + super(); |
| 21 | + this.attachShadow({mode: 'open'}); |
| 22 | + if (window.ShadyCSS) { |
| 23 | + ShadyCSS.prepareTemplate(template, tagName); |
| 24 | + ShadyCSS.styleElement(this); |
| 25 | + } |
| 26 | + this.shadowRoot.appendChild(template.content.cloneNode(true)); |
| 27 | + this.$head = this.shadowRoot.querySelector('#head'); |
| 28 | + this._onHeadClick = this._onHeadClick.bind(this); |
| 29 | + } |
| 30 | + |
| 31 | + connectedCallback () { |
| 32 | + this.$head.addEventListener('click', this._onHeadClick); |
| 33 | + if (!this.hasAttribute('role')) { |
| 34 | + this.setAttribute('role', 'tablist'); |
| 35 | + } |
| 36 | + |
| 37 | + if (!this.hasAttribute('selected')) { |
| 38 | + this._selectPanelByIndex(0); |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + disconnectedCallback () { |
| 43 | + this.$head.removeEventListener('click', this._onHeadClick); |
| 44 | + } |
| 45 | + |
| 46 | + attributeChangedCallback (attr, oldValue, newValue) { |
| 47 | + this._selectPanelById(newValue); |
| 48 | + } |
| 49 | + |
| 50 | + get selected () { |
| 51 | + return this.getAttribute('selected'); |
| 52 | + } |
| 53 | + |
| 54 | + set selected (id) { |
| 55 | + if (this.querySelector(`hx-tabpanel#${id}`)) { |
| 56 | + this.setAttribute('selected', id); |
| 57 | + } else { |
| 58 | + throw new Error(`Tab with id "${id}" not found`); |
| 59 | + } |
| 60 | + } |
| 61 | + |
| 62 | + get tabs () { |
| 63 | + return Array.from(this.querySelectorAll(`.hxTab`)); |
| 64 | + } |
| 65 | + |
| 66 | + get panels () { |
| 67 | + return Array.from(this.querySelectorAll('hx-tabpanel')); |
| 68 | + } |
| 69 | + |
| 70 | + _selectPanelById (id) { |
| 71 | + this._selectPanel(this.querySelector(`hx-tabpanel#${id}`)); |
| 72 | + } |
| 73 | + |
| 74 | + _selectPanelByIndex (idx) { |
| 75 | + if (idx < 0 || idx >= this.panels.length) { |
| 76 | + throw new Error(`Panel index out of bounds`); |
| 77 | + } else { |
| 78 | + this._selectPanel(this.panels[idx]); |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + _selectPanel (panel) { |
| 83 | + if (panel) { |
| 84 | + this._reset(); |
| 85 | + panel.open = true; |
| 86 | + var selectedIndex = this.panels.indexOf(panel); |
| 87 | + this.tabs[selectedIndex].classList.add('current'); |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + _reset () { |
| 92 | + this.panels.forEach(panel => panel.open = false); |
| 93 | + this.tabs.forEach(tab => tab.classList.remove('current')); |
| 94 | + } |
| 95 | + |
| 96 | + _onHeadClick (event) { |
| 97 | + event.preventDefault(); |
| 98 | + this._selectPanelByIndex(this.tabs.indexOf(event.target)); |
| 99 | + } |
| 100 | + } |
| 101 | + customElements.define(HxTabset.is, HxTabset) |
| 102 | +}); |
0 commit comments