2 /* global sourcesIndex */
4 // Local js definitions:
5 /* global addClass, getCurrentValue, onEachLazy, removeClass, browserSupportsHistoryApi */
6 /* global updateLocalStorage */
12 const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value;
13 let oldScrollPosition = 0;
15 function createDirEntry(elem, parent, fullPath, hasFoundFile) {
16 const dirEntry = document.createElement("details");
17 const summary = document.createElement("summary");
19 dirEntry.className = "dir-entry";
21 fullPath += elem["name"] + "/";
23 summary.innerText = elem["name"];
24 dirEntry.appendChild(summary);
26 const folders = document.createElement("div");
27 folders.className = "folders";
29 for (const dir of elem.dirs) {
30 if (createDirEntry(dir, folders, fullPath, hasFoundFile)) {
36 dirEntry.appendChild(folders);
38 const files = document.createElement("div");
39 files.className = "files";
41 for (const file_text of elem.files) {
42 const file = document.createElement("a");
43 file.innerText = file_text;
44 file.href = rootPath + "src/" + fullPath + file_text + ".html";
45 const w = window.location.href.split("#")[0];
46 if (!hasFoundFile && w === file.href) {
47 file.className = "selected";
51 files.appendChild(file);
54 dirEntry.appendChild(files);
55 parent.appendChild(dirEntry);
59 function toggleSidebar() {
60 const child = this.children[0];
61 if (child.innerText === ">") {
62 if (window.innerWidth < 701) {
63 // This is to keep the scroll position on mobile.
64 oldScrollPosition = window.scrollY;
65 document.body.style.position = "fixed";
66 document.body.style.top = `-${oldScrollPosition}px`;
68 addClass(document.documentElement, "source-sidebar-expanded");
69 child.innerText = "<";
70 updateLocalStorage("source-sidebar-show", "true");
72 if (window.innerWidth < 701) {
73 // This is to keep the scroll position on mobile.
74 document.body.style.position = "";
75 document.body.style.top = "";
76 // The scroll position is lost when resetting the style, hence why we store it in
78 window.scrollTo(0, oldScrollPosition);
80 removeClass(document.documentElement, "source-sidebar-expanded");
81 child.innerText = ">";
82 updateLocalStorage("source-sidebar-show", "false");
86 function createSidebarToggle() {
87 const sidebarToggle = document.createElement("div");
88 sidebarToggle.id = "sidebar-toggle";
89 sidebarToggle.onclick = toggleSidebar;
91 const inner = document.createElement("div");
93 if (getCurrentValue("source-sidebar-show") === "true") {
94 inner.innerText = "<";
96 inner.innerText = ">";
99 sidebarToggle.appendChild(inner);
100 return sidebarToggle;
103 // This function is called from "source-files.js", generated in `html/render/mod.rs`.
104 // eslint-disable-next-line no-unused-vars
105 function createSourceSidebar() {
106 const container = document.querySelector("nav.sidebar");
108 const sidebarToggle = createSidebarToggle();
109 container.insertBefore(sidebarToggle, container.firstChild);
111 const sidebar = document.createElement("div");
112 sidebar.id = "source-sidebar";
114 let hasFoundFile = false;
116 const title = document.createElement("div");
117 title.className = "title";
118 title.innerText = "Files";
119 sidebar.appendChild(title);
120 Object.keys(sourcesIndex).forEach(key => {
121 sourcesIndex[key].name = key;
122 hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
126 container.appendChild(sidebar);
127 // Focus on the current file in the source files sidebar.
128 const selected_elem = sidebar.getElementsByClassName("selected")[0];
129 if (typeof selected_elem !== "undefined") {
130 selected_elem.focus();
134 const lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
136 function highlightSourceLines(match) {
137 if (typeof match === "undefined") {
138 match = window.location.hash.match(lineNumbersRegex);
143 let from = parseInt(match[1], 10);
145 if (typeof match[2] !== "undefined") {
146 to = parseInt(match[2], 10);
153 let elem = document.getElementById(from);
157 const x = document.getElementById(from);
161 onEachLazy(document.getElementsByClassName("line-numbers"), e => {
162 onEachLazy(e.getElementsByTagName("span"), i_e => {
163 removeClass(i_e, "line-highlighted");
166 for (let i = from; i <= to; ++i) {
167 elem = document.getElementById(i);
171 addClass(elem, "line-highlighted");
175 const handleSourceHighlight = (function() {
176 let prev_line_id = 0;
178 const set_fragment = name => {
179 const x = window.scrollX,
181 if (browserSupportsHistoryApi()) {
182 history.replaceState(null, null, "#" + name);
183 highlightSourceLines();
185 location.replace("#" + name);
187 // Prevent jumps when selecting one or many lines
188 window.scrollTo(x, y);
192 let cur_line_id = parseInt(ev.target.id, 10);
193 // It can happen when clicking not on a line number span.
194 if (isNaN(cur_line_id)) {
199 if (ev.shiftKey && prev_line_id) {
200 // Swap selection if needed
201 if (prev_line_id > cur_line_id) {
202 const tmp = prev_line_id;
203 prev_line_id = cur_line_id;
207 set_fragment(prev_line_id + "-" + cur_line_id);
209 prev_line_id = cur_line_id;
211 set_fragment(cur_line_id);
216 window.addEventListener("hashchange", () => {
217 const match = window.location.hash.match(lineNumbersRegex);
219 return highlightSourceLines(match);
223 onEachLazy(document.getElementsByClassName("line-numbers"), el => {
224 el.addEventListener("click", handleSourceHighlight);
227 highlightSourceLines();
229 window.createSourceSidebar = createSourceSidebar;