summaryrefslogtreecommitdiff
path: root/client/simple/src/js/main/keyboard.js
diff options
context:
space:
mode:
authorIvan Gabaldon <igabaldon@inetol.net>2025-06-28 10:19:15 +0200
committerMarkus Heiser <markus.heiser@darmarIT.de>2025-07-03 17:35:05 +0200
commit95172213f69c8fe85a0af69dd2654c7a77327968 (patch)
treec5ce5d7f75f2be026100023ce52f227c8f521bbf /client/simple/src/js/main/keyboard.js
parenta947d5b3cff32104ee009113226feab45439dbdd (diff)
[mod] theme/simple: fmt/lint minor pass
*Safe* changes, no behaviour changes. - Initial ES5 to ES2015+ conversion. - Plenty of styling diff changes.
Diffstat (limited to 'client/simple/src/js/main/keyboard.js')
-rw-r--r--client/simple/src/js/main/keyboard.js433
1 files changed, 222 insertions, 211 deletions
diff --git a/client/simple/src/js/main/keyboard.js b/client/simple/src/js/main/keyboard.js
index e16134579..bc878c561 100644
--- a/client/simple/src/js/main/keyboard.js
+++ b/client/simple/src/js/main/keyboard.js
@@ -1,14 +1,13 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
/* global searxng */
-searxng.ready(function () {
-
- function isElementInDetail (el) {
+searxng.ready(() => {
+ function isElementInDetail(el) {
while (el !== undefined) {
- if (el.classList.contains('detail')) {
+ if (el.classList.contains("detail")) {
return true;
}
- if (el.classList.contains('result')) {
+ if (el.classList.contains("result")) {
// we found a result, no need to go to the root of the document:
// el is not inside a <div class="detail"> element
return false;
@@ -18,9 +17,9 @@ searxng.ready(function () {
return false;
}
- function getResultElement (el) {
+ function getResultElement(el) {
while (el !== undefined) {
- if (el.classList.contains('result')) {
+ if (el.classList.contains("result")) {
return el;
}
el = el.parentNode;
@@ -28,14 +27,14 @@ searxng.ready(function () {
return undefined;
}
- function isImageResult (resultElement) {
- return resultElement && resultElement.classList.contains('result-images');
+ function isImageResult(resultElement) {
+ return resultElement && resultElement.classList.contains("result-images");
}
- searxng.on('.result', 'click', function (e) {
+ searxng.on(".result", "click", function (e) {
if (!isElementInDetail(e.target)) {
highlightResult(this)(true, true);
- let resultElement = getResultElement(e.target);
+ const resultElement = getResultElement(e.target);
if (isImageResult(resultElement)) {
e.preventDefault();
searxng.selectImage(resultElement);
@@ -43,166 +42,179 @@ searxng.ready(function () {
}
});
- searxng.on('.result a', 'focus', function (e) {
- if (!isElementInDetail(e.target)) {
- let resultElement = getResultElement(e.target);
- if (resultElement && resultElement.getAttribute("data-vim-selected") === null) {
- highlightResult(resultElement)(true);
- }
- if (isImageResult(resultElement)) {
- searxng.selectImage(resultElement);
+ searxng.on(
+ ".result a",
+ "focus",
+ (e) => {
+ if (!isElementInDetail(e.target)) {
+ const resultElement = getResultElement(e.target);
+ if (resultElement && resultElement.getAttribute("data-vim-selected") === null) {
+ highlightResult(resultElement)(true);
+ }
+ if (isImageResult(resultElement)) {
+ searxng.selectImage(resultElement);
+ }
}
- }
- }, true);
+ },
+ true
+ );
/* common base for layouts */
var baseKeyBinding = {
- 'Escape': {
- key: 'ESC',
+ Escape: {
+ key: "ESC",
fun: removeFocus,
- des: 'remove focus from the focused input',
- cat: 'Control'
+ des: "remove focus from the focused input",
+ cat: "Control"
},
- 'c': {
- key: 'c',
+ c: {
+ key: "c",
fun: copyURLToClipboard,
- des: 'copy url of the selected result to the clipboard',
- cat: 'Results'
+ des: "copy url of the selected result to the clipboard",
+ cat: "Results"
},
- 'h': {
- key: 'h',
+ h: {
+ key: "h",
fun: toggleHelp,
- des: 'toggle help window',
- cat: 'Other'
+ des: "toggle help window",
+ cat: "Other"
},
- 'i': {
- key: 'i',
+ i: {
+ key: "i",
fun: searchInputFocus,
- des: 'focus on the search input',
- cat: 'Control'
+ des: "focus on the search input",
+ cat: "Control"
},
- 'n': {
- key: 'n',
+ n: {
+ key: "n",
fun: GoToNextPage(),
- des: 'go to next page',
- cat: 'Results'
+ des: "go to next page",
+ cat: "Results"
},
- 'o': {
- key: 'o',
+ o: {
+ key: "o",
fun: openResult(false),
- des: 'open search result',
- cat: 'Results'
+ des: "open search result",
+ cat: "Results"
},
- 'p': {
- key: 'p',
+ p: {
+ key: "p",
fun: GoToPreviousPage(),
- des: 'go to previous page',
- cat: 'Results'
+ des: "go to previous page",
+ cat: "Results"
},
- 'r': {
- key: 'r',
+ r: {
+ key: "r",
fun: reloadPage,
- des: 'reload page from the server',
- cat: 'Control'
+ des: "reload page from the server",
+ cat: "Control"
},
- 't': {
- key: 't',
+ t: {
+ key: "t",
fun: openResult(true),
- des: 'open the result in a new tab',
- cat: 'Results'
- },
+ des: "open the result in a new tab",
+ cat: "Results"
+ }
};
var keyBindingLayouts = {
-
- "default": Object.assign(
- { /* SearXNG layout */
- 'ArrowLeft': {
- key: '←',
- fun: highlightResult('up'),
- des: 'select previous search result',
- cat: 'Results'
- },
- 'ArrowRight': {
- key: '→',
- fun: highlightResult('down'),
- des: 'select next search result',
- cat: 'Results'
+ default: Object.assign(
+ {
+ /* SearXNG layout */
+ ArrowLeft: {
+ key: "←",
+ fun: highlightResult("up"),
+ des: "select previous search result",
+ cat: "Results"
},
- }, baseKeyBinding),
-
- 'vim': Object.assign(
- { /* Vim-like Key Layout. */
- 'b': {
- key: 'b',
+ ArrowRight: {
+ key: "→",
+ fun: highlightResult("down"),
+ des: "select next search result",
+ cat: "Results"
+ }
+ },
+ baseKeyBinding
+ ),
+
+ vim: Object.assign(
+ {
+ /* Vim-like Key Layout. */
+ b: {
+ key: "b",
fun: scrollPage(-window.innerHeight),
- des: 'scroll one page up',
- cat: 'Navigation'
+ des: "scroll one page up",
+ cat: "Navigation"
},
- 'f': {
- key: 'f',
+ f: {
+ key: "f",
fun: scrollPage(window.innerHeight),
- des: 'scroll one page down',
- cat: 'Navigation'
+ des: "scroll one page down",
+ cat: "Navigation"
},
- 'u': {
- key: 'u',
+ u: {
+ key: "u",
fun: scrollPage(-window.innerHeight / 2),
- des: 'scroll half a page up',
- cat: 'Navigation'
+ des: "scroll half a page up",
+ cat: "Navigation"
},
- 'd': {
- key: 'd',
+ d: {
+ key: "d",
fun: scrollPage(window.innerHeight / 2),
- des: 'scroll half a page down',
- cat: 'Navigation'
+ des: "scroll half a page down",
+ cat: "Navigation"
},
- 'g': {
- key: 'g',
- fun: scrollPageTo(-document.body.scrollHeight, 'top'),
- des: 'scroll to the top of the page',
- cat: 'Navigation'
+ g: {
+ key: "g",
+ fun: scrollPageTo(-document.body.scrollHeight, "top"),
+ des: "scroll to the top of the page",
+ cat: "Navigation"
},
- 'v': {
- key: 'v',
- fun: scrollPageTo(document.body.scrollHeight, 'bottom'),
- des: 'scroll to the bottom of the page',
- cat: 'Navigation'
+ v: {
+ key: "v",
+ fun: scrollPageTo(document.body.scrollHeight, "bottom"),
+ des: "scroll to the bottom of the page",
+ cat: "Navigation"
},
- 'k': {
- key: 'k',
- fun: highlightResult('up'),
- des: 'select previous search result',
- cat: 'Results'
+ k: {
+ key: "k",
+ fun: highlightResult("up"),
+ des: "select previous search result",
+ cat: "Results"
},
- 'j': {
- key: 'j',
- fun: highlightResult('down'),
- des: 'select next search result',
- cat: 'Results'
+ j: {
+ key: "j",
+ fun: highlightResult("down"),
+ des: "select next search result",
+ cat: "Results"
},
- 'y': {
- key: 'y',
+ y: {
+ key: "y",
fun: copyURLToClipboard,
- des: 'copy url of the selected result to the clipboard',
- cat: 'Results'
- },
- }, baseKeyBinding)
- }
+ des: "copy url of the selected result to the clipboard",
+ cat: "Results"
+ }
+ },
+ baseKeyBinding
+ )
+ };
var keyBindings = keyBindingLayouts[searxng.settings.hotkeys] || keyBindingLayouts.default;
- searxng.on(document, "keydown", function (e) {
+ searxng.on(document, "keydown", (e) => {
// check for modifiers so we don't break browser's hotkeys
if (
- Object.prototype.hasOwnProperty.call(keyBindings, e.key)
- && !e.ctrlKey && !e.altKey
- && !e.shiftKey && !e.metaKey
+ // biome-ignore lint/suspicious/noPrototypeBuiltins: FIXME: support for Chromium 93-87, Firefox 92-78, Safari 15.4-14
+ Object.prototype.hasOwnProperty.call(keyBindings, e.key) &&
+ !e.ctrlKey &&
+ !e.altKey &&
+ !e.shiftKey &&
+ !e.metaKey
) {
var tagName = e.target.tagName.toLowerCase();
- if (e.key === 'Escape') {
+ if (e.key === "Escape") {
keyBindings[e.key].fun(e);
} else {
- if (e.target === document.body || tagName === 'a' || tagName === 'button') {
+ if (e.target === document.body || tagName === "a" || tagName === "button") {
e.preventDefault();
keyBindings[e.key].fun();
}
@@ -210,13 +222,13 @@ searxng.ready(function () {
}
});
- function highlightResult (which) {
- return function (noScroll, keepFocus) {
- var current = document.querySelector('.result[data-vim-selected]'),
+ function highlightResult(which) {
+ return (noScroll, keepFocus) => {
+ var current = document.querySelector(".result[data-vim-selected]"),
effectiveWhich = which;
if (current === null) {
// no selection : choose the first one
- current = document.querySelector('.result');
+ current = document.querySelector(".result");
if (current === null) {
// no first one : there are no results
return;
@@ -227,48 +239,50 @@ searxng.ready(function () {
}
}
- var next, results = document.querySelectorAll('.result');
- results = Array.from(results); // convert NodeList to Array for further use
+ var next,
+ results = document.querySelectorAll(".result");
+ results = Array.from(results); // convert NodeList to Array for further use
- if (typeof effectiveWhich !== 'string') {
+ if (typeof effectiveWhich !== "string") {
next = effectiveWhich;
} else {
switch (effectiveWhich) {
- case 'visible':
- var top = document.documentElement.scrollTop || document.body.scrollTop;
- var bot = top + document.documentElement.clientHeight;
-
- for (var i = 0; i < results.length; i++) {
- next = results[i];
- var etop = next.offsetTop;
- var ebot = etop + next.clientHeight;
-
- if ((ebot <= bot) && (etop > top)) {
- break;
+ case "visible": {
+ var top = document.documentElement.scrollTop || document.body.scrollTop;
+ var bot = top + document.documentElement.clientHeight;
+
+ for (var i = 0; i < results.length; i++) {
+ next = results[i];
+ var etop = next.offsetTop;
+ var ebot = etop + next.clientHeight;
+
+ if (ebot <= bot && etop > top) {
+ break;
+ }
}
+ break;
}
- break;
- case 'down':
- next = results[results.indexOf(current) + 1] || current;
- break;
- case 'up':
- next = results[results.indexOf(current) - 1] || current;
- break;
- case 'bottom':
- next = results[results.length - 1];
- break;
- case 'top':
+ case "down":
+ next = results[results.indexOf(current) + 1] || current;
+ break;
+ case "up":
+ next = results[results.indexOf(current) - 1] || current;
+ break;
+ case "bottom":
+ next = results[results.length - 1];
+ break;
+ case "top":
/* falls through */
- default:
- next = results[0];
+ default:
+ next = results[0];
}
}
if (next) {
- current.removeAttribute('data-vim-selected');
- next.setAttribute('data-vim-selected', 'true');
+ current.removeAttribute("data-vim-selected");
+ next.setAttribute("data-vim-selected", "true");
if (!keepFocus) {
- var link = next.querySelector('h3 a') || next.querySelector('a');
+ var link = next.querySelector("h3 a") || next.querySelector("a");
if (link !== null) {
link.focus();
}
@@ -280,21 +294,21 @@ searxng.ready(function () {
};
}
- function reloadPage () {
+ function reloadPage() {
document.location.reload(true);
}
- function removeFocus (e) {
+ function removeFocus(e) {
const tagName = e.target.tagName.toLowerCase();
- if (document.activeElement && (tagName === 'input' || tagName === 'select' || tagName === 'textarea')) {
+ if (document.activeElement && (tagName === "input" || tagName === "select" || tagName === "textarea")) {
document.activeElement.blur();
} else {
searxng.closeDetail();
}
}
- function pageButtonClick (css_selector) {
- return function () {
+ function pageButtonClick(css_selector) {
+ return () => {
var button = document.querySelector(css_selector);
if (button) {
button.click();
@@ -302,16 +316,16 @@ searxng.ready(function () {
};
}
- function GoToNextPage () {
+ function GoToNextPage() {
return pageButtonClick('nav#pagination .next_page button[type="submit"]');
}
- function GoToPreviousPage () {
+ function GoToPreviousPage() {
return pageButtonClick('nav#pagination .previous_page button[type="submit"]');
}
- function scrollPageToSelected () {
- var sel = document.querySelector('.result[data-vim-selected]');
+ function scrollPageToSelected() {
+ var sel = document.querySelector(".result[data-vim-selected]");
if (sel === null) {
return;
}
@@ -321,39 +335,39 @@ searxng.ready(function () {
ebot = etop + sel.clientHeight,
offset = 120;
// first element ?
- if ((sel.previousElementSibling === null) && (ebot < wheight)) {
+ if (sel.previousElementSibling === null && ebot < wheight) {
// set to the top of page if the first element
// is fully included in the viewport
window.scroll(window.scrollX, 0);
return;
}
- if (wtop > (etop - offset)) {
+ if (wtop > etop - offset) {
window.scroll(window.scrollX, etop - offset);
} else {
var wbot = wtop + wheight;
- if (wbot < (ebot + offset)) {
+ if (wbot < ebot + offset) {
window.scroll(window.scrollX, ebot - wheight + offset);
}
}
}
- function scrollPage (amount) {
- return function () {
+ function scrollPage(amount) {
+ return () => {
window.scrollBy(0, amount);
- highlightResult('visible')();
+ highlightResult("visible")();
};
}
- function scrollPageTo (position, nav) {
- return function () {
+ function scrollPageTo(position, nav) {
+ return () => {
window.scrollTo(0, position);
highlightResult(nav)();
};
}
- function searchInputFocus () {
+ function searchInputFocus() {
window.scrollTo(0, 0);
- var q = document.querySelector('#q');
+ var q = document.querySelector("#q");
q.focus();
if (q.setSelectionRange) {
var len = q.value.length;
@@ -361,14 +375,14 @@ searxng.ready(function () {
}
}
- function openResult (newTab) {
- return function () {
- var link = document.querySelector('.result[data-vim-selected] h3 a');
+ function openResult(newTab) {
+ return () => {
+ var link = document.querySelector(".result[data-vim-selected] h3 a");
if (link === null) {
- link = document.querySelector('.result[data-vim-selected] > a');
+ link = document.querySelector(".result[data-vim-selected] > a");
}
if (link !== null) {
- var url = link.getAttribute('href');
+ var url = link.getAttribute("href");
if (newTab) {
window.open(url);
} else {
@@ -378,7 +392,7 @@ searxng.ready(function () {
};
}
- function initHelpContent (divElement) {
+ function initHelpContent(divElement) {
var categories = {};
for (var k in keyBindings) {
@@ -387,75 +401,72 @@ searxng.ready(function () {
categories[key.cat].push(key);
}
- var sorted = Object.keys(categories).sort(function (a, b) {
- return categories[b].length - categories[a].length;
- });
+ var sorted = Object.keys(categories).sort((a, b) => categories[b].length - categories[a].length);
if (sorted.length === 0) {
return;
}
var html = '<a href="#" class="close" aria-label="close" title="close">×</a>';
- html += '<h3>How to navigate SearXNG with hotkeys</h3>';
- html += '<table>';
+ html += "<h3>How to navigate SearXNG with hotkeys</h3>";
+ html += "<table>";
for (var i = 0; i < sorted.length; i++) {
var cat = categories[sorted[i]];
- var lastCategory = i === (sorted.length - 1);
+ var lastCategory = i === sorted.length - 1;
var first = i % 2 === 0;
if (first) {
- html += '<tr>';
+ html += "<tr>";
}
- html += '<td>';
+ html += "<td>";
- html += '<h4>' + cat[0].cat + '</h4>';
+ html += "<h4>" + cat[0].cat + "</h4>";
html += '<ul class="list-unstyled">';
for (var cj in cat) {
- html += '<li><kbd>' + cat[cj].key + '</kbd> ' + cat[cj].des + '</li>';
+ html += "<li><kbd>" + cat[cj].key + "</kbd> " + cat[cj].des + "</li>";
}
- html += '</ul>';
- html += '</td>'; // col-sm-*
+ html += "</ul>";
+ html += "</td>"; // col-sm-*
if (!first || lastCategory) {
- html += '</tr>'; // row
+ html += "</tr>"; // row
}
}
- html += '</table>';
+ html += "</table>";
divElement.innerHTML = html;
}
- function toggleHelp () {
- var helpPanel = document.querySelector('#vim-hotkeys-help');
+ function toggleHelp() {
+ var helpPanel = document.querySelector("#vim-hotkeys-help");
if (helpPanel === undefined || helpPanel === null) {
// first call
- helpPanel = document.createElement('div');
- helpPanel.id = 'vim-hotkeys-help';
- helpPanel.className = 'dialog-modal';
+ helpPanel = document.createElement("div");
+ helpPanel.id = "vim-hotkeys-help";
+ helpPanel.className = "dialog-modal";
initHelpContent(helpPanel);
- var body = document.getElementsByTagName('body')[0];
+ var body = document.getElementsByTagName("body")[0];
body.appendChild(helpPanel);
} else {
// toggle hidden
- helpPanel.classList.toggle('invisible');
- return;
+ helpPanel.classList.toggle("invisible");
}
}
- function copyURLToClipboard () {
- var currentUrlElement = document.querySelector('.result[data-vim-selected] h3 a');
+ function copyURLToClipboard() {
+ var currentUrlElement = document.querySelector(".result[data-vim-selected] h3 a");
if (currentUrlElement === null) return;
- const url = currentUrlElement.getAttribute('href');
+ const url = currentUrlElement.getAttribute("href");
navigator.clipboard.writeText(url);
}
searxng.scrollPageToSelected = scrollPageToSelected;
- searxng.selectNext = highlightResult('down');
- searxng.selectPrevious = highlightResult('up');
+ searxng.selectNext = highlightResult("down");
+ searxng.selectPrevious = highlightResult("up");
});