2 /* global search, sourcesIndex */
4 // Local js definitions:
5 /* global addClass, getCurrentValue, hasClass, onEachLazy, removeClass, searchState */
6 /* global updateLocalStorage */
9 function getCurrentFilePath() {
10 var parts = window.location.pathname.split("/");
11 var rootPathParts = window.rootPath.split("/");
13 for (var i = 0, len = rootPathParts.length; i < len; ++i) {
14 if (rootPathParts[i] === "..") {
18 var file = window.location.pathname.substring(parts.join("/").length);
19 if (file.startsWith("/")) {
20 file = file.substring(1);
22 return file.substring(0, file.length - 5);
25 function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
26 var name = document.createElement("div");
27 name.className = "name";
29 fullPath += elem["name"] + "/";
31 name.onclick = function() {
32 if (hasClass(this, "expand")) {
33 removeClass(this, "expand");
35 addClass(this, "expand");
38 name.innerText = elem["name"];
42 var children = document.createElement("div");
43 children.className = "children";
44 var folders = document.createElement("div");
45 folders.className = "folders";
47 for (i = 0, len = elem.dirs.length; i < len; ++i) {
48 if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
50 addClass(name, "expand");
55 children.appendChild(folders);
57 var files = document.createElement("div");
58 files.className = "files";
60 for (i = 0, len = elem.files.length; i < len; ++i) {
61 var file = document.createElement("a");
62 file.innerText = elem.files[i];
63 file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
64 if (!hasFoundFile && currentFile === fullPath + elem.files[i]) {
65 file.className = "selected";
66 addClass(name, "expand");
69 files.appendChild(file);
72 search.fullPath = fullPath;
73 children.appendChild(files);
74 parent.appendChild(name);
75 parent.appendChild(children);
76 return hasFoundFile && currentFile.startsWith(fullPath);
79 function toggleSidebar() {
80 var sidebar = document.querySelector("nav.sidebar");
81 var child = this.children[0];
82 if (child.innerText === ">") {
83 sidebar.classList.add("expanded");
84 child.innerText = "<";
85 updateLocalStorage("rustdoc-source-sidebar-show", "true");
87 sidebar.classList.remove("expanded");
88 child.innerText = ">";
89 updateLocalStorage("rustdoc-source-sidebar-show", "false");
93 function createSidebarToggle() {
94 var sidebarToggle = document.createElement("div");
95 sidebarToggle.id = "sidebar-toggle";
96 sidebarToggle.onclick = toggleSidebar;
98 var inner = document.createElement("div");
100 if (getCurrentValue("rustdoc-source-sidebar-show") === "true") {
101 inner.innerText = "<";
103 inner.innerText = ">";
106 sidebarToggle.appendChild(inner);
107 return sidebarToggle;
110 // This function is called from "source-files.js", generated in `html/render/mod.rs`.
111 // eslint-disable-next-line no-unused-vars
112 function createSourceSidebar() {
113 if (!window.rootPath.endsWith("/")) {
114 window.rootPath += "/";
116 var container = document.querySelector("nav.sidebar");
118 var sidebarToggle = createSidebarToggle();
119 container.insertBefore(sidebarToggle, container.firstChild);
121 var sidebar = document.createElement("div");
122 sidebar.id = "source-sidebar";
123 if (getCurrentValue("rustdoc-source-sidebar-show") !== "true") {
124 container.classList.remove("expanded");
126 container.classList.add("expanded");
129 var currentFile = getCurrentFilePath();
130 var hasFoundFile = false;
132 var title = document.createElement("div");
133 title.className = "title";
134 title.innerText = "Files";
135 sidebar.appendChild(title);
136 Object.keys(sourcesIndex).forEach(function(key) {
137 sourcesIndex[key].name = key;
138 hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
139 currentFile, hasFoundFile);
142 container.appendChild(sidebar);
143 // Focus on the current file in the source files sidebar.
144 var selected_elem = sidebar.getElementsByClassName("selected")[0];
145 if (typeof selected_elem !== "undefined") {
146 selected_elem.focus();
150 var lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
152 function highlightSourceLines(scrollTo, match) {
153 if (typeof match === "undefined") {
154 match = window.location.hash.match(lineNumbersRegex);
159 var from = parseInt(match[1], 10);
161 if (typeof match[2] !== "undefined") {
162 to = parseInt(match[2], 10);
169 var elem = document.getElementById(from);
174 var x = document.getElementById(from);
179 onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
180 onEachLazy(e.getElementsByTagName("span"), function(i_e) {
181 removeClass(i_e, "line-highlighted");
184 for (var i = from; i <= to; ++i) {
185 elem = document.getElementById(i);
189 addClass(elem, "line-highlighted");
193 var handleSourceHighlight = (function() {
194 var prev_line_id = 0;
196 var set_fragment = function(name) {
197 var x = window.scrollX,
199 if (searchState.browserSupportsHistoryApi()) {
200 history.replaceState(null, null, "#" + name);
201 highlightSourceLines(true);
203 location.replace("#" + name);
205 // Prevent jumps when selecting one or many lines
206 window.scrollTo(x, y);
209 return function(ev) {
210 var cur_line_id = parseInt(ev.target.id, 10);
213 if (ev.shiftKey && prev_line_id) {
214 // Swap selection if needed
215 if (prev_line_id > cur_line_id) {
216 var tmp = prev_line_id;
217 prev_line_id = cur_line_id;
221 set_fragment(prev_line_id + "-" + cur_line_id);
223 prev_line_id = cur_line_id;
225 set_fragment(cur_line_id);
230 window.addEventListener("hashchange", function() {
231 var match = window.location.hash.match(lineNumbersRegex);
233 return highlightSourceLines(false, match);
237 onEachLazy(document.getElementsByClassName("line-numbers"), function(el) {
238 el.addEventListener("click", handleSourceHighlight);
241 highlightSourceLines(true);
243 window.createSourceSidebar = createSourceSidebar;