1// Populate the sidebar 2// 3// This is a script, and not included directly in the page, to control the total size of the book. 4// The TOC contains an entry for each page, so if each page includes a copy of the TOC, 5// the total size of the page becomes O(n**2). 6class MDBookSidebarScrollbox extends HTMLElement { 7 constructor() { 8 super(); 9 } 10 connectedCallback() { 11 this.innerHTML = '<ol class="chapter"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="index.html"><strong aria-hidden="true">1.</strong> ãã¥ã¼ããªã¢ã«æ¦è¦</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_1-1.html"><strong aria-hidden="true">1.1.</strong> CHIRIMEN ã«ã¤ãã¦</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_1-1-1.html"><strong aria-hidden="true">1.1.1.</strong> CHIRIMEN ã³ãã¥ããã£</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_1-2.html"><strong aria-hidden="true">1.2.</strong> Raspberry Pi ã«ã¤ãã¦</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_1-3.html"><strong aria-hidden="true">1.3.</strong> JavaScript ã®åºç¤</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_1-4.html"><strong aria-hidden="true">1.4.</strong> ããä½¿ãæ å ±ã¸ã®ãªã³ã¯</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_2.html"><strong aria-hidden="true">2.</strong> æ©ææºå㨠Wi-Fi ã¸ã®æ¥ç¶</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_2-1.html"><strong aria-hidden="true">2.1.</strong> ã¹ããã0ï¼æ©ææºåï¼</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_2-2.html"><strong aria-hidden="true">2.2.</strong> ã¹ããã1ï¼ã¿ã¼ããã«æ¥ç¶ï¼</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_2-2-1.html"><strong aria-hidden="true">2.2.1.</strong> Note. CLIæä½ã«ã¤ãã¦</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_2-2-2.html"><strong aria-hidden="true">2.2.2.</strong> Note. pi4 ã®å©ç¨æ¹æ³</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_2-3.html"><strong aria-hidden="true">2.3.</strong> ã¹ããã2ï¼Wi-Fiè¨å®ï¼</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_3.html"><strong aria-hidden="true">3.</strong> Hello Real Worldï¼Lãã«ãå®è¡ããï¼</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_3-1.html"><strong aria-hidden="true">3.1.</strong> é ç·</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_3-2.html"><strong aria-hidden="true">3.2.</strong> ããã°ã©ã ãæ¸ã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_3-3.html"><strong aria-hidden="true">3.3.</strong> å®è¡ãã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_3-4.html"><strong aria-hidden="true">3.4.</strong> ã³ã¼ããèªã</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_4.html"><strong aria-hidden="true">4.</strong> GPIOã試ã</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_4-1.html"><strong aria-hidden="true">4.1.</strong> GPIOãçè§£ãã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_4-2.html"><strong aria-hidden="true">4.2.</strong> GPIOãåºå</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_4-3.html"><strong aria-hidden="true">4.3.</strong>
11 GPIOãå
¥åï¼onchangeï¼</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_4-3-1.html"><strong aria-hidden="true">4.3.1.</strong> onchange ã³ã¼ããèªã</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_4-4.html"><strong aria-hidden="true">4.4.</strong> GPIOãå
¥åï¼ãã¼ãªã³ã°ï¼</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_4-4-1.html"><strong aria-hidden="true">4.4.1.</strong> ãã¼ãªã³ã°ã³ã¼ããèªã</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_4-5.html"><strong aria-hidden="true">4.5.</strong> GPIOã»ã³ãµã¼ãè¤æ°åæã«ä½¿ã</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_4-5-1.html"><strong aria-hidden="true">4.5.1.</strong> Lãã«ã®ã³ã¼ããæ¸ãæãã</a></span></li></ol></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_5.html"><strong aria-hidden="true">5.</strong> I2Cããã¤ã¹ã試ã</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_5-1.html"><strong aria-hidden="true">5.1.</strong> I2Cãçè§£ãã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_5-2.html"><strong aria-hidden="true">5.2.</strong> SHT30ç·¨</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_5-2-1.html"><strong aria-hidden="true">5.2.1.</strong> I2Cã»ã³ãµã¼(SHT30)ã®èªèã確èªãã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_5-2-2.html"><strong aria-hidden="true">5.2.2.</strong> SHT30 ã®ã³ã¼ãåå¾ã¨å®è¡</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_5-2-3.html"><strong aria-hidden="true">5.2.3.</strong> SHT30 ã®ã³ã¼ããèªã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_5-2-4.html"><strong aria-hidden="true">5.2.4.</strong> SHT30 ã®ã³ã¼ãã®è©³ç´°è§£èª¬</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_5-3.html"><strong aria-hidden="true">5.3.</strong> ADT7410ç·¨</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_5-4.html"><strong aria-hidden="true">5.4.</strong> GPIO 㨠I2Cã»ã³ãµã¼ãçµã¿åããã</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_6.html"><strong aria-hidden="true">6.</strong> IoTã試ã</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_6-1.html"><strong aria-hidden="true">6.1.</strong> é éLEDã³ã³ããã¼ã«</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_6-2.html"><strong aria-hidden="true">6.2.</strong> PiZero ãµã³ãã«ã³ã¼ãã®å®è¡</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_6-3.html"><strong aria-hidden="true">6.3.</strong> PC ãµã³ãã«ã³ã¼ãã®å®è¡</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_6-4.html"><strong aria-hidden="true">6.4.</strong> èªåå°ç¨ãã£ã³ãã«ã§å¶å¾¡</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_6-5.html"><strong aria-hidden="true">6.5.</strong> PiZero å´ã®ã³ã¼ããèªã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_6-6.html"><strong aria-hidden="true">6.6.</strong> PC å´ã®ã³ã¼ããèªã</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_7.html"><strong aria-hidden="true">7.</strong> 常é§ããã°ã©ã åãã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="using-ai-assistant.html"><strong aria-hidden="true">8.</strong> AIã¢ã·ã¹ã¿ã³ããæ´»ç¨ãã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8.html"><strong aria-hidden="true">9.</strong> ä»ã®ãããããªããã¤ã¹ã試ãã¦ã¿ã</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8-1.html"><strong aria-hidden="true">9.1.</strong> å¿ç¨ã»ã³ãµã¼ãããã®ä½¿ãæ¹</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8-1-1.html"><strong aria-hidden="true">9.1.1.</strong> åä½ã§åä½ç¢ºèªã§ããã»ã³ãµã¼</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8-1-2.html"><strong aria-hidden="true">9.1.2.</strong> 人æã»ã³ãµã¼</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8-1-3.html"><strong aria-hidden="true">9.1.3.</strong> Neopixel LED</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8-1-4.html"><strong aria-hidden="true">9.1.4.</strong> ã¢ããã°ã»ã³ãµã¼</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8-1-5.html"><strong aria-hidden="true">
119.1.5.</strong> ãµã¼ãã¢ã¼ã¿ã¼</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8-1-6.html"><strong aria-hidden="true">9.1.6.</strong> DCã¢ã¼ã¿ã¼ï¼MX1508å©ç¨ï¼</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8-1-7.html"><strong aria-hidden="true">9.1.7.</strong> DCã¢ã¼ã¿ã¼ï¼PWMé§åï¼</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_8-1-8.html"><strong aria-hidden="true">9.1.8.</strong> RaspberryPi ã®ã«ã¡ã©ã®æ³¨æç¹</a></span></li></ol></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_9.html"><strong aria-hidden="true">10.</strong> ä»é²(äºåç¥è)</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_9-1.html"><strong aria-hidden="true">10.1.</strong> CHIRIMEN ãã©ã¦ã¶ã¼çã¨ã®å·®ç°</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_9-2.html"><strong aria-hidden="true">10.2.</strong> CHIRIMENç°å¢ã®ä»»æã®ãã£ã¬ã¯ããªã¸ã®ã»ããã¢ãã</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10.html"><strong aria-hidden="true">11.</strong> å
±éè³æé</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-1.html"><strong aria-hidden="true">11.1.</strong> CHIRIMEN</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-2.html"><strong aria-hidden="true">11.2.</strong> ãã¼ãã¦ã§ã¢ã»ããã¤ã¹</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-2-1.html"><strong aria-hidden="true">11.2.1.</strong> LED</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-2-2.html"><strong aria-hidden="true">11.2.2.</strong> ãã¬ãããã¼ã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-2-3.html"><strong aria-hidden="true">11.2.3.</strong> æµæå¤ã®èªã¿æ¹</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-2-4.html"><strong aria-hidden="true">11.2.4.</strong> MOSFETã«ãã大é»åå¶å¾¡</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-3.html"><strong aria-hidden="true">11.3.</strong> JavaScript</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-3-1.html"><strong aria-hidden="true">11.3.1.</strong> JavaScriptã³ã¼ãã¨ã©ã¤ãã©ãªã®èªã¿è¾¼ã¿</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-3-2.html"><strong aria-hidden="true">11.3.2.</strong> éåæå¦ç</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-4.html"><strong aria-hidden="true">11.4.</strong> GPIO</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-4-1.html"><strong aria-hidden="true">11.4.1.</strong> GPIOãã¼ãã®åæåã¨åºåå¦ç</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-4-2.html"><strong aria-hidden="true">11.4.2.</strong> GPIOPortã®å
¥åå¦çï¼onchangeï¼</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-4-3.html"><strong aria-hidden="true">11.4.3.</strong> GPIOPortã®å
¥åå¦çï¼ãã¼ãªã³ã°ï¼</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-5.html"><strong aria-hidden="true">11.5.</strong> I2C</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-5-1.html"><strong aria-hidden="true">11.5.1.</strong>
11 å種ãã¼ãã® I2C端å</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-5-2.html"><strong aria-hidden="true">11.5.2.</strong> I2Cã®è©³ç´°æ å ±ã¨ãã¤ã³ã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-5-3.html"><strong aria-hidden="true">11.5.3.</strong> WebI2C ã¨ããã¤ã¹ãã©ã¤ã</a></span></li></ol><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6.html"><strong aria-hidden="true">11.6.</strong> IoT</a></span><ol class="section"><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6-1.html"><strong aria-hidden="true">11.6.1.</strong> webSocketã¨pub/sub services</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6-2.html"><strong aria-hidden="true">11.6.2.</strong> relayService</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6-3.html"><strong aria-hidden="true">11.6.3.</strong> ãªã¢ã«ã¿ã¤ã æ§</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6-4.html"><strong aria-hidden="true">11.6.4.</strong> relayServer.js</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6-5.html"><strong aria-hidden="true">11.6.5.</strong> ããã°ã©ã ã®æµã</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6-6.html"><strong aria-hidden="true">11.6.6.</strong> ã»ãã¥ãªãã£</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6-7.html"><strong aria-hidden="true">11.6.7.</strong> Node.jsã§ã®å©ç¨</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6-8.html"><strong aria-hidden="true">11.6.8.</strong> Webhooks</a></span></li><li class="chapter-item expanded "><span class="chapter-link-wrapper"><a href="chapter_10-6-9.html"><strong aria-hidden="true">11.6.9.</strong> IoTã¯ã©ã¦ããµã¼ãã¹</a></span></li></ol></li></ol></li></ol>'; 12 // Set the current, active page, and reveal it if it's hidden 13 let current_page = document.location.href.toString().split('#')[0].split('?')[0]; 14 if (current_page.endsWith('/')) { 15 current_page += 'index.html'; 16 } 17 const links = Array.prototype.slice.call(this.querySelectorAll('a')); 18 const l = links.length; 19 for (let i = 0; i < l; ++i) { 20 const link = links[i]; 21 const href = link.getAttribute('href'); 22 if (href && !href.startsWith('#') && !/^(?:[a-z+]+:)?\/\//.test(href)) { 23 link.href = path_to_root + href; 24 } 25 // The 'index' page is supposed to alias the first chapter in the book. 26 // Check both with and without the '.html' suffix to be robust against pretty URLs 27 if (link.href.replace(/\.html$/, '') === current_page.replace(/\.html$/, '') 28 || i === 0 29 && path_to_root === '' 30 && current_page.endsWith('/index.html')) { 31 link.classList.add('active'); 32 let parent = link.parentElement; 33 while (parent) { 34 if (parent.tagName === 'LI' && parent.classList.contains('chapter-item')) { 35 parent.classList.add('expanded'); 36 } 37 parent = parent.parentElement; 38 } 39 } 40 } 41 // Track and set sidebar scroll position 42 this.addEventListener('click', e => { 43 if (e.target.tagName === 'A') { 44 const clientRect = e.target.getBoundingClientRect(); 45 const sidebarRect = this.getBoundingClientRect(); 46 sessionStorage.setItem('sidebar-scroll-offset', clientRect.top - sidebarRect.top); 47 } 48 }, { passive: true }); 49 const sidebarScrollOffset = sessionStorage.getItem('sidebar-scroll-offset'); 50 sessionStorage.removeItem('sidebar-scroll-offset'); 51 if (sidebarScrollOffset !== null) { 52 // preserve sidebar scroll position when navigating via links within sidebar 53 const activeSection = this.querySelector('.active'); 54 if (activeSection) { 55 const clientRect = activeSection.getBoundingClientRect(); 56 const sidebarRect = this.getBoundingClientRect(); 57 const currentOffset = clientRect.top - sidebarRect.top; 58 this.scrollTop += currentOffset - parseFloat(sidebarScrollOffset); 59 } 60 } else { 61 // scroll sidebar to current active section when navigating via 62 // 'next/previous chapter' buttons 63 const activeSection = document.querySelector('#mdbook-sidebar .active'); 64 if (activeSection) { 65 activeSection.scrollIntoView({ block: 'center' }); 66 } 67 } 68 // Toggle buttons 69 const sidebarAnchorToggles = document.querySelectorAll('.chapter-fold-toggle'); 70 function toggleSection(ev) { 71 ev.currentTarget.parentElement.parentElement.classList.toggle('expanded'); 72 }
73 Array.from(sidebarAnchorToggles).forEach(el => { 74 el.addEventListener('click', toggleSection); 75 }); 76 } 77} 78window.customElements.define('mdbook-sidebar-scrollbox', MDBookSidebarScrollbox); 79 80 81// --------------------------------------------------------------------------- 82// Support for dynamically adding headers to the sidebar. 83 84(function() { 85 // This is used to detect which direction the page has scrolled since the 86 // last scroll event. 87 let lastKnownScrollPosition = 0; 88 // This is the threshold in px from the top of the screen where it will 89 // consider a header the "current" header when scrolling down. 90 const defaultDownThreshold = 150; 91 // Same as defaultDownThreshold, except when scrolling up. 92 const defaultUpThreshold = 300; 93 // The threshold is a virtual horizontal line on the screen where it 94 // considers the "current" header to be above the line. The threshold is 95 // modified dynamically to handle headers that are near the bottom of the 96 // screen, and to slightly offset the behavior when scrolling up vs down. 97 let threshold = defaultDownThreshold; 98 // This is used to disable updates while scrolling. This is needed when 99 // clicking the header in the sidebar, which triggers a scroll event. It 100 // is somewhat finicky to detect when the scroll has finished, so this 101 // uses a relatively dumb system of disabling scroll updates for a short 102 // time after the click. 103 let disableScroll = false; 104 // Array of header elements on the page. 105 let headers; 106 // Array of li elements that are initially collapsed headers in the sidebar. 107 // I'm not sure why eslint seems to have a false positive here. 108 // eslint-disable-next-line prefer-const 109 let headerToggles = []; 110 // This is a debugging tool for the threshold which you can enable in the console. 111 let thresholdDebug = false; 112 113 // Updates the threshold based on the scroll position. 114 function updateThreshold() { 115 const scrollTop = window.pageYOffset || document.documentElement.scrollTop; 116 const windowHeight = window.innerHeight; 117 const documentHeight = document.documentElement.scrollHeight; 118 119 // The number of pixels below the viewport, at most documentHeight. 120 // This is used to push the threshold down to the bottom of the page 121 // as the user scrolls towards the bottom. 122 const pixelsBelow = Math.max(0, documentHeight - (scrollTop + windowHeight)); 123 // The number of pixels above the viewport, at least defaultDownThreshold. 124 // Similar to pixelsBelow, this is used to push the threshold back towards 125 // the top when reaching the top of the page. 126 const pixelsAbove = Math.max(0, defaultDownThreshold - scrollTop); 127 // How much the threshold should be offset once it gets close to the 128 // bottom of the page. 129 const bottomAdd = Math.max(0, windowHeight - pixelsBelow - defaultDownThreshold); 130 let adjustedBottomAdd = bottomAdd; 131 132 // Adjusts bottomAdd for a small document. The calculation above 133 // assumes the document is at least twice the windowheight in size. If 134 // it is less than that, then bottomAdd needs to be shrunk 135 // proportional to the difference in size. 136 if (documentHeight < windowHeight * 2) { 137 const maxPixelsBelow = documentHeight - windowHeight; 138 const t = 1 - pixelsBelow / Math.max(1, maxPixelsBelow); 139 const clamp = Math.max(0, Math.min(1, t)); 140 adjustedBottomAdd *= clamp; 141 } 142 143 let scrollingDown = true; 144 if (scrollTop < lastKnownScrollPosition) { 145 scrollingDown = false; 146 } 147 148 if (scrollingDown) { 149 // When scrolling down, move the threshold up towards the default 150 // downwards threshold position. If near the bottom of the page, 151 // adjustedBottomAdd will offset the threshold towards the bottom 152 // of the page. 153 const amountScrolledDown = scrollTop - lastKnownScrollPosition; 154 const adjustedDefault = defaultDownThreshold + adjustedBottomAdd; 155 threshold = Math.max(adjustedDefault, threshold - amountScrolledDown); 156 } else { 157 // When scrolling up, move the threshold down towards the default 158 // upwards threshold position. If near the bottom of the page, 159 // quickly transition the threshold back up where it normally 160 // belongs. 161 const amountScrolledUp = lastKnownScrollPosition - scrollTop; 162 const adjustedDefault = defaultUpThreshold - pixelsAbove 163 + Math.max(0, adjustedBottomAdd - defaultDownThreshold); 164 threshold = Math.min(adjustedDefault, threshold + amountScrolledUp); 165 } 166 167 if (documentHeight <= windowHeight) { 168 threshold = 0; 169 } 170 171 if (thresholdDebug) { 172 const id = 'mdbook-threshold-debug-data'; 173 let data = document.getElementById(id); 174 if (data === null) { 175 data = document.createElement('div'); 176 data.id = id; 177 data.style.cssText = `
178 position: fixed; 179 top: 50px; 180 right: 10px; 181 background-color: 0xeeeeee; 182 z-index: 9999; 183 pointer-events: none; 184 `; 185 document.body.appendChild(data); 186 } 187 data.innerHTML = ` 188 <table> 189 <tr><td>documentHeight</td><td>${documentHeight.toFixed(1)}</td></tr> 190 <tr><td>windowHeight</td><td>${windowHeight.toFixed(1)}</td></tr> 191 <tr><td>scrollTop</td><td>${scrollTop.toFixed(1)}</td></tr> 192 <tr><td>pixelsAbove</td><td>${pixelsAbove.toFixed(1)}</td></tr> 193 <tr><td>pixelsBelow</td><td>${pixelsBelow.toFixed(1)}</td></tr> 194 <tr><td>bottomAdd</td><td>${bottomAdd.toFixed(1)}</td></tr> 195 <tr><td>adjustedBottomAdd</td><td>${adjustedBottomAdd.toFixed(1)}</td></tr> 196 <tr><td>scrollingDown</td><td>${scrollingDown}</td></tr> 197 <tr><td>threshold</td><td>${threshold.toFixed(1)}</td></tr> 198 </table> 199 `; 200 drawDebugLine(); 201 } 202 203 lastKnownScrollPosition = scrollTop; 204 } 205 206 function drawDebugLine() { 207 if (!document.body) { 208 return; 209 } 210 const id = 'mdbook-threshold-debug-line'; 211 const existingLine = document.getElementById(id); 212 if (existingLine) { 213 existingLine.remove(); 214 } 215 const line = document.createElement('div'); 216 line.id = id; 217 line.style.cssText = ` 218 position: fixed; 219 top: ${threshold}px; 220 left: 0; 221 width: 100vw; 222 height: 2px; 223 background-color: red; 224 z-index: 9999; 225 pointer-events: none; 226 `; 227 document.body.appendChild(line); 228 } 229 230 function mdbookEnableThresholdDebug() { 231 thresholdDebug = true; 232 updateThreshold(); 233 drawDebugLine(); 234 } 235 236 window.mdbookEnableThresholdDebug = mdbookEnableThresholdDebug; 237 238 // Updates which headers in the sidebar should be expanded. If the current 239 // header is inside a collapsed group, then it, and all its parents should 240 // be expanded. 241 function updateHeaderExpanded(currentA) { 242 // Add expanded to all header-item li ancestors. 243 let current = currentA.parentElement; 244 while (current) { 245 if (current.tagName === 'LI' && current.classList.contains('header-item')) { 246 current.classList.add('expanded'); 247 } 248 current = current.parentElement; 249 } 250 } 251 252 // Updates which header is marked as the "current" header in the sidebar. 253 // This is done with a virtual Y threshold, where headers at or below 254 // that line will be considered the current one. 255 function updateCurrentHeader() { 256 if (!headers || !headers.length) { 257 return; 258 } 259 260 // Reset the classes, which will be rebuilt below. 261 const els = document.getElementsByClassName('current-header'); 262 for (const el of els) { 263 el.classList.remove('current-header'); 264 } 265 for (const toggle of headerToggles) { 266 toggle.classList.remove('expanded'); 267 } 268 269 // Find the last header that is above the threshold. 270 let lastHeader = null; 271 for (const header of headers) { 272 const rect = header.getBoundingClientRect(); 273 if (rect.top <= threshold) { 274 lastHeader = header; 275 } else { 276 break; 277 } 278 } 279 if (lastHeader === null) { 280 lastHeader = headers[0]; 281 const rect = lastHeader.getBoundingClientRect(); 282 const windowHeight = window.innerHeight; 283 if (rect.top >= windowHeight) { 284 return; 285 } 286 } 287 288 // Get the anchor in the summary. 289 const href = '#' + lastHeader.id; 290 const a = [...document.querySelectorAll('.header-in-summary')] 291 .find(element => element.getAttribute('href') === href); 292 if (!a) { 293 return; 294 } 295 296 a.classList.add('current-header'); 297 298 updateHeaderExpanded(a); 299 } 300 301 // Updates which header is "current" based on the threshold line. 302 function reloadCurrentHeader() { 303 if (disableScroll) { 304 return; 305 } 306 updateThreshold(); 307 updateCurrentHeader(); 308 } 309 310 311 // When clicking on a header in the sidebar, this adjusts the threshold so 312 // that it is located next to the header. This is so that header becomes 313 // "current". 314 function headerThresholdClick(event) { 315 // See disableScroll description why this is done. 316 disableScroll = true; 317 setTimeout(() => { 318 disableScroll = false;
319 }, 100); 320 // requestAnimationFrame is used to delay the update of the "current" 321 // header until after the scroll is done, and the header is in the new 322 // position. 323 requestAnimationFrame(() => { 324 requestAnimationFrame(() => { 325 // Closest is needed because if it has child elements like <code>. 326 const a = event.target.closest('a'); 327 const href = a.getAttribute('href'); 328 const targetId = href.substring(1); 329 const targetElement = document.getElementById(targetId); 330 if (targetElement) { 331 threshold = targetElement.getBoundingClientRect().bottom; 332 updateCurrentHeader(); 333 } 334 }); 335 }); 336 } 337 338 // Takes the nodes from the given head and copies them over to the 339 // destination, along with some filtering. 340 function filterHeader(source, dest) { 341 const clone = source.cloneNode(true); 342 clone.querySelectorAll('mark').forEach(mark => { 343 mark.replaceWith(...mark.childNodes); 344 }); 345 dest.append(...clone.childNodes); 346 } 347 348 // Scans page for headers and adds them to the sidebar. 349 document.addEventListener('DOMContentLoaded', function() { 350 const activeSection = document.querySelector('#mdbook-sidebar .active'); 351 if (activeSection === null) { 352 return; 353 } 354 355 const main = document.getElementsByTagName('main')[0]; 356 headers = Array.from(main.querySelectorAll('h2, h3, h4, h5, h6')) 357 .filter(h => h.id !== '' && h.children.length && h.children[0].tagName === 'A'); 358 359 if (headers.length === 0) { 360 return; 361 } 362 363 // Build a tree of headers in the sidebar. 364 365 const stack = []; 366 367 const firstLevel = parseInt(headers[0].tagName.charAt(1)); 368 for (let i = 1; i < firstLevel; i++) { 369 const ol = document.createElement('ol'); 370 ol.classList.add('section'); 371 if (stack.length > 0) { 372 stack[stack.length - 1].ol.appendChild(ol); 373 } 374 stack.push({level: i + 1, ol: ol}); 375 } 376 377 // The level where it will start folding deeply nested headers. 378 const foldLevel = 3; 379 380 for (let i = 0; i < headers.length; i++) { 381 const header = headers[i]; 382 const level = parseInt(header.tagName.charAt(1)); 383 384 const currentLevel = stack[stack.length - 1].level; 385 if (level > currentLevel) { 386 // Begin nesting to this level. 387 for (let nextLevel = currentLevel + 1; nextLevel <= level; nextLevel++) { 388 const ol = document.createElement('ol'); 389 ol.classList.add('section'); 390 const last = stack[stack.length - 1]; 391 const lastChild = last.ol.lastChild; 392 // Handle the case where jumping more than one nesting 393 // level, which doesn't have a list item to place this new 394 // list inside of. 395 if (lastChild) { 396 lastChild.appendChild(ol); 397 } else { 398 last.ol.appendChild(ol); 399 } 400 stack.push({level: nextLevel, ol: ol}); 401 } 402 } else if (level < currentLevel) { 403 while (stack.length > 1 && stack[stack.length - 1].level > level) { 404 stack.pop(); 405 } 406 } 407 408 const li = document.createElement('li'); 409 li.classList.add('header-item'); 410 li.classList.add('expanded'); 411 if (level < foldLevel) { 412 li.classList.add('expanded'); 413 } 414 const span = document.createElement('span'); 415 span.classList.add('chapter-link-wrapper'); 416 const a = document.createElement('a'); 417 span.appendChild(a); 418 a.href = '#' + header.id; 419 a.classList.add('header-in-summary'); 420 filterHeader(header.children[0], a); 421 a.addEventListener('click', headerThresholdClick); 422 const nextHeader = headers[i + 1]; 423 if (nextHeader !== undefined) { 424 const nextLevel = parseInt(nextHeader.tagName.charAt(1)); 425 if (nextLevel > level && level >= foldLevel) { 426 const toggle = document.createElement('a'); 427 toggle.classList.add('chapter-fold-toggle'); 428 toggle.classList.add('header-toggle'); 429 toggle.addEventListener('click', () => { 430 li.classList.toggle('expanded'); 431 }); 432 const toggleDiv = document.createElement('div'); 433 toggleDiv.textContent = 'â±'; 434 toggle.appendChild(toggleDiv); 435 span.appendChild(toggle); 436 headerToggles.push(li); 437 } 438 } 439 li.appendChild(span); 440 441 const currentParent = stack[stack.length - 1]; 442 currentParent.ol.appendChild(li); 443 } 444 445 const onThisPage = document.createElement('div'); 446 onThisPage.classList.add('on-this-page'); 447 onThisPage.append(stack[0].ol); 448 const activeItemSpan = activeSection.parentElement; 449 activeItemSpan.after(onThisPage); 450 }); 451 452 document.addEventListener('DOMContentLoaded', reloadCurrentHeader); 453 document.addEventListener('scroll', reloadCurrentHeader, { passive: true }); 454})(); 455
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.