Spaces:
Running
Running
| /** | |
| * Add Toggle Buttons to elements | |
| */ | |
| let toggleChevron = ` | |
| <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"> | |
| <path stroke="none" d="M0 0h24v24H0z" fill="none"/> | |
| <polyline points="9 6 15 12 9 18" /> | |
| </svg>`; | |
| var initToggleItems = () => { | |
| var itemsToToggle = document.querySelectorAll(togglebuttonSelector); | |
| console.log(`[togglebutton]: Adding toggle buttons to ${itemsToToggle.length} items`) | |
| // Add the button to each admonition and hook up a callback to toggle visibility | |
| itemsToToggle.forEach((item, index) => { | |
| if (item.classList.contains("admonition")) { | |
| // If it's an admonition block, then we'll add a button inside | |
| // Generate unique IDs for this item | |
| var toggleID = `toggle-${index}`; | |
| var buttonID = `button-${toggleID}`; | |
| item.setAttribute('id', toggleID); | |
| if (!item.classList.contains("toggle")){ | |
| item.classList.add("toggle"); | |
| } | |
| // This is the button that will be added to each item to trigger the toggle | |
| var collapseButton = ` | |
| <button type="button" id="${buttonID}" class="toggle-button" data-target="${toggleID}" data-button="${buttonID}" data-toggle-hint="${toggleHintShow}" aria-label="Toggle hidden content"> | |
| ${toggleChevron} | |
| </button>`; | |
| title = item.querySelector(".admonition-title") | |
| title.insertAdjacentHTML("beforeend", collapseButton); | |
| thisButton = document.getElementById(buttonID); | |
| // Add click handlers for the button + admonition title (if admonition) | |
| admonitionTitle = document.querySelector(`#${toggleID} > .admonition-title`) | |
| if (admonitionTitle) { | |
| // If an admonition, then make the whole title block clickable | |
| admonitionTitle.addEventListener('click', toggleClickHandler); | |
| admonitionTitle.dataset.target = toggleID | |
| admonitionTitle.dataset.button = buttonID | |
| } else { | |
| // If not an admonition then we'll listen for the button click | |
| thisButton.addEventListener('click', toggleClickHandler); | |
| } | |
| // Now hide the item for this toggle button unless explicitly noted to show | |
| if (!item.classList.contains("toggle-shown")) { | |
| toggleHidden(thisButton); | |
| } | |
| } else { | |
| // If not an admonition, wrap the block in a <details> block | |
| // Define the structure of the details block and insert it as a sibling | |
| var detailsBlock = ` | |
| <details class="toggle-details"> | |
| <summary class="toggle-details__summary"> | |
| ${toggleChevron} | |
| <span class="toggle-details__summary-text">${toggleHintShow}</span> | |
| </summary> | |
| </details>`; | |
| item.insertAdjacentHTML("beforebegin", detailsBlock); | |
| // Now move the toggle-able content inside of the details block | |
| details = item.previousElementSibling | |
| details.appendChild(item) | |
| item.classList.add("toggle-details__container") | |
| // Set up a click trigger to change the text as needed | |
| details.addEventListener('click', (click) => { | |
| let parent = click.target.parentElement; | |
| if (parent.tagName.toLowerCase() == "details") { | |
| summary = parent.querySelector("summary"); | |
| details = parent; | |
| } else { | |
| summary = parent; | |
| details = parent.parentElement; | |
| } | |
| // Update the inner text for the proper hint | |
| if (details.open) { | |
| summary.querySelector("span.toggle-details__summary-text").innerText = toggleHintShow; | |
| } else { | |
| summary.querySelector("span.toggle-details__summary-text").innerText = toggleHintHide; | |
| } | |
| }); | |
| // If we have a toggle-shown class, open details block should be open | |
| if (item.classList.contains("toggle-shown")) { | |
| details.click(); | |
| } | |
| } | |
| }) | |
| }; | |
| // This should simply add / remove the collapsed class and change the button text | |
| var toggleHidden = (button) => { | |
| target = button.dataset['target'] | |
| var itemToToggle = document.getElementById(target); | |
| if (itemToToggle.classList.contains("toggle-hidden")) { | |
| itemToToggle.classList.remove("toggle-hidden"); | |
| button.classList.remove("toggle-button-hidden"); | |
| } else { | |
| itemToToggle.classList.add("toggle-hidden"); | |
| button.classList.add("toggle-button-hidden"); | |
| } | |
| } | |
| var toggleClickHandler = (click) => { | |
| // Be cause the admonition title is clickable and extends to the whole admonition | |
| // We only look for a click event on this title to trigger the toggle. | |
| if (click.target.classList.contains("admonition-title")) { | |
| button = click.target.querySelector(".toggle-button"); | |
| } else if (click.target.classList.contains("tb-icon")) { | |
| // We've clicked the icon and need to search up one parent for the button | |
| button = click.target.parentElement; | |
| } else if (click.target.tagName == "polyline") { | |
| // We've clicked the SVG elements inside the button, need to up 2 layers | |
| button = click.target.parentElement.parentElement; | |
| } else if (click.target.classList.contains("toggle-button")) { | |
| // We've clicked the button itself and so don't need to do anything | |
| button = click.target; | |
| } else { | |
| console.log(`[togglebutton]: Couldn't find button for ${click.target}`) | |
| } | |
| target = document.getElementById(button.dataset['button']); | |
| toggleHidden(target); | |
| } | |
| // If we want to blanket-add toggle classes to certain cells | |
| var addToggleToSelector = () => { | |
| const selector = ""; | |
| if (selector.length > 0) { | |
| document.querySelectorAll(selector).forEach((item) => { | |
| item.classList.add("toggle"); | |
| }) | |
| } | |
| } | |
| // Helper function to run when the DOM is finished | |
| const sphinxToggleRunWhenDOMLoaded = cb => { | |
| if (document.readyState != 'loading') { | |
| cb() | |
| } else if (document.addEventListener) { | |
| document.addEventListener('DOMContentLoaded', cb) | |
| } else { | |
| document.attachEvent('onreadystatechange', function() { | |
| if (document.readyState == 'complete') cb() | |
| }) | |
| } | |
| } | |
| sphinxToggleRunWhenDOMLoaded(addToggleToSelector) | |
| sphinxToggleRunWhenDOMLoaded(initToggleItems) | |
| /** Toggle details blocks to be open when printing */ | |
| if (toggleOpenOnPrint == "true") { | |
| window.addEventListener("beforeprint", () => { | |
| // Open the details | |
| document.querySelectorAll("details.toggle-details").forEach((el) => { | |
| el.dataset["togglestatus"] = el.open; | |
| el.open = true; | |
| }); | |
| // Open the admonitions | |
| document.querySelectorAll(".admonition.toggle.toggle-hidden").forEach((el) => { | |
| console.log(el); | |
| el.querySelector("button.toggle-button").click(); | |
| el.dataset["toggle_after_print"] = "true"; | |
| }); | |
| }); | |
| window.addEventListener("afterprint", () => { | |
| // Re-close the details that were closed | |
| document.querySelectorAll("details.toggle-details").forEach((el) => { | |
| el.open = el.dataset["togglestatus"] == "true"; | |
| delete el.dataset["togglestatus"]; | |
| }); | |
| // Re-close the admonition toggle buttons | |
| document.querySelectorAll(".admonition.toggle").forEach((el) => { | |
| if (el.dataset["toggle_after_print"] == "true") { | |
| el.querySelector("button.toggle-button").click(); | |
| delete el.dataset["toggle_after_print"]; | |
| } | |
| }); | |
| }); | |
| } | |