Merge pull request #2608 from szabgab/navigation-help
Add pop-up window showing the keyboard shortcuts
This commit is contained in:
commit
481346812c
6 changed files with 129 additions and 20 deletions
|
|
@ -656,3 +656,46 @@ html:not(.sidebar-resizing) .sidebar {
|
||||||
margin-inline-start: -14px;
|
margin-inline-start: -14px;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The container for the help popup that covers the whole window. */
|
||||||
|
#mdbook-help-container {
|
||||||
|
/* Position and size for the whole window. */
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
/* This uses flex layout (which is set in book.js), and centers the popup
|
||||||
|
in the window.*/
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
/* Dim out the book while the popup is visible. */
|
||||||
|
background: var(--overlay-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The popup help box. */
|
||||||
|
#mdbook-help-popup {
|
||||||
|
box-shadow: 0 4px 24px rgba(0,0,0,0.15);
|
||||||
|
min-width: 300px;
|
||||||
|
max-width: 500px;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--bg);
|
||||||
|
color: var(--fg);
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: var(--theme-popup-border);
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mdbook-help-title {
|
||||||
|
text-align: center;
|
||||||
|
/* mdbook's margin for h2 is way too large. */
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@
|
||||||
--copy-button-filter-hover: invert(68%) sepia(55%) saturate(531%) hue-rotate(341deg) brightness(104%) contrast(101%);
|
--copy-button-filter-hover: invert(68%) sepia(55%) saturate(531%) hue-rotate(341deg) brightness(104%) contrast(101%);
|
||||||
|
|
||||||
--footnote-highlight: #2668a6;
|
--footnote-highlight: #2668a6;
|
||||||
|
|
||||||
|
--overlay-bg: rgba(33, 40, 48, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.coal {
|
.coal {
|
||||||
|
|
@ -115,6 +117,8 @@
|
||||||
--copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%);
|
--copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%);
|
||||||
|
|
||||||
--footnote-highlight: #4079ae;
|
--footnote-highlight: #4079ae;
|
||||||
|
|
||||||
|
--overlay-bg: rgba(33, 40, 48, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.light, html:not(.js) {
|
.light, html:not(.js) {
|
||||||
|
|
@ -166,6 +170,8 @@
|
||||||
--copy-button-filter-hover: invert(14%) sepia(93%) saturate(4250%) hue-rotate(243deg) brightness(99%) contrast(130%);
|
--copy-button-filter-hover: invert(14%) sepia(93%) saturate(4250%) hue-rotate(243deg) brightness(99%) contrast(130%);
|
||||||
|
|
||||||
--footnote-highlight: #7e7eff;
|
--footnote-highlight: #7e7eff;
|
||||||
|
|
||||||
|
--overlay-bg: rgba(200, 200, 205, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.navy {
|
.navy {
|
||||||
|
|
@ -217,6 +223,8 @@
|
||||||
--copy-button-filter-hover: invert(46%) sepia(20%) saturate(1537%) hue-rotate(156deg) brightness(85%) contrast(90%);
|
--copy-button-filter-hover: invert(46%) sepia(20%) saturate(1537%) hue-rotate(156deg) brightness(85%) contrast(90%);
|
||||||
|
|
||||||
--footnote-highlight: #4079ae;
|
--footnote-highlight: #4079ae;
|
||||||
|
|
||||||
|
--overlay-bg: rgba(33, 40, 48, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rust {
|
.rust {
|
||||||
|
|
@ -266,6 +274,8 @@
|
||||||
--copy-button-filter-hover: invert(77%) sepia(16%) saturate(1798%) hue-rotate(328deg) brightness(98%) contrast(83%);
|
--copy-button-filter-hover: invert(77%) sepia(16%) saturate(1798%) hue-rotate(328deg) brightness(98%) contrast(83%);
|
||||||
|
|
||||||
--footnote-highlight: #d3a17a;
|
--footnote-highlight: #d3a17a;
|
||||||
|
|
||||||
|
--overlay-bg: rgba(150, 150, 150, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
|
|
|
||||||
|
|
@ -623,7 +623,7 @@ aria-label="Show hidden lines"></button>';
|
||||||
|
|
||||||
(function chapterNavigation() {
|
(function chapterNavigation() {
|
||||||
document.addEventListener('keydown', function(e) {
|
document.addEventListener('keydown', function(e) {
|
||||||
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) {
|
if (e.altKey || e.ctrlKey || e.metaKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (window.search && window.search.hasFocus()) {
|
if (window.search && window.search.hasFocus()) {
|
||||||
|
|
@ -643,6 +643,55 @@ aria-label="Show hidden lines"></button>';
|
||||||
window.location.href = previousButton.href;
|
window.location.href = previousButton.href;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function showHelp() {
|
||||||
|
const container = document.getElementById('mdbook-help-container');
|
||||||
|
const overlay = document.getElementById('mdbook-help-popup');
|
||||||
|
container.style.display = 'flex';
|
||||||
|
|
||||||
|
// Clicking outside the popup will dismiss it.
|
||||||
|
const mouseHandler = event => {
|
||||||
|
if (overlay.contains(event.target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.button !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
document.removeEventListener('mousedown', mouseHandler);
|
||||||
|
hideHelp();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pressing esc will dismiss the popup.
|
||||||
|
const escapeKeyHandler = event => {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
document.removeEventListener('keydown', escapeKeyHandler, true);
|
||||||
|
hideHelp();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener('keydown', escapeKeyHandler, true);
|
||||||
|
document.getElementById('mdbook-help-container')
|
||||||
|
.addEventListener('mousedown', mouseHandler);
|
||||||
|
}
|
||||||
|
function hideHelp() {
|
||||||
|
document.getElementById('mdbook-help-container').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usually needs the Shift key to be pressed
|
||||||
|
switch (e.key) {
|
||||||
|
case '?':
|
||||||
|
e.preventDefault();
|
||||||
|
showHelp();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rest of the keys are only active when the Shift key is not pressed
|
||||||
|
if (e.shiftKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case 'ArrowRight':
|
case 'ArrowRight':
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,7 @@ window.search = window.search || {};
|
||||||
mark_exclude = ['text'],
|
mark_exclude = ['text'],
|
||||||
marker = new Mark(content),
|
marker = new Mark(content),
|
||||||
URL_SEARCH_PARAM = 'search',
|
URL_SEARCH_PARAM = 'search',
|
||||||
URL_MARK_PARAM = 'highlight',
|
URL_MARK_PARAM = 'highlight';
|
||||||
|
|
||||||
SEARCH_HOTKEY_KEYCODES = [83, 191], // `s` or `/`.
|
|
||||||
ESCAPE_KEYCODE = 27,
|
|
||||||
DOWN_KEYCODE = 40,
|
|
||||||
UP_KEYCODE = 38,
|
|
||||||
SELECT_KEYCODE = 13;
|
|
||||||
|
|
||||||
let current_searchterm = '',
|
let current_searchterm = '',
|
||||||
doc_urls = [],
|
doc_urls = [],
|
||||||
|
|
@ -352,7 +346,7 @@ window.search = window.search || {};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.keyCode === ESCAPE_KEYCODE) {
|
if (e.key === 'Escape') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
searchbar.classList.remove('active');
|
searchbar.classList.remove('active');
|
||||||
setSearchUrlParameters('',
|
setSearchUrlParameters('',
|
||||||
|
|
@ -362,38 +356,38 @@ window.search = window.search || {};
|
||||||
}
|
}
|
||||||
showSearch(false);
|
showSearch(false);
|
||||||
marker.unmark();
|
marker.unmark();
|
||||||
} else if (!hasFocus() && SEARCH_HOTKEY_KEYCODES.includes(e.keyCode)) {
|
} else if (!hasFocus() && (e.key === 'S' || e.key === '/')) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
showSearch(true);
|
showSearch(true);
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
searchbar.select();
|
searchbar.select();
|
||||||
} else if (hasFocus() && (e.keyCode === DOWN_KEYCODE
|
} else if (hasFocus() && (e.key === 'ArrowDown'
|
||||||
|| e.keyCode === SELECT_KEYCODE)) {
|
|| e.key === 'Enter')) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const first = searchresults.firstElementChild;
|
const first = searchresults.firstElementChild;
|
||||||
if (first !== null) {
|
if (first !== null) {
|
||||||
unfocusSearchbar();
|
unfocusSearchbar();
|
||||||
first.classList.add('focus');
|
first.classList.add('focus');
|
||||||
if (e.keyCode === SELECT_KEYCODE) {
|
if (e.key === 'Enter') {
|
||||||
window.location.assign(first.querySelector('a'));
|
window.location.assign(first.querySelector('a'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!hasFocus() && (e.keyCode === DOWN_KEYCODE
|
} else if (!hasFocus() && (e.key === 'ArrowDown'
|
||||||
|| e.keyCode === UP_KEYCODE
|
|| e.key === 'ArrowUp'
|
||||||
|| e.keyCode === SELECT_KEYCODE)) {
|
|| e.key === 'Enter')) {
|
||||||
// not `:focus` because browser does annoying scrolling
|
// not `:focus` because browser does annoying scrolling
|
||||||
const focused = searchresults.querySelector('li.focus');
|
const focused = searchresults.querySelector('li.focus');
|
||||||
if (!focused) {
|
if (!focused) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (e.keyCode === DOWN_KEYCODE) {
|
if (e.key === 'ArrowDown') {
|
||||||
const next = focused.nextElementSibling;
|
const next = focused.nextElementSibling;
|
||||||
if (next) {
|
if (next) {
|
||||||
focused.classList.remove('focus');
|
focused.classList.remove('focus');
|
||||||
next.classList.add('focus');
|
next.classList.add('focus');
|
||||||
}
|
}
|
||||||
} else if (e.keyCode === UP_KEYCODE) {
|
} else if (e.key === 'ArrowUp') {
|
||||||
focused.classList.remove('focus');
|
focused.classList.remove('focus');
|
||||||
const prev = focused.previousElementSibling;
|
const prev = focused.previousElementSibling;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
|
|
@ -401,7 +395,7 @@ window.search = window.search || {};
|
||||||
} else {
|
} else {
|
||||||
searchbar.select();
|
searchbar.select();
|
||||||
}
|
}
|
||||||
} else { // SELECT_KEYCODE
|
} else { // Enter
|
||||||
window.location.assign(focused.querySelector('a'));
|
window.location.assign(focused.querySelector('a'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,19 @@
|
||||||
<script src="{{ resource "toc.js" }}"></script>
|
<script src="{{ resource "toc.js" }}"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="mdbook-help-container">
|
||||||
|
<div id="mdbook-help-popup">
|
||||||
|
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
|
||||||
|
<div>
|
||||||
|
<p>Press <kbd>←</kbd> or <kbd>→</kbd> to navigate between chapters</p>
|
||||||
|
{{#if search_enabled}}
|
||||||
|
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
|
||||||
|
{{/if}}
|
||||||
|
<p>Press <kbd>?</kbd> to show this help</p>
|
||||||
|
<p>Press <kbd>Esc</kbd> to hide this help</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="body-container">
|
<div id="body-container">
|
||||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||||
<script>
|
<script>
|
||||||
|
|
|
||||||
|
|
@ -667,7 +667,7 @@ fn build_header_links(html: &str) -> String {
|
||||||
static BUILD_HEADER_LINKS: LazyLock<Regex> = LazyLock::new(|| {
|
static BUILD_HEADER_LINKS: LazyLock<Regex> = LazyLock::new(|| {
|
||||||
Regex::new(r#"<h(\d)(?: id="([^"]+)")?(?: class="([^"]+)")?>(.*?)</h\d>"#).unwrap()
|
Regex::new(r#"<h(\d)(?: id="([^"]+)")?(?: class="([^"]+)")?>(.*?)</h\d>"#).unwrap()
|
||||||
});
|
});
|
||||||
static IGNORE_CLASS: &[&str] = &["menu-title"];
|
static IGNORE_CLASS: &[&str] = &["menu-title", "mdbook-help-title"];
|
||||||
|
|
||||||
let mut id_counter = HashMap::new();
|
let mut id_counter = HashMap::new();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue