search: improve keyboard handling #387

This commit is contained in:
Sören Weber 2022-11-17 17:29:01 +01:00
parent 69f679ffe6
commit dd44547a10
No known key found for this signature in database
GPG key ID: BEC6D55545451B6D
10 changed files with 177 additions and 93 deletions

View file

@ -2,11 +2,11 @@
</main><!-- #body-inner -->
{{- partial "custom-comments.html" . }}
</div><!-- #body -->
{{- partialCached "menu.html" . .RelPermalink }}
{{- $outputFormat := partial "output-format.hugo" .Page }}
{{- partial "output-partial.hugo" (dict "base" "menu" "page" . "parameter" . "outputFormat" $outputFormat) }}
<script src="{{"js/clipboard.min.js" | relURL}}{{ if not .Site.Params.disableAssetsBusting }}?{{ now.Unix }}{{ end }}" defer></script>
<script src="{{"js/perfect-scrollbar.min.js" | relURL}}{{ if not .Site.Params.disableAssetsBusting }}?{{ now.Unix }}{{ end }}" defer></script>
<script src="{{"js/featherlight.min.js" | relURL}}{{ if not .Site.Params.disableAssetsBusting }}?{{ now.Unix }}{{ end }}" defer></script>
{{- $outputFormat := partial "output-format.hugo" .Page }}
{{- $wantsMathJax := or (.Page.Store.Get "hasMathJax") (and (.Page.Store.Get (printf "%sIsNested" $outputFormat)) (.Page.Store.Get "nestedHasMathJax")) }}
{{- if $wantsMathJax }}
{{- if isset .Params "mathjaxinitialize" }}

View file

@ -1,9 +1,13 @@
<div class="searchbox default-animation">
{{- $link := "" }}
{{- with .Site.Home.OutputFormats.Get "SEARCHPAGE" }}
{{- $link = partial "relLangPrettyUglyURL.hugo" (dict "to" .) }}
{{- end }}
{{- $c:="" }} {{ if $link }}<form action="{{ $link }}" method="get">{{ end }}<div class="searchbox default-animation">
{{ if $link }}<button type="submit" title="{{ T "Search" }} (CTRL+ALT+f)">{{ end }}<i class="fas fa-search"{{ if not $link }} title="{{ T "Search" }} (CTRL+ALT+f)"{{ end }}></i>{{ if $link }}</button>{{ end }}
<label class="a11y-only" for="search-by">{{ T "Search" }}</label>
<i class="fas fa-search"></i>
<input data-search-input id="search-by" type="search" placeholder="{{ T "Search-placeholder" }}">
<input data-search-input id="search-by" name="search-by" class="search-by" type="search" placeholder="{{ T "Search-placeholder" }}">
<span data-search-clear=""><i class="fas fa-times"></i></span>
</div>
</div>{{ if $link }}</form>{{ end }}
{{- $assetBusting := not .Site.Params.disableAssetsBusting }}
{{- $pageBaseLang := replaceRE "([a-z]+).*" "${1}" .Page.Lang }}
{{- $contentlangs := (union (slice | append .Site.Params.additionalContentLanguage) (slice $pageBaseLang)) }}

View file

@ -10,7 +10,8 @@
position: absolute;
display: none;
z-index: 9999;
max-height: 254px;
max-height: 150px;
max-height: calc( 100vh - 150px );
overflow: hidden;
overflow-y: auto;
box-sizing: border-box;
@ -43,6 +44,7 @@
.autocomplete-suggestion > .context {
font-size: 12px;
margin-inline-start: 1em;
overflow: hidden;
text-overflow: ellipsis;
}

View file

