1 // Local js definitions:
2 /* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
3 /* global addClass, removeClass, onEach, onEachLazy, NOT_DISPLAYED_ID */
4 /* global MAIN_ID, getVar, getSettingsButton, switchDisplayedElement, getNotDisplayedElem */
9 const isSettingsPage = window.location.pathname.endsWith("/settings.html");
11 function changeSetting(settingName, value) {
12 updateLocalStorage(settingName, value);
14 switch (settingName) {
16 case "preferred-dark-theme":
17 case "preferred-light-theme":
18 case "use-system-theme":
25 function handleKey(ev) {
26 // Don't interfere with browser shortcuts
27 if (ev.ctrlKey || ev.altKey || ev.metaKey) {
30 switch (getVirtualKey(ev)) {
34 ev.target.checked = !ev.target.checked;
40 function showLightAndDark() {
41 addClass(document.getElementById("theme").parentElement, "hidden");
42 removeClass(document.getElementById("preferred-light-theme").parentElement, "hidden");
43 removeClass(document.getElementById("preferred-dark-theme").parentElement, "hidden");
46 function hideLightAndDark() {
47 addClass(document.getElementById("preferred-light-theme").parentElement, "hidden");
48 addClass(document.getElementById("preferred-dark-theme").parentElement, "hidden");
49 removeClass(document.getElementById("theme").parentElement, "hidden");
52 function updateLightAndDark() {
53 if (getSettingValue("use-system-theme") !== "false") {
60 function setEvents(settingsElement) {
62 onEachLazy(settingsElement.getElementsByClassName("slider"), elem => {
63 const toggle = elem.previousElementSibling;
64 const settingId = toggle.id;
65 const settingValue = getSettingValue(settingId);
66 if (settingValue !== null) {
67 toggle.checked = settingValue === "true";
69 toggle.onchange = function() {
70 changeSetting(this.id, this.checked);
72 toggle.onkeyup = handleKey;
73 toggle.onkeyrelease = handleKey;
75 onEachLazy(settingsElement.getElementsByClassName("select-wrapper"), elem => {
76 const select = elem.getElementsByTagName("select")[0];
77 const settingId = select.id;
78 const settingValue = getSettingValue(settingId);
79 if (settingValue !== null) {
80 select.value = settingValue;
82 select.onchange = function() {
83 changeSetting(this.id, this.value);
86 onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"), elem => {
87 const settingId = elem.name;
88 const settingValue = getSettingValue(settingId);
89 if (settingValue !== null && settingValue !== "null") {
90 elem.checked = settingValue === elem.value;
92 elem.addEventListener("change", ev => {
93 changeSetting(ev.target.name, ev.target.value);
99 * This function builds the sections inside the "settings page". It takes a `settings` list
100 * as argument which describes each setting and how to render it. It returns a string
101 * representing the raw HTML.
103 * @param {Array<Object>} settings
107 function buildSettingsPageSections(settings) {
110 for (const setting of settings) {
111 output += `<div class="setting-line">`;
112 const js_data_name = setting["js_name"];
113 const setting_name = setting["name"];
115 if (setting["options"] !== undefined) {
116 // This is a select setting.
117 output += `<div class="radio-line" id="${js_data_name}">\
118 <span class="setting-name">${setting_name}</span>\
119 <div class="choices">`;
120 onEach(setting["options"], option => {
121 const checked = option === setting["default"] ? " checked" : "";
123 output += `<label for="${js_data_name}-${option}" class="choice">\
124 <input type="radio" name="${js_data_name}" \
125 id="${js_data_name}-${option}" value="${option}"${checked}>\
129 output += "</div></div>";
132 const checked = setting["default"] === true ? " checked" : "";
134 <label class="toggle">
135 <input type="checkbox" id="${js_data_name}"${checked}>
136 <span class="slider"></span>
138 <div>${setting_name}</div>`;
146 * This function builds the "settings page" and returns the generated HTML element.
148 * @return {HTMLElement}
150 function buildSettingsPage() {
151 const themes = getVar("themes").split(",");
154 "name": "Use system theme",
155 "js_name": "use-system-theme",
165 "name": "Preferred light theme",
166 "js_name": "preferred-light-theme",
171 "name": "Preferred dark theme",
172 "js_name": "preferred-dark-theme",
177 "name": "Auto-hide item contents for large items",
178 "js_name": "auto-hide-large-items",
182 "name": "Auto-hide item methods' documentation",
183 "js_name": "auto-hide-method-docs",
187 "name": "Auto-hide trait implementation documentation",
188 "js_name": "auto-hide-trait-implementations",
192 "name": "Directly go to item in search if there is only one result",
193 "js_name": "go-to-only-result",
197 "name": "Show line numbers on code examples",
198 "js_name": "line-numbers",
202 "name": "Disable keyboard shortcuts",
203 "js_name": "disable-shortcuts",
208 // Then we build the DOM.
209 const el = document.createElement("section");
212 <div class="main-heading">
214 <span class="in-band">Rustdoc settings</span>
216 <span class="out-of-band">`;
218 if (isSettingsPage) {
220 `<a id="back" href="javascript:void(0)" onclick="history.back();">Back</a>`;
223 `<a id="back" href="javascript:void(0)" onclick="switchDisplayedElement(null);">\
226 innerHTML += `</span>
228 <div class="settings">${buildSettingsPageSections(settings)}</div>`;
230 el.innerHTML = innerHTML;
232 if (isSettingsPage) {
233 document.getElementById(MAIN_ID).appendChild(el);
235 getNotDisplayedElem().appendChild(el);
240 const settingsMenu = buildSettingsPage();
242 if (isSettingsPage) {
243 // We replace the existing "onclick" callback to do nothing if clicked.
244 getSettingsButton().onclick = function(event) {
245 event.preventDefault();
248 // We replace the existing "onclick" callback.
249 const settingsButton = getSettingsButton();
250 settingsButton.onclick = function(event) {
251 event.preventDefault();
252 if (settingsMenu.parentElement.id === NOT_DISPLAYED_ID) {
253 switchDisplayedElement(settingsMenu);
255 window.hideSettings();
258 window.hideSettings = function() {
259 switchDisplayedElement(null);
263 // We now wait a bit for the web browser to end re-computing the DOM...
265 setEvents(settingsMenu);
266 // The setting menu is already displayed if we're on the settings page.
267 if (!isSettingsPage) {
268 switchDisplayedElement(settingsMenu);
270 removeClass(getSettingsButton(), "rotate");