1/* 2 * Base JavaScript utilities for all Sphinx HTML documentation. 3 */ 4"use strict"; 5 6const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ 7 "TEXTAREA", 8 "INPUT", 9 "SELECT", 10 "BUTTON", 11]); 12 13const _ready = (callback) => { 14 if (document.readyState !== "loading") { 15 callback(); 16 } else { 17 document.addEventListener("DOMContentLoaded", callback); 18 } 19}; 20 21/** 22 * Small JavaScript module for the documentation. 23 */ 24const Documentation = { 25 init: () => { 26 Documentation.initDomainIndexTable(); 27 Documentation.initOnKeyListeners(); 28 }, 29 30 /** 31 * i18n support 32 */ 33 TRANSLATIONS: {}, 34 PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), 35 LOCALE: "unknown", 36 37 // gettext and ngettext don't access this so that the functions 38 // can safely bound to a different name (_ = Documentation.gettext) 39 gettext: (string) => { 40 const translated = Documentation.TRANSLATIONS[string]; 41 switch (typeof translated) { 42 case "undefined": 43 return string; // no translation 44 case "string": 45 return translated; // translation exists 46 default: 47 return translated[0]; // (singular, plural) translation tuple exists 48 } 49 }, 50 51 ngettext: (singular, plural, n) => { 52 const translated = Documentation.TRANSLATIONS[singular]; 53 if (typeof translated !== "undefined") 54 return translated[Documentation.PLURAL_EXPR(n)]; 55 return n === 1 ? singular : plural; 56 }, 57 58 addTranslations: (catalog) => { 59 Object.assign(Documentation.TRANSLATIONS, catalog.messages); 60 Documentation.PLURAL_EXPR = new Function( 61 "n", 62 `return (${catalog.plural_expr})`, 63 ); 64 Documentation.LOCALE = catalog.locale; 65 }, 66 67 /** 68 * helper function to focus on search bar 69 */ 70 focusSearchBar: () => { 71 document.querySelectorAll("input[name=q]")[0]?.focus(); 72 }, 73 74 /** 75 * Initialise the domain index toggle buttons 76 */ 77 initDomainIndexTable: () => { 78 const toggler = (el) => { 79 const idNumber = el.id.substr(7); 80 const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); 81 if (el.src.substr(-9) === "minus.png") { 82 el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; 83 toggledRows.forEach((el) => (el.style.display = "none")); 84 } else { 85 el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; 86 toggledRows.forEach((el) => (el.style.display = "")); 87 } 88 }; 89 90 const togglerElements = document.querySelectorAll("img.toggler"); 91 togglerElements.forEach((el) => 92 el.addEventListener("click", (event) => toggler(event.currentTarget)), 93 ); 94 togglerElements.forEach((el) => (el.style.display = "")); 95 if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); 96 }, 97 98 initOnKeyListeners: () => { 99 // only install a listener if it is really needed 100 if ( 101 !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS 102 && !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS 103 ) 104 return; 105 106 document.addEventListener("keydown", (event) => { 107 // bail for input elements 108 if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) 109 return; 110 // bail with special keys 111 if (event.altKey || event.ctrlKey || event.metaKey) return; 112 113 if (!event.shiftKey) { 114 switch (event.key) { 115 case "ArrowLeft": 116 if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 117 118 const prevLink = document.querySelector('link[rel="prev"]'); 119 if (prevLink && prevLink.href) { 120 window.location.href = prevLink.href; 121 event.preventDefault(); 122 } 123 break; 124 case "ArrowRight": 125 if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 126 127 const nextLink = document.querySelector('link[rel="next"]'); 128 if (nextLink && nextLink.href) { 129 window.location.href = nextLink.href; 130 event.preventDefault(); 131 } 132 break; 133 } 134 } 135 136 // some keyboard layouts may need Shift to get / 137 switch (event.key) { 138 case "/": 139 if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; 140 Documentation.focusSearchBar(); 141 event.preventDefault(); 142 } 143 }); 144 }, 145}; 146 147// quick alias for translations 148const _ = Documentation.gettext; 149 150_ready(Documentation.init);
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.