@ -5,6 +5,9 @@
.tags {
direction: ltr;
}
h2, h3, h4, h5, h6 {
padding-right: 2rem;
}
blockquote {
border-left: 10px solid rgba( 134, 134, 134, .4 );
padding-left: 0.85rem;
@ -44,6 +47,9 @@
#body .tab-nav-button:first-child {
margin-left: 9px;
}
.autocomplete-suggestion > .context {
margin-left: 1em;
}
/* set default colors as in variant.css for IE11 */
body {
@ -136,10 +142,6 @@
font-family: "Work Sans", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif; /* var(--MAIN-TITLES-TEXT-font) */
}
h2, h3, h4, h5, h6 {
padding-right: 2rem;
}
div.box {
background-color: rgba( 128, 128, 128, 1 ); /* var(--INTERNAL-BOX-NEUTRAL-color) */
}
@ -337,14 +339,14 @@
background-color: rgba( 128, 128, 128, 1 ); /* var(--BOX-NEUTRAL-color) */
}
.btn a {
.btn > * {
border-color: rgba( 128, 128, 128, 1 ); /* var(--BOX-NEUTRAL-color) */
color: rgba( 255, 255, 255, 1 ); /* var(--BOX-CAPTION-color) */
}
.btn a:hover,
.btn a:focus,
.btn a:active {
.btn > *:hover,
.btn > *:focus,
.btn > *:active {
background-color: rgba( 255, 255, 255, .833 ); /* var(--BOX-BG-color) */
color: rgba( 16, 16, 16, 1 ); /* var(--BOX-NEUTRAL-TEXT-color) */
}
@ -353,7 +355,7 @@
background-color: rgba( 48, 117, 229, 1 ); /* var(--BOX-INFO-color) */
}
.btn.cstyle.info a {
.btn.cstyle.info > * {
border-color: rgba( 48, 117, 229, 1 ); /* var(--BOX-INFO-color) */
}
@ -361,7 +363,7 @@
background-color: rgba( 237, 153, 9, 1 ); /* var(--BOX-NOTE-color) */
}
.btn.cstyle.note a {
.btn.cstyle.note > * {
border-color: rgba( 237, 153, 9, 1 ); /* var(--BOX-NOTE-color) */
}
@ -369,7 +371,7 @@
background-color: rgba( 42, 178, 24, 1 ); /* var(--BOX-TIP-color) */
}
.btn.cstyle.tip a {
.btn.cstyle.tip > * {
border-color: rgba( 42, 178, 24, 1 ); /* var(--BOX-TIP-color) */
}
@ -377,7 +379,7 @@
background-color: rgba( 224, 62, 62, 1 ); /* var(--BOX-WARNING-color) */
}
.btn.cstyle.warning a {
.btn.cstyle.warning > * {
border-color: rgba( 224, 62, 62, 1 ); /* var(--BOX-WARNING-color) */
}
@ -385,7 +387,7 @@
background-color: #7dc903; /* var(--PRIMARY-color) */
}
.btn.cstyle.primary a {
.btn.cstyle.primary > * {
border-color: #7dc903; /* var(--PRIMARY-color) */
}
@ -393,7 +395,7 @@
background-color: #486ac9; /* var(--SECONDARY-color) */
}
.btn.cstyle.secondary a {
.btn.cstyle.secondary > * {
border-color: #486ac9; /* var(--SECONDARY-color) */
}
@ -401,7 +403,7 @@
background-color: rgba( 48, 117, 229, 1 ); /* var(--BOX-BLUE-color) */
}
.btn.cstyle.blue a {
.btn.cstyle.blue > * {
border-color: rgba( 48, 117, 229, 1 ); /* var(--BOX-BLUE-color) */
}
@ -409,7 +411,7 @@
background-color: rgba( 42, 178, 24, 1 ); /* var(--BOX-GREEN-color) */
}
.btn.cstyle.green a {
.btn.cstyle.green > * {
border-color: rgba( 42, 178, 24, 1 ); /* var(--BOX-GREEN-color) */
}
@ -417,7 +419,7 @@
background-color: rgba( 128, 128, 128, 1 ); /* var(--BOX-GREY-color) */
}
.btn.cstyle.grey a {
.btn.cstyle.grey > * {
border-color: rgba( 128, 128, 128, 1 ); /* var(--BOX-GREY-color) */
}
@ -425,7 +427,7 @@
background-color: rgba( 237, 153, 9, 1 ); /* var(--BOX-ORANGE-color) */
}
.btn.cstyle.orange a {
.btn.cstyle.orange > * {
border-color: rgba( 237, 153, 9, 1 ); /* var(--BOX-ORANGE-color) */
}
@ -433,7 +435,7 @@
background-color: rgba( 224, 62, 62, 1 ); /* var(--BOX-RED-color) */
}
.btn.cstyle.red a {
.btn.cstyle.red > * {
border-color: rgba( 224, 62, 62, 1 ); /* var(--BOX-RED-color) */
}
@ -448,7 +450,7 @@
background-color: rgba( 128, 128, 128, 1 ); /* var(--BOX-NEUTRAL-color) */
}
.btn.cstyle.transparent a {
.btn.cstyle.transparent > * {
color: #4a4a4a; /* var(--MAIN-TITLES-TEXT-color) */
}

View file

@ -208,6 +208,7 @@ body div.box {
}
body .btn,
body .btn > *,
body div.box > .box-label {
text-shadow:
0 0 1px #fff,
@ -224,14 +225,14 @@ body .btn.cstyle.transparent {
--VARIABLE-BOX-BG-color: var(--INTERNAL-BOX-BG-color);
}
body .btn.cstyle.transparent a {
body .btn.cstyle.transparent > * {
border-color: var(--VARIABLE-BOX-color);
color: var(--VARIABLE-BOX-CAPTION-color);
}
body .btn.cstyle.transparent a:hover,
body .btn.cstyle.transparent a:focus,
body .btn.cstyle.transparent a:active {
body .btn.cstyle.transparent > *:hover,
body .btn.cstyle.transparent > *:focus,
body .btn.cstyle.transparent > *:active {
background-color: var(--INTERNAL-MAIN-TITLES-TEXT-color);
color: var(--INTERNAL-MAIN-TEXT-color);
}

View file

@ -86,18 +86,31 @@ th {
margin-top: 1rem;
}
.searchbox > i {
.searchbox > :first-child {
color: rgba( 255, 255, 255, .8 );
position: absolute;
left: 10px;
top: 6px;
}
.searchbox > button {
-webkit-appearance: none;
appearance: none;
background-color: transparent;
border: 0;
margin: 0;
padding: 0;
top: 4px;
}
.searchbox > i {
top: 7px;
}
.searchbox span {
color: rgba( 255, 255, 255, .6 );
position: absolute;
right: 10px;
top: 3px;
top: 4px;
cursor: pointer;
}
@ -116,10 +129,7 @@ th {
font-weight: 300;
}
.searchbox input:-ms-input-placeholder {
color: rgba( 255, 255, 255, .4 );
}
.searchbox input:-ms-input-placeholder,
.searchbox input::placeholder {
color: rgba( 255, 255, 255, .4 );
}
@ -1204,7 +1214,7 @@ option {
display: inline-block;
font-size: .9rem;
font-weight: 500;
line-height: 1.42857143;
line-height: 1.1;
margin-bottom: 0;
touch-action: manipulation;
-ms-user-select: none;
@ -1212,7 +1222,16 @@ option {
user-select: none;
}
.btn a {
.btn > :where(button) {
-webkit-appearance: none;
appearance: none;
border-width: 0;
margin: 0;
padding: 0;
}
.btn > * {
background-color: transparent;
border-radius: 4px;
border-style: solid;
border-width: 1px;
@ -1223,19 +1242,18 @@ option {
-webkit-user-select: none;
user-select: none;
white-space: nowrap;
}
#body #body-inner .btn > *.highlight:after {
background-color: transparent;
}
#body #body-inner .btn a.highlight:after {
background-color: transparent;
}
.btn a:focus {
.btn > *:focus {
outline: none;
}
.btn a:hover,
.btn a:focus {
.btn > *:hover,
.btn > *:focus {
text-decoration: none;
}

View file

@ -366,14 +366,14 @@ pre .copy-to-clipboard-button:hover {
background-color: var(--VARIABLE-BOX-color);
}
.btn a {
.btn > * {
border-color: var(--VARIABLE-BOX-color);
color: var(--VARIABLE-BOX-CAPTION-color);
}
.btn a:hover,
.btn a:focus,
.btn a:active {
.btn > *:hover,
.btn > *:focus,
.btn > *:active {
background-color: var(--VARIABLE-BOX-BG-color);
color: var(--VARIABLE-BOX-TEXT-color);
}
@ -388,7 +388,7 @@ pre .copy-to-clipboard-button:hover {
background-color: var(--INTERNAL-BOX-NEUTRAL-color);
}
.btn.cstyle.transparent a {
.btn.cstyle.transparent > * {
--VARIABLE-BOX-color: var(--INTERNAL-BOX-NEUTRAL-color);
--VARIABLE-BOX-TEXT-color: var(--VARIABLE-BOX-CAPTION-color);
}

View file

@ -1,8 +1,13 @@
/*
JavaScript autoComplete v1.0.4
JavaScript autoComplete v1.0.4+
#46 - positioning
#75 - complete
McShelby/hugo-theme-relearn#155
- sticky dropdown on scrolling
McShelby/hugo-theme-relearn#3xx
- don't empty search input if no data-val is given
- don't delete search term but close suggestions when suggestions are open
- delete search term when suggestions are closed
Copyright (c) 2014 Simon Steinberger / Pixabay
GitHub: https://github.com/Pixabay/JavaScript-autoComplete
License: http://www.opensource.org/licenses/mit-license.php
@ -159,21 +164,44 @@ var autoComplete = (function(){
if (!sel) {
next = (key == 40) ? that.sc.querySelector('.autocomplete-suggestion') : that.sc.childNodes[that.sc.childNodes.length - 1]; // first : last
next.className += ' selected';
that.value = next.getAttribute('data-val');
if (next.getAttribute('data-val')) that.value = next.getAttribute('data-val');
} else {
next = (key == 40) ? sel.nextSibling : sel.previousSibling;
if (next) {
sel.className = sel.className.replace('selected', '');
next.className += ' selected';
that.value = next.getAttribute('data-val');
if (next.getAttribute('data-val')) that.value = next.getAttribute('data-val');
}
else {
sel.className = sel.className.replace('selected', '');
that.value = that.last_val;
next = 0;
}
else { sel.className = sel.className.replace('selected', ''); that.value = that.last_val; next = 0; }
}
that.updateSC(0, next);
return false;
}
// esc
else if (key == 27) { that.value = that.last_val; that.sc.style.display = 'none'; }
else if (key == 27) {
if( that.sc.style.display != 'none' ){
var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
if (sel) {
e.preventDefault();
setTimeout(function(){
that.value = that.last_val;
that.focus();
that.sc.style.display = 'none';
}, 0);
}
else{
that.value = '';
that.sc.style.display = 'none';
}
}
else{
that.value = '';
}
}
// enter
else if (key == 13 || key == 9) {
var sel = that.sc.querySelector('.autocomplete-suggestion.selected');

View file

@ -122,6 +122,7 @@ $(function() {
/* onSelect callback fires when a search suggestion is chosen */
onSelect: function(e, term, item) {
location.href = item.getAttribute('data-uri');
e.preventDefault();
}
});

View file

@ -21,6 +21,12 @@ Prism.manual = true;
var psc;
var psm;
var pst;
var elc = document.querySelector('#body-inner');
function documentFocus(){
document.querySelector( '#body-inner' ).focus();
psc && psc.scrollbarY.focus();
}
function scrollbarWidth(){
// https://davidwalsh.name/detect-scrollbar-width
@ -35,6 +41,17 @@ function scrollbarWidth(){
return scrollbarWidth;
}
var scrollbarSize = scrollbarWidth();
function adjustContentWidth(){
var left = parseFloat( getComputedStyle( elc ).getPropertyValue( 'padding-left' ) );
var right = left;
if( elc.scrollHeight > elc.clientHeight ){
// if we have a scrollbar reduce the right margin by the scrollbar width
right = Math.max( 0, left - scrollbarSize );
}
elc.style[ 'padding-right' ] = '' + right + 'px';
}
function switchTab(tabGroup, tabId) {
var tabs = jQuery(".tab-panel").has("[data-tab-group='"+tabGroup+"'][data-tab-item='"+tabId+"']");
var allTabItems = tabs.find("[data-tab-group='"+tabGroup+"']");
@ -371,7 +388,6 @@ function initMenuScrollbar(){
return;
}
var elc = document.querySelector('#body-inner');
var elm = document.querySelector('#content-wrapper');
var elt = document.querySelector('#TableOfContents');
@ -442,16 +458,6 @@ function initMenuScrollbar(){
});
// finally, we want to adjust the contents right padding if there is a scrollbar visible
var scrollbarSize = scrollbarWidth();
function adjustContentWidth(){
var left = parseFloat( getComputedStyle( elc ).getPropertyValue( 'padding-left' ) );
var right = left;
if( elc.scrollHeight > elc.clientHeight ){
// if we have a scrollbar reduce the right margin by the scrollbar width
right = Math.max( 0, left - scrollbarSize );
}
elc.style[ 'padding-right' ] = '' + right + 'px';
}
window.addEventListener('resize', adjustContentWidth );
adjustContentWidth();
}
@ -461,8 +467,7 @@ function sidebarEscapeHandler( event ){
var b = document.querySelector( 'body' );
b.classList.remove( 'sidebar-flyout' );
document.removeEventListener( 'keydown', sidebarEscapeHandler );
document.querySelector( '#body-inner' ).focus();
psc && psc.scrollbarY.focus();
documentFocus();
}
}
@ -471,8 +476,7 @@ function tocEscapeHandler( event ){
var b = document.querySelector( 'body' );
b.classList.remove( 'toc-flyout' );
document.removeEventListener( 'keydown', tocEscapeHandler );
document.querySelector( '#body-inner' ).focus();
psc && psc.scrollbarY.focus();
documentFocus();
}
}
@ -482,6 +486,12 @@ function sidebarShortcutHandler( event ){
}
}
function searchShortcutHandler( event ){
if( !event.shiftKey && event.altKey && event.ctrlKey && !event.metaKey && event.which == 70 /* f */ ){
showSearch();
}
}
function tocShortcutHandler( event ){
if( !event.shiftKey && event.altKey && event.ctrlKey && !event.metaKey && event.which == 84 /* t */ ){
showToc();
@ -500,6 +510,22 @@ function printShortcutHandler( event ){
}
}
function showSearch(){
var s = document.querySelector( '#search-by' );
var b = document.querySelector( 'body' );
if( s == document.activeElement ){
if( b.classList.contains( 'sidebar-flyout' ) ){
showNav();
}
documentFocus();
} else {
if( !b.classList.contains( 'sidebar-flyout' ) ){
showNav();
}
s.focus();
}
}
function showNav(){
if( !document.querySelector( '#sidebar-overlay' ) ){
// we may not have a flyout
@ -514,8 +540,7 @@ function showNav(){
}
else{
document.removeEventListener( 'keydown', sidebarEscapeHandler );
document.querySelector( '#body-inner' ).focus();
psc && psc.scrollbarY.focus();
documentFocus();
}
}
@ -533,8 +558,7 @@ function showToc(){
}
else{
document.removeEventListener( 'keydown', tocEscapeHandler );
document.querySelector( '#body-inner' ).focus();
psc && psc.scrollbarY.focus();
documentFocus();
}
}
@ -560,15 +584,8 @@ function initToc(){
document.addEventListener( 'keydown', editShortcutHandler );
document.addEventListener( 'keydown', printShortcutHandler );
document.addEventListener( 'keydown', sidebarShortcutHandler );
document.addEventListener( 'keydown', searchShortcutHandler );
document.addEventListener( 'keydown', tocShortcutHandler );
// avoid keyboard navigation for input fields
jQuery(formelements).keydown(function (e) {
if( !e.shiftKey && e.altKey && e.ctrlKey && !e.metaKey){
if( e.which == 78 /* n */ || e.which == 84 /* t */ || e.which == 87 /* w */ || e.which == 80 /* p */ ){
e.stopPropagation();
}
}
});
document.querySelector( '#sidebar-overlay' ).addEventListener( 'click', showNav );
document.querySelector( '#sidebar-toggle' ).addEventListener( 'click', showNav );
@ -582,8 +599,7 @@ function initToc(){
}
// finally give initial focus to allow keyboard scrolling in FF
document.querySelector( '#body-inner' ).focus();
psc && psc.scrollbarY.focus();
documentFocus();
}
function initSwipeHandler(){
@ -613,8 +629,7 @@ function initSwipeHandler(){
var b = document.querySelector( 'body' );
b.classList.remove( 'sidebar-flyout' );
document.removeEventListener( 'keydown', sidebarEscapeHandler );
document.querySelector( '#body-inner' ).focus();
psc && psc.scrollbarY.focus();
documentFocus();
}
}
return false;
@ -721,16 +736,29 @@ function unmark(){
psm && psm.update();
}
function searchInputHandler(value) {
unmark();
if (value.length) {
sessionStorage.setItem(baseUriFull+'search-value', value);
mark();
}
}
function initSearch() {
jQuery('[data-search-input]').on('keydown', function(event) {
if (event.key == "Escape") {
var input = jQuery(this);
input.blur();
searchInputHandler( '' );
documentFocus();
}
});
jQuery('[data-search-input]').on('input', function() {
var input = jQuery(this);
var value = input.val();
unmark();
if (value.length) {
sessionStorage.setItem(baseUriFull+'search-value', value);
mark();
}
searchInputHandler( value );
});
jQuery('[data-search-clear]').on('click', function() {
jQuery('[data-search-input]').val('').trigger('input');
unmark();