PageSourceSearch

https://nemos-neuro.org/en/latest/_static/togglebutton.js?v=b8b12719

js nemos-neuro.org collected 2026-09-29 07:29:15 UTC 9,547 bytes, 257 lines download raw bytes

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(
14    `[togglebutton]: Adding toggle buttons to ${itemsToToggle.length} items`
15  );
16  // Add the button to each admonition and hook up a callback to toggle visibility
17  itemsToToggle.forEach((item, index) => {
18    if (item.classList.contains("admonition")) {
19      // If it's an admonition block, then we'll add a button inside
20      // Generate unique IDs for this item,
21      // IF AND ONLY IF THE ITEM DOESN'T ALREADY HAVE AN ID
22      if (!item.id) {
23        var toggleID = `toggle-${index}`;
24      } else {
25        var toggleID = item.id;
26      }
27      var buttonID = `button-${toggleID}`;
28
29      item.setAttribute("id", toggleID);
30      if (!item.classList.contains("toggle")) {
31        item.classList.add("toggle");
32      }
33      // This is the button that will be added to each item to trigger the toggle
34      var collapseButton = `
35        <button type="button"
36                id="${buttonID}"
37                class="toggle-button"
38                data-target="${toggleID}"
39                data-button="${buttonID}"
40                data-toggle-hint="${toggleHintShow}"
41                aria-label="Toggle hidden content"
42                aria-expanded="false"
43            >
44            ${toggleChevron}
45        </button>`;
46
47      title = item.querySelector(".admonition-title");
48      title.insertAdjacentHTML("beforeend", collapseButton);
49      thisButton = document.getElementById(buttonID);
50
51      // Add click handlers for the button + admonition title (if admonition)
52      admonitionTitle = document.querySelector(
53        `#` + CSS.escape(toggleID) + ` > .admonition-title`
54      );
55      if (admonitionTitle) {
56        // If an admonition, then make the whole title block clickable
57        admonitionTitle.addEventListener("click", toggleClickHandler);
58        admonitionTitle.dataset.target = toggleID;
59        admonitionTitle.dataset.button = buttonID;
60      } else {
61        // If not an admonition then we'll listen for the button click
62        thisButton.addEventListener("click", toggleClickHandler);
63      }
64
65      // Now hide the item for this toggle button unless explicitly noted to show
66      if (!item.classList.contains("toggle-shown")) {
67        toggleHidden(thisButton);
68      }
69    } else {
70      // If not an admonition, wrap the block in a <details> block
71      // Define the structure of the details block and insert it as a sibling
72      var detailsBlock = `
73        <details class="toggle-details">
74            <summary class="toggle-details__summary">
75              ${toggleChevron}
76              <span class="toggle-details__summary-text">${toggleHintShow}</span>
77            </summary>
78        </details>`;
79      item.insertAdjacentHTML("beforebegin", detailsBlock);
80
81      // Now move the toggle-able content inside of the details block
82      details = item.previousElementSibling;
83      details.appendChild(item);
84      item.classList.add("toggle-details__container");
85
86      // Set up a click trigger to change the text as needed
87      details.addEventListener("click", (click) => {
88        let parent = click.target.parentElement;
89        if (parent.tagName.toLowerCase() == "details") {
90          summary = parent.querySelector("summary");
91          details = parent;
92        } else {
93          summary = parent;
94          details = parent.parentElement;
95        }
96        // Update the inner text for the proper hint
97        if (details.open) {
98          summary.querySelector("span.toggle-details__summary-text").innerText =
99            toggleHintShow;
100        } else {
101          summary.querySelector("span.toggle-details__summary-text").innerText =
102            toggleHintHide;
103        }
104      });
105
106      // If we have a toggle-shown class, open details block should be open
107      if (item.classList.contains("toggle-shown")) {
108        details.click();
109      }
110    }
111  });
112};
113
114// This should simply add / remove the collapsed class and change the button text
115var toggleHidden = (button) => {
116  target = button.dataset["target"];
117  var itemToToggle = document.getElementById(target);
118  if (itemToToggle.classList.contains("toggle-hidden")) {
119    itemToToggle.classList.remove("toggle-hidden");
120    button.classList.remove("toggle-button-hidden");
121    button.dataset.toggleHint = toggleHintHide;
122    button.setAttribute("aria-expanded", true);
123  } else {
124    itemToToggle.classList.add("toggle-hidden");
125    button.classList.add("toggle-button-hidden");
126    button.dataset.toggleHint = toggleHintShow;
127    button.setAttribute("aria-expanded", false);
128  }
129};
130
131// Function to synchronize the data-toggle-hint with the current state
132var syncToggleHint = (button) => {
133  const target = button.dataset["target"];
134  const itemToToggle = document.getElementById(target);
135  
136  if (itemToToggle && itemToToggle.classList.contains("toggle-hidden")) {
137    button.dataset.toggleHint = toggleHintShow;
138    button.setAttribute("aria-expanded", false);
139  } else if (itemToToggle) {
140    button.dataset.toggleHint = toggleHintHide;
141    button.setAttribute("aria-expanded", true);
142  }
143};
144
145// Function to sync all toggle buttons - can be called by external extensions
146var syncAllToggleHints = () => {
147  document.querySelectorAll('.toggle-button').forEach(syncToggleHint);
148};
149
150var toggleClickHandler = (click) => {
151  // Be cause the admonition title is clickable and extends to the whole admonition
152  // We only look for a click event on this title to trigger the toggle.
153
154  if (click.target.classList.contains("admonition-title")) {
155    button = click.target.querySelector(".toggle-button");
156  } else if (click.target.classList.contains("tb-icon")) {
157    // We've clicked the icon and need to search up one parent for the button
158    button = click.target.parentElement;
159  } else if (click.target.tagName == "polyline") {
160    // We've clicked the SVG elements inside the button, need to up 2 layers
161    button = click.target.parentElement.parentElement;
162  } else if (click.target.classList.contains("toggle-button")) {
163    // We've clicked the button itself and so don't need to do anything
164    button = click.target;
165  } else {
166    console.log(`[togglebutton]: Couldn't find button for ${click.target}`);
167  }
168  target = document.getElementById(button.dataset["button"]);
169  toggleHidden(target);
170};
171
172// If we want to blanket-add toggle classes to certain cells
173var addToggleToSelector = () => {
174  const selector = "";
175  if (selector.length > 0) {
176    document.querySelectorAll(selector).forEach((item) => {
177      item.classList.add("toggle");
178    });
179  }
180};
181
182// Helper function to run when the DOM is finished
183const sphinxToggleRunWhenDOMLoaded = (cb) => {
184  if (document.readyState != "loading") {
185    cb();
186  } else if (document.addEventListener) {
187    document.addEventListener("DOMContentLoaded", cb);
188  } else {
189    document.attachEvent("onreadystatechange", function () {
190      if (document.readyState == "complete") cb();
191    });
192  }
193};
194sphinxToggleRunWhenDOMLoaded(addToggleToSelector);
195sphinxToggleRunWhenDOMLoaded(initToggleItems);
196
197// Set up MutationObserver to watch for external changes to toggle states
198sphinxToggleRunWhenDOMLoaded(() => {
199  const observer = new MutationObserver((mutations) => {
200    mutations.forEach((mutation) => {
201      if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
202        const target = mutation.target;
203        // Check if this is a toggle item that had its class changed
204        if (target.classList.contains('toggle')) {
205          // Find the associated toggle button and sync its hint
206          const button = target.querySelector('.toggle-button');
207          if (button) {
208            syncToggleHint(button);
209          }
210        }
211      }
212    });
213  });
214
215  // Start observing class changes on all toggle elements
216  document.querySelectorAll('.toggle').forEach((toggleElement) => {
217    observer.observe(toggleElement, {
218      attributes: true,
219      attributeFilter: ['class']
220    });
221  });
222});
223
224/** Toggle details blocks to be open when printing */
225if (toggleOpenOnPrint == "true") {
226  window.addEventListener("beforeprint", () => {
227    // Open the details
228    document.querySelectorAll("details.toggle-details").forEach((el) => {
229      el.dataset["togglestatus"] = el.open;
230      el.open = true;
231    });
232
233    // Open the admonitions
234    document
235      .querySelectorAll(".admonition.toggle.toggle-hidden")
236      .forEach((el) => {
237        console.log(el);
238        el.querySelector("button.toggle-button").click();
239        el.dataset["toggle_after_print"] = "true";
240      });
241  });
242  window.addEventListener("afterprint", () => {
243    // Re-close the details that were closed
244    document.querySelectorAll("details.toggle-details").forEach((el) => {
245      el.open = el.dataset["togglestatus"] == "true";
246      delete el.dataset["togglestatus"];
247    });
248
249    // Re-close the admonition toggle buttons
250    document.querySelectorAll(".admonition.toggle").forEach((el) => {
251      if (el.dataset["toggle_after_print"] == "true") {
252        el.querySelector("button.toggle-button").click();
253        delete el.dataset["toggle_after_print"];
254      }
255    });
256  });
257}

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.