1// ===----------------------------------------------------------------------===// 2// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// https://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// ===----------------------------------------------------------------------===// 16(function () { 17 // Opens <details> blocks if anchor tags target elements inside them. 18 const openTarget = () => { 19 const hash = window.location.hash; 20 if (hash.length === 0) { 21 return; 22 } 23 const target = document.querySelector(hash); 24 if (!target) { 25 return; 26 } 27 const details = target.closest("details"); 28 if (!details) { 29 return; 30 } 31 details.open = true; 32 } 33 window.addEventListener("hashchange", openTarget); 34 openTarget(); 35 36 window.addEventListener("load", function () { 37 const tablists = document.querySelectorAll('[role=tablist].automatic'); 38 for (let i = 0; i < tablists.length; i++) { 39 new Tabs(tablists[i], i === 0); 40 } 41 }); 42})(); 43 44class Tabs { 45 constructor(node, autoScroll) { 46 this.tabs = []; 47 this.firstTab = null; 48 this.lastTab = null; 49 this.tabSelected = false; 50 this.tabIndex = 0; 51 52 this.tabs = Array.from(node.querySelectorAll('[role=tab]')); 53 this.tabpanels = []; 54 55 for (let i = 0; i < this.tabs.length; i += 1) { 56 const tab = this.tabs[i]; 57 const tabpanel = document.getElementById(tab.getAttribute('aria-controls')); 58 59 tab.tabIndex = -1; 60 tab.setAttribute('aria-selected', 'false'); 61 this.tabpanels.push(tabpanel); 62 63 tab.addEventListener('keydown', this.onKeydown.bind(this)); 64 tab.addEventListener('click', this.onClick.bind(this)); 65 66 if (!this.firstTab) { 67 this.firstTab = tab; 68 } 69 this.lastTab = tab; 70 } 71 72 this.setSelectedTab(this.firstTab, false); 73 } 74 75 setSelectedTab(currentTab, setFocus = true) { 76 for (let i = 0; i < this.tabs.length; i += 1) { 77 const tab = this.tabs[i]; 78 if (currentTab === tab) { 79 tab.setAttribute('aria-selected', 'true'); 80 tab.removeAttribute('tabindex'); 81 this.tabpanels[i].classList.remove('is-hidden'); 82 if (setFocus) { 83 tab.focus(); 84 } 85 } else { 86 tab.setAttribute('aria-selected', 'false'); 87 tab.tabIndex = -1; 88 this.tabpanels[i].classList.add('is-hidden'); 89 } 90 } 91 } 92 93 setSelectedToPreviousTab(currentTab) { 94 let index; 95 if (currentTab === this.firstTab) { 96 this.setSelectedTab(this.lastTab); 97 } else { 98 index = this.tabs.indexOf(currentTab); 99 this.setSelectedTab(this.tabs[index - 1]); 100 } 101 } 102 103 setSelectedToNextTab(currentTab, setFocus = true) { 104 let index; 105 if (currentTab === this.lastTab) { 106 this.setSelectedTab(this.firstTab, setFocus); 107 } else { 108 index = this.tabs.indexOf(currentTab); 109 this.setSelectedTab(this.tabs[index + 1], setFocus); 110 } 111 } 112 113 /* EVENT HANDLERS */ 114 115 onKeydown(event) { 116 const tgt = event.currentTarget; 117 let flag = false; 118 119 switch (event.key) { 120 case 'ArrowLeft': 121 this.setSelectedToPreviousTab(tgt); 122 this.tabSelected = true; 123 flag = true; 124 break; 125 126 case 'ArrowRight': 127 this.setSelectedToNextTab(tgt); 128 this.tabSelected = true; 129 flag = true; 130 break; 131 132 case 'Home': 133 this.setSelectedTab(this.firstTab); 134 this.tabSelected = true; 135 flag = true; 136 break; 137 138 case 'End': 139 this.setSelectedTab(this.lastTab); 140 this.tabSelected = true; 141 flag = true; 142 break; 143 144 default: 145 break; 146 } 147 148 if (flag) { 149 event.stopPropagation(); 150 event.preventDefault(); 151 } 152 } 153 154 onClick(event) { 155 this.setSelectedTab(event.currentTarget); 156 this.tabSelected = true; 157 } 158 159}
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.