1(function (jtd, undefined) { 2 3// Event handling 4 5jtd.addEvent = function(el, type, handler) { 6 if (el.attachEvent) el.attachEvent('on'+type, handler); else el.addEventListener(type, handler); 7} 8jtd.removeEvent = function(el, type, handler) { 9 if (el.detachEvent) el.detachEvent('on'+type, handler); else el.removeEventListener(type, handler); 10} 11jtd.onReady = function(ready) { 12 // in case the document is already rendered 13 if (document.readyState!='loading') ready(); 14 // modern browsers 15 else if (document.addEventListener) document.addEventListener('DOMContentLoaded', ready); 16 // IE <= 8 17 else document.attachEvent('onreadystatechange', function(){ 18 if (document.readyState=='complete') ready(); 19 }); 20} 21 22// Show/hide mobile menu 23 24function initNav() { 25 jtd.addEvent(document, 'click', function(e){ 26 var target = e.target; 27 while (target && !(target.classList && target.classList.contains('nav-list-expander'))) { 28 target = target.parentNode; 29 } 30 if (target) { 31 e.preventDefault(); 32 target.ariaExpanded = target.parentNode.classList.toggle('active'); 33 } 34 }); 35 36 const siteNav = document.getElementById('site-nav'); 37 const mainHeader = document.getElementById('main-header'); 38 const menuButton = document.getElementById('menu-button'); 39 40 disableHeadStyleSheets(); 41 42 jtd.addEvent(menuButton, 'click', function(e){ 43 e.preventDefault(); 44 45 if (menuButton.classList.toggle('nav-open')) { 46 siteNav.classList.add('nav-open'); 47 mainHeader.classList.add('nav-open'); 48 menuButton.ariaExpanded = true; 49 } else { 50 siteNav.classList.remove('nav-open'); 51 mainHeader.classList.remove('nav-open'); 52 menuButton.ariaExpanded = false; 53 } 54 }); 55} 56 57// The <head> element is assumed to include the following stylesheets: 58// - a <link> to /assets/css/just-the-docs-head-nav.css, 59// with id 'jtd-head-nav-stylesheet' 60// - a <style> containing the result of _includes/css/activation.scss.liquid. 61// To avoid relying on the order of stylesheets (which can change with HTML 62// compression, user-added JavaScript, and other side effects), stylesheets 63// are only interacted with via ID 64 65function disableHeadStyleSheets() { 66 const headNav = document.getElementById('jtd-head-nav-stylesheet'); 67 if (headNav) { 68 headNav.disabled = true; 69 } 70 71 const activation = document.getElementById('jtd-nav-activation'); 72 if (activation) { 73 activation.disabled = true; 74 } 75} 76 77// Switch theme 78 79jtd.getTheme = function() { 80 var cssFileHref = document.querySelector('[rel="stylesheet"]').getAttribute('href'); 81 return cssFileHref.substring(cssFileHref.lastIndexOf('-') + 1, cssFileHref.length - 4); 82} 83 84jtd.setTheme = function(theme) { 85 var cssFile = document.querySelector('[rel="stylesheet"]'); 86 cssFile.setAttribute('href', '/assets/css/just-the-docs-' + theme + '.css'); 87} 88 89// Note: pathname can have a trailing slash on a local jekyll server 90// and not have the slash on GitHub Pages 91 92function navLink() { 93 var pathname = document.location.pathname; 94 95 var navLink = document.getElementById('site-nav').querySelector('a[href="' + pathname + '"]'); 96 if (navLink) { 97 return navLink; 98 } 99 100 // The `permalink` setting may produce navigation links whose `href` ends with `/` or `.html`. 101 // To find these links when `/` is omitted from or added to pathname, or `.html` is omitted: 102 103 if (pathname.endsWith('/') && pathname != '/') { 104 pathname = pathname.slice(0, -1); 105 } 106 107 if (pathname != '/') { 108 navLink = document.getElementById('site-nav').querySelector('a[href="' + pathname + '"], a[href="' + pathname + '/"], a[href="' + pathname + '.html"]'); 109 if (navLink) { 110 return navLink; 111 } 112 } 113 114 return null; // avoids `undefined` 115} 116 117// Scroll site-nav to ensure the link to the current page is visible 118 119function scrollNav() { 120 const targetLink = navLink(); 121 if (targetLink) { 122 targetLink.scrollIntoView({ block: "center" }); 123 targetLink.removeAttribute('href'); 124 } 125} 126 127// Find the nav-list-link that refers to the current page 128// then make it and all enclosing nav-list-item elements active. 129 130function activateNav() { 131 var target = navLink(); 132 if (target) { 133 target.classList.toggle('active', true); 134 } 135 while (target) { 136 while (target && !(target.classList && target.classList.contains('nav-list-item'))) { 137 target = target.parentNode; 138 } 139 if (target) { 140 target.classList.toggle('active', true); 141 target = target.parentNode; 142 } 143 } 144} 145 146// Document ready 147 148jtd.onReady(function(){ 149 if (document.getElementById('site-nav')) { 150 initNav(); 151 activateNav(); 152 scrollNav(); 153 } 154}); 155 156// Accessibility: set tabindex=0 on each code highlight block, so screenreaders 157// can focus over (particularly important if there's horizontal scroll) 158// see: https://dequeuniversity.com/rules/axe/4.9/scrollable-region-focusable?application=a
158xeAPI 159 160jtd.onReady(() => { 161 document 162 .querySelectorAll("div.highlight") 163 .forEach(codeBlock => codeBlock.setAttribute("tabindex", "0")); 164}); 165 166// Copy button on code 167 168jtd.onReady(function(){ 169 170 if (!window.isSecureContext) { 171 console.log('Window does not have a secure context, therefore code clipboard copy functionality will not be available. For more details see https://web.dev/async-clipboard/#security-and-permissions'); 172 return; 173 } 174 175 var codeBlocks = document.querySelectorAll('div.highlighter-rouge, div.listingblock > div.content, figure.highlight'); 176 177 // note: the SVG svg-copied and svg-copy is only loaded as a Jekyll include if site.enable_copy_code_button is true; see _includes/icons/icons.html 178 var svgCopied = '<svg viewBox="0 0 24 24" class="copy-icon"><use xlink:href="#svg-copied"></use></svg>'; 179 var svgCopy = '<svg viewBox="0 0 24 24" class="copy-icon"><use xlink:href="#svg-copy"></use></svg>'; 180 181 codeBlocks.forEach(codeBlock => { 182 var copyButton = document.createElement('button'); 183 var timeout = null; 184 copyButton.type = 'button'; 185 copyButton.ariaLabel = 'Copy code to clipboard'; 186 copyButton.innerHTML = svgCopy; 187 codeBlock.append(copyButton); 188 189 copyButton.addEventListener('click', function () { 190 if(timeout === null) { 191 var code = (codeBlock.querySelector('pre:not(.lineno, .highlight)') || codeBlock.querySelector('code')).innerText; 192 window.navigator.clipboard.writeText(code); 193 194 copyButton.innerHTML = svgCopied; 195 196 var timeoutSetting = 4000; 197 198 timeout = setTimeout(function () { 199 copyButton.innerHTML = svgCopy; 200 timeout = null; 201 }, timeoutSetting); 202 } 203 }); 204 }); 205 206}); 207 208})(window.jtd = window.jtd || {}); 209 210
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.