1/** 2 * Add Toggle Buttons to elements 3 */ 4 5let toggleChevron = ` 6<svg xmlns="http://www.w3.org/2000/svg" class="tb-icon toggle-chevron-right" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round"> 7<path stroke="none" d="M0 0h24v24H0z" fill="none"/> 8<polyline points="9 6 15 12 9 18" /> 9</svg>`; 10 11var initToggleItems = () => { 12 var itemsToToggle = document.querySelectorAll(togglebuttonSelector); 13 console.log(`[togglebutton]: Adding toggle buttons to ${itemsToToggle.length} items`) 14 // Add the button to each admonition and hook up a callback to toggle visibility 15 itemsToToggle.forEach((item, index) => { 16 if (item.classList.contains("admonition")) { 17 // If it's an admonition block, then we'll add a button inside 18 // Generate unique IDs for this item 19 var toggleID = `toggle-${index}`; 20 var buttonID = `button-${toggleID}`; 21 22 item.setAttribute('id', toggleID); 23 if (!item.classList.contains("toggle")){ 24 item.classList.add("toggle"); 25 } 26 // This is the button that will be added to each item to trigger the toggle 27 var collapseButton = ` 28 <button type="button" id="${buttonID}" class="toggle-button" data-target="${toggleID}" data-button="${buttonID}" data-toggle-hint="${toggleHintShow}" aria-label="Toggle hidden content"> 29 ${toggleChevron} 30 </button>`; 31 32 title = item.querySelector(".admonition-title") 33 title.insertAdjacentHTML("beforeend", collapseButton); 34 thisButton = document.getElementById(buttonID); 35 36 // Add click handlers for the button + admonition title (if admonition) 37 admonitionTitle = document.querySelector(`#${toggleID} > .admonition-title`) 38 if (admonitionTitle) { 39 // If an admonition, then make the whole title block clickable 40 admonitionTitle.addEventListener('click', toggleClickHandler); 41 admonitionTitle.dataset.target = toggleID 42 admonitionTitle.dataset.button = buttonID 43 } else { 44 // If not an admonition then we'll listen for the button click 45 thisButton.addEventListener('click', toggleClickHandler); 46 } 47 48 // Now hide the item for this toggle button unless explicitly noted to show 49 if (!item.classList.contains("toggle-shown")) { 50 toggleHidden(thisButton); 51 } 52 } else { 53 // If not an admonition, wrap the block in a <details> block 54 // Define the structure of the details block and insert it as a sibling 55 var detailsBlock = ` 56 <details class="toggle-details"> 57 <summary class="toggle-details__summary"> 58 ${toggleChevron} 59 <span class="toggle-details__summary-text">${toggleHintShow}</span> 60 </summary> 61 </details>`; 62 item.insertAdjacentHTML("beforebegin", detailsBlock); 63 64 // Now move the toggle-able content inside of the details block 65 details = item.previousElementSibling 66 details.appendChild(item) 67 item.classList.add("toggle-details__container") 68 69 // Set up a click trigger to change the text as needed 70 details.addEventListener('click', (click) => { 71 let parent = click.target.parentElement; 72 if (parent.tagName.toLowerCase() == "details") { 73 summary = parent.querySelector("summary"); 74 details = parent; 75 } else { 76 summary = parent; 77 details = parent.parentElement; 78 } 79 // Update the inner text for the proper hint 80 if (details.open) { 81 summary.querySelector("span.toggle-details__summary-text").innerText = toggleHintShow; 82 } else { 83 summary.querySelector("span.toggle-details__summary-text").innerText = toggleHintHide; 84 } 85 86 }); 87 88 // If we have a toggle-shown class, open details block should be open 89 if (item.classList.contains("toggle-shown")) { 90 details.click(); 91 } 92 } 93 }) 94}; 95 96// This should simply add / remove the collapsed class and change the button text 97var toggleHidden = (button) => { 98 target = button.dataset['target'] 99 var itemToToggle = document.getElementById(target); 100 if (itemToToggle.classList.contains("toggle-hidden")) { 101 itemToToggle.classList.remove("toggle-hidden"); 102 button.classList.remove("toggle-button-hidden"); 103 } else { 104 itemToToggle.classList.add("toggle-hidden"); 105 button.classList.add("toggle-button-hidden"); 106 } 107} 108 109var toggleClickHandler = (click) => { 110 // Be cause the admonition title is clickable and extends to the whole admonition 111 // We only look for a click event on this title to trigger the toggle. 112 113 if (click.target.classList.contains("admonition-title")) { 114 button = click.target.querySelector(".toggle-button"); 115 } else if (click.target.classList.contains("tb-icon")) { 116 // We've clicked the icon and need to search up one parent for the button 117 button = click.target.parentElement; 118 } else if (click.target.tagName == "polyline") { 119 // We've clicked the SVG elements inside the button, need to up 2 layers 120 button = click.target.parentElement.parentElement; 121 } else if (click.target.classList.contains("toggle-button")) { 122 // We've clicked the button itself and so don't need to do anything 123 button = click.target; 124 } else { 125 console.log(`[togglebutton]: Couldn't find button for ${click.target}`) 126 } 127 target = document.getElementById(button.dataset['button']); 128 toggleHidden(target); 129} 130 131// If we want to blanket-add toggle classes to certain cells 132var addToggleToSelector = () => { 133 const selector = ""; 134 if (selector.length > 0) { 135 document.querySelectorAll(selector).forEach((item) => { 136 item.classList.add("toggle"); 137 }) 138 } 139} 140 141// Helper function to run when the DOM is finished 142const sphinxToggleRunWhenDOMLoaded = cb => { 143 if (document.readyState != 'loading') { 144 cb() 145 } else if (document.addEventListener) { 146 document.addEventListener('DOMContentLoaded', cb) 147 } else { 148 document.attachEvent('onreadystatechange', function() { 149 if (document.readyState == 'complete') cb() 150 }) 151 } 152} 153sphinxToggleRunWhenDOMLoaded(addToggleToSelector) 154sphinxToggleRunWhenDOMLoaded(initToggleItems) 155 156/** Toggle details blocks to be open when printing */ 157if (toggleOpenOnPrint == "true") { 158 window.addEventListener("beforeprint", () => { 159 // Open the details 160 document.querySelectorAll("details.toggle-details").forEach((el) => { 161 el.dataset["togglestatus"] = el.open; 162 el.open = true; 163 }); 164 165 // Open the admonitions 166 document.querySelectorAll(".admonition.toggle.toggle-hidden").forEach((el) => { 167 console.log(el); 168 el.querySelector("button.toggle-button").click(); 169 el.dataset["toggle_after_print"] = "true"; 170 }); 171 }); 172 window.addEventListener("afterprint", () => { 173 // Re-close the details that were closed 174 document.querySelectorAll("details.toggle-details").forEach((el) => { 175 el.open = el.dataset["togglestatus"] == "true"; 176 delete el.dataset["togglestatus"]; 177 }); 178 179 // Re-close the admonition toggle buttons 180 document.querySelectorAll(".admonition.toggle").forEach((el) => { 181 if (el.dataset["toggle_after_print"] == "true") { 182 el.querySelector("button.toggle-button").click(); 183 delete el.dataset["toggle_after_print"]; 184 } 185 }); 186 }); 187}
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.