| // From rust: |
| /* global sourcesIndex */ |
| |
| // Local js definitions: |
| /* global addClass, getCurrentValue, onEachLazy, removeClass, browserSupportsHistoryApi */ |
| /* global updateLocalStorage */ |
| |
| "use strict"; |
| |
| (function() { |
| |
| const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value; |
| |
| const NAME_OFFSET = 0; |
| const DIRS_OFFSET = 1; |
| const FILES_OFFSET = 2; |
| |
| function closeSidebarIfMobile() { |
| if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) { |
| updateLocalStorage("source-sidebar-show", "false"); |
| } |
| } |
| |
| function createDirEntry(elem, parent, fullPath, hasFoundFile) { |
| const dirEntry = document.createElement("details"); |
| const summary = document.createElement("summary"); |
| |
| dirEntry.className = "dir-entry"; |
| |
| fullPath += elem[NAME_OFFSET] + "/"; |
| |
| summary.innerText = elem[NAME_OFFSET]; |
| dirEntry.appendChild(summary); |
| |
| const folders = document.createElement("div"); |
| folders.className = "folders"; |
| if (elem[DIRS_OFFSET]) { |
| for (const dir of elem[DIRS_OFFSET]) { |
| if (createDirEntry(dir, folders, fullPath, false)) { |
| dirEntry.open = true; |
| hasFoundFile = true; |
| } |
| } |
| } |
| dirEntry.appendChild(folders); |
| |
| const files = document.createElement("div"); |
| files.className = "files"; |
| if (elem[FILES_OFFSET]) { |
| for (const file_text of elem[FILES_OFFSET]) { |
| const file = document.createElement("a"); |
| file.innerText = file_text; |
| file.href = rootPath + "src/" + fullPath + file_text + ".html"; |
| file.addEventListener("click", closeSidebarIfMobile); |
| const w = window.location.href.split("#")[0]; |
| if (!hasFoundFile && w === file.href) { |
| file.className = "selected"; |
| dirEntry.open = true; |
| hasFoundFile = true; |
| } |
| files.appendChild(file); |
| } |
| } |
| dirEntry.appendChild(files); |
| parent.appendChild(dirEntry); |
| return hasFoundFile; |
| } |
| |
| function toggleSidebar() { |
| const child = this.parentNode.children[0]; |
| if (child.innerText === ">") { |
| window.rustdocMobileScrollLock(); |
| addClass(document.documentElement, "source-sidebar-expanded"); |
| child.innerText = "<"; |
| updateLocalStorage("source-sidebar-show", "true"); |
| } else { |
| window.rustdocMobileScrollUnlock(); |
| removeClass(document.documentElement, "source-sidebar-expanded"); |
| child.innerText = ">"; |
| updateLocalStorage("source-sidebar-show", "false"); |
| } |
| } |
| |
| function createSidebarToggle() { |
| const sidebarToggle = document.createElement("div"); |
| sidebarToggle.id = "sidebar-toggle"; |
| |
| const inner = document.createElement("button"); |
| |
| if (getCurrentValue("source-sidebar-show") === "true") { |
| inner.innerText = "<"; |
| } else { |
| inner.innerText = ">"; |
| } |
| inner.onclick = toggleSidebar; |
| |
| sidebarToggle.appendChild(inner); |
| return sidebarToggle; |
| } |
| |
| // This function is called from "source-files.js", generated in `html/render/write_shared.rs`. |
| // eslint-disable-next-line no-unused-vars |
| function createSourceSidebar() { |
| const container = document.querySelector("nav.sidebar"); |
| |
| const sidebarToggle = createSidebarToggle(); |
| container.insertBefore(sidebarToggle, container.firstChild); |
| |
| const sidebar = document.createElement("div"); |
| sidebar.id = "source-sidebar"; |
| |
| let hasFoundFile = false; |
| |
| const title = document.createElement("div"); |
| title.className = "title"; |
| title.innerText = "Files"; |
| sidebar.appendChild(title); |
| Object.keys(sourcesIndex).forEach(key => { |
| sourcesIndex[key][NAME_OFFSET] = key; |
| hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", |
| hasFoundFile); |
| }); |
| |
| container.appendChild(sidebar); |
| // Focus on the current file in the source files sidebar. |
| const selected_elem = sidebar.getElementsByClassName("selected")[0]; |
| if (typeof selected_elem !== "undefined") { |
| selected_elem.focus(); |
| } |
| } |
| |
| const lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/; |
| |
| function highlightSourceLines(match) { |
| if (typeof match === "undefined") { |
| match = window.location.hash.match(lineNumbersRegex); |
| } |
| if (!match) { |
| return; |
| } |
| let from = parseInt(match[1], 10); |
| let to = from; |
| if (typeof match[2] !== "undefined") { |
| to = parseInt(match[2], 10); |
| } |
| if (to < from) { |
| const tmp = to; |
| to = from; |
| from = tmp; |
| } |
| let elem = document.getElementById(from); |
| if (!elem) { |
| return; |
| } |
| const x = document.getElementById(from); |
| if (x) { |
| x.scrollIntoView(); |
| } |
| onEachLazy(document.getElementsByClassName("src-line-numbers"), e => { |
| onEachLazy(e.getElementsByTagName("span"), i_e => { |
| removeClass(i_e, "line-highlighted"); |
| }); |
| }); |
| for (let i = from; i <= to; ++i) { |
| elem = document.getElementById(i); |
| if (!elem) { |
| break; |
| } |
| addClass(elem, "line-highlighted"); |
| } |
| } |
| |
| const handleSourceHighlight = (function() { |
| let prev_line_id = 0; |
| |
| const set_fragment = name => { |
| const x = window.scrollX, |
| y = window.scrollY; |
| if (browserSupportsHistoryApi()) { |
| history.replaceState(null, null, "#" + name); |
| highlightSourceLines(); |
| } else { |
| location.replace("#" + name); |
| } |
| // Prevent jumps when selecting one or many lines |
| window.scrollTo(x, y); |
| }; |
| |
| return ev => { |
| let cur_line_id = parseInt(ev.target.id, 10); |
| // It can happen when clicking not on a line number span. |
| if (isNaN(cur_line_id)) { |
| return; |
| } |
| ev.preventDefault(); |
| |
| if (ev.shiftKey && prev_line_id) { |
| // Swap selection if needed |
| if (prev_line_id > cur_line_id) { |
| const tmp = prev_line_id; |
| prev_line_id = cur_line_id; |
| cur_line_id = tmp; |
| } |
| |
| set_fragment(prev_line_id + "-" + cur_line_id); |
| } else { |
| prev_line_id = cur_line_id; |
| |
| set_fragment(cur_line_id); |
| } |
| }; |
| }()); |
| |
| window.addEventListener("hashchange", () => { |
| const match = window.location.hash.match(lineNumbersRegex); |
| if (match) { |
| return highlightSourceLines(match); |
| } |
| }); |
| |
| onEachLazy(document.getElementsByClassName("src-line-numbers"), el => { |
| el.addEventListener("click", handleSourceHighlight); |
| }); |
| |
| highlightSourceLines(); |
| |
| window.createSourceSidebar = createSourceSidebar; |
| })(); |