1/* 2 * This content is licensed according to the W3C Software License at 3 * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document 4 * 5 * File: tabs-automatic.js 6 * 7 * Desc: Tablist widget that implements ARIA Authoring Practices 8 */ 9 10'use strict'; 11 12class TabsAutomatic { 13 constructor(groupNode) { 14 this.tablistNode = groupNode; 15 16 this.tabs = []; 17 18 this.firstTab = null; 19 this.lastTab = null; 20 21 this.tabs = Array.from(this.tablistNode.querySelectorAll('[role=tab]')); 22 this.tabpanels = []; 23 24 for (var i = 0; i < this.tabs.length; i += 1) { 25 var tab = this.tabs[i]; 26 var tabpanel = document.getElementById(tab.getAttribute('aria-controls')); 27 28 tab.tabIndex = -1; 29 tab.setAttribute('aria-selected', 'false'); 30 this.tabpanels.push(tabpanel); 31 32 tab.addEventListener('keydown', this.onKeydown.bind(this)); 33 tab.addEventListener('click', this.onClick.bind(this)); 34 35 if (!this.firstTab) { 36 this.firstTab = tab; 37 } 38 this.lastTab = tab; 39 } 40 41 this.setSelectedTab(this.firstTab, false); 42 } 43 44 setSelectedTab(currentTab, setFocus) { 45 if (typeof setFocus !== 'boolean') { 46 setFocus = true; 47 } 48 49 for (var i = 0; i < this.tabs.length; i += 1) { 50 var tab = this.tabs[i]; 51 52 53 if (this.tabpanels[i] === null) { 54 continue; 55 } 56 if (currentTab === tab) { 57 tab.setAttribute('aria-selected', 'true'); 58 tab.removeAttribute('tabindex'); 59 this.tabpanels[i].classList.remove('hidden'); 60 if (setFocus) { 61 tab.focus(); 62 } 63 } else { 64 tab.setAttribute('aria-selected', 'false'); 65 tab.tabIndex = -1; 66 this.tabpanels[i].classList.add('hidden'); 67 } 68 } 69 } 70 71 setSelectedToPreviousTab(currentTab) { 72 var index; 73 74 if (currentTab === this.firstTab) { 75 this.setSelectedTab(this.lastTab); 76 } else { 77 index = this.tabs.indexOf(currentTab); 78 this.setSelectedTab(this.tabs[index - 1]); 79 } 80 } 81 82 setSelectedToNextTab(currentTab) { 83 var index; 84 85 if (currentTab === this.lastTab) { 86 this.setSelectedTab(this.firstTab); 87 } else { 88 index = this.tabs.indexOf(currentTab); 89 this.setSelectedTab(this.tabs[index + 1]); 90 } 91 } 92 93 /* EVENT HANDLERS */ 94 95 onKeydown(event) { 96 var tgt = event.currentTarget, 97 flag = false; 98 99 switch (event.key) { 100 case 'ArrowLeft': 101 this.setSelectedToPreviousTab(tgt); 102 flag = true; 103 break; 104 105 case 'ArrowRight': 106 this.setSelectedToNextTab(tgt); 107 flag = true; 108 break; 109 110 case 'Home': 111 this.setSelectedTab(this.firstTab); 112 flag = true; 113 break; 114 115 case 'End': 116 this.setSelectedTab(this.lastTab); 117 flag = true; 118 break; 119 120 default: 121 break; 122 } 123 124 if (flag) { 125 event.stopPropagation(); 126 event.preventDefault(); 127 } 128 } 129 130 onClick(event) { 131 this.setSelectedTab(event.currentTarget); 132 } 133} 134 135// Initialize tablist 136 137window.addEventListener('load', function () { 138 var tablists = document.querySelectorAll('[role=tablist]'); 139 for (var i = 0; i < tablists.length; i++) { 140 141 new TabsAutomatic(tablists[i]); 142 } 143});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.