mirror of
https://github.com/searxng/searxng.git
synced 2026-05-29 22:24:13 +02:00
aa607a379a
Bumps the minor group in /client/simple with 6 updates: | Package | From | To | | --- | --- | --- | | [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.3.8` | `2.3.10` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.0.1` | `25.0.3` | | [edge.js](https://github.com/edge-js/edge) | `6.3.0` | `6.4.0` | | [less](https://github.com/less/less.js) | `4.4.2` | `4.5.1` | | [sort-package-json](https://github.com/keithamus/sort-package-json) | `3.5.1` | `3.6.0` | | [vite-bundle-analyzer](https://github.com/nonzzz/vite-bundle-analyzer) | `1.3.1` | `1.3.2` | Updates `@biomejs/biome` from 2.3.8 to 2.3.10 - [Release notes](https://github.com/biomejs/biome/releases) - [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md) - [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.3.10/packages/@biomejs/biome) Updates `@types/node` from 25.0.1 to 25.0.3 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `edge.js` from 6.3.0 to 6.4.0 - [Release notes](https://github.com/edge-js/edge/releases) - [Changelog](https://github.com/edge-js/edge/blob/6.x/CHANGELOG.md) - [Commits](https://github.com/edge-js/edge/compare/v6.3.0...v6.4.0) Updates `less` from 4.4.2 to 4.5.1 - [Release notes](https://github.com/less/less.js/releases) - [Changelog](https://github.com/less/less.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/less/less.js/commits) Updates `sort-package-json` from 3.5.1 to 3.6.0 - [Release notes](https://github.com/keithamus/sort-package-json/releases) - [Commits](https://github.com/keithamus/sort-package-json/compare/v3.5.1...v3.6.0) Updates `vite-bundle-analyzer` from 1.3.1 to 1.3.2 - [Release notes](https://github.com/nonzzz/vite-bundle-analyzer/releases) - [Changelog](https://github.com/nonzzz/vite-bundle-analyzer/blob/master/CHANGELOG.md) - [Commits](https://github.com/nonzzz/vite-bundle-analyzer/compare/v1.3.1...v1.3.2) --- updated-dependencies: - dependency-name: "@biomejs/biome" dependency-version: 2.3.10 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: minor - dependency-name: "@types/node" dependency-version: 25.0.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: minor - dependency-name: edge.js dependency-version: 6.4.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor - dependency-name: less dependency-version: 4.5.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor - dependency-name: sort-package-json dependency-version: 3.6.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor - dependency-name: vite-bundle-analyzer dependency-version: 1.3.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: minor ... Signed-off-by: dependabot[bot] <support@github.com>
190 lines
6.0 KiB
TypeScript
190 lines
6.0 KiB
TypeScript
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
import "../../../node_modules/swiped-events/src/swiped-events.js";
|
|
import { listen, mutable, settings } from "../toolkit.ts";
|
|
import { assertElement } from "../util/assertElement.ts";
|
|
|
|
let imgTimeoutID: number;
|
|
|
|
const imageLoader = (resultElement: HTMLElement): void => {
|
|
if (imgTimeoutID) clearTimeout(imgTimeoutID);
|
|
|
|
const imgElement = resultElement.querySelector<HTMLImageElement>(".result-images-source img");
|
|
if (!imgElement) return;
|
|
|
|
// use thumbnail until full image loads
|
|
const thumbnail = resultElement.querySelector<HTMLImageElement>(".image_thumbnail");
|
|
if (thumbnail) {
|
|
if (thumbnail.src === `${settings.theme_static_path}/img/img_load_error.svg`) return;
|
|
|
|
imgElement.onerror = (): void => {
|
|
imgElement.src = thumbnail.src;
|
|
};
|
|
|
|
imgElement.src = thumbnail.src;
|
|
}
|
|
|
|
const imgSource = imgElement.getAttribute("data-src");
|
|
if (!imgSource) return;
|
|
|
|
// unsafe nodejs specific, cast to https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout#return_value
|
|
// https://github.com/searxng/searxng/pull/5073#discussion_r2265767231
|
|
imgTimeoutID = setTimeout(() => {
|
|
imgElement.src = imgSource;
|
|
imgElement.removeAttribute("data-src");
|
|
}, 1000) as unknown as number;
|
|
};
|
|
|
|
const imageThumbnails: NodeListOf<HTMLImageElement> =
|
|
document.querySelectorAll<HTMLImageElement>("#urls img.image_thumbnail");
|
|
for (const thumbnail of imageThumbnails) {
|
|
if (thumbnail.complete && thumbnail.naturalWidth === 0) {
|
|
thumbnail.src = `${settings.theme_static_path}/img/img_load_error.svg`;
|
|
}
|
|
|
|
thumbnail.onerror = (): void => {
|
|
thumbnail.src = `${settings.theme_static_path}/img/img_load_error.svg`;
|
|
};
|
|
}
|
|
|
|
const copyUrlButton: HTMLButtonElement | null =
|
|
document.querySelector<HTMLButtonElement>("#search_url button#copy_url");
|
|
copyUrlButton?.style.setProperty("display", "block");
|
|
|
|
mutable.selectImage = (resultElement: HTMLElement): void => {
|
|
// add a class that can be evaluated in the CSS and indicates that the
|
|
// detail view is open
|
|
const resultsElement = document.getElementById("results");
|
|
resultsElement?.classList.add("image-detail-open");
|
|
|
|
// add a hash to the browser history so that pressing back doesn't return
|
|
// to the previous page this allows us to dismiss the image details on
|
|
// pressing the back button on mobile devices
|
|
window.location.hash = "#image-viewer";
|
|
|
|
mutable.scrollPageToSelected?.();
|
|
|
|
// if there is no element given by the caller, stop here
|
|
if (!resultElement) return;
|
|
|
|
imageLoader(resultElement);
|
|
};
|
|
|
|
mutable.closeDetail = (): void => {
|
|
const resultsElement = document.getElementById("results");
|
|
resultsElement?.classList.remove("image-detail-open");
|
|
|
|
// remove #image-viewer hash from url by navigating back
|
|
if (window.location.hash === "#image-viewer") {
|
|
window.history.back();
|
|
}
|
|
|
|
mutable.scrollPageToSelected?.();
|
|
};
|
|
|
|
listen("click", ".btn-collapse", function (this: HTMLElement) {
|
|
const btnLabelCollapsed = this.getAttribute("data-btn-text-collapsed");
|
|
const btnLabelNotCollapsed = this.getAttribute("data-btn-text-not-collapsed");
|
|
const target = this.getAttribute("data-target");
|
|
|
|
if (!(target && btnLabelCollapsed && btnLabelNotCollapsed)) return;
|
|
|
|
const targetElement = document.querySelector<HTMLElement>(target);
|
|
assertElement(targetElement);
|
|
|
|
const isCollapsed = this.classList.contains("collapsed");
|
|
const newLabel = isCollapsed ? btnLabelNotCollapsed : btnLabelCollapsed;
|
|
const oldLabel = isCollapsed ? btnLabelCollapsed : btnLabelNotCollapsed;
|
|
|
|
this.innerHTML = this.innerHTML.replace(oldLabel, newLabel);
|
|
this.classList.toggle("collapsed");
|
|
|
|
targetElement.classList.toggle("invisible");
|
|
});
|
|
|
|
listen("click", ".media-loader", function (this: HTMLElement) {
|
|
const target = this.getAttribute("data-target");
|
|
if (!target) return;
|
|
|
|
const iframeLoad = document.querySelector<HTMLIFrameElement>(`${target} > iframe`);
|
|
assertElement(iframeLoad);
|
|
|
|
const srctest = iframeLoad.getAttribute("src");
|
|
if (!srctest) {
|
|
const dataSrc = iframeLoad.getAttribute("data-src");
|
|
if (dataSrc) {
|
|
iframeLoad.setAttribute("src", dataSrc);
|
|
}
|
|
}
|
|
});
|
|
|
|
listen("click", "#copy_url", async function (this: HTMLElement) {
|
|
const target = this.parentElement?.querySelector<HTMLPreElement>("pre");
|
|
assertElement(target);
|
|
|
|
if (window.isSecureContext) {
|
|
await navigator.clipboard.writeText(target.innerText);
|
|
} else {
|
|
const selection = window.getSelection();
|
|
if (selection) {
|
|
const range = document.createRange();
|
|
range.selectNodeContents(target);
|
|
selection.removeAllRanges();
|
|
selection.addRange(range);
|
|
document.execCommand("copy");
|
|
}
|
|
}
|
|
|
|
if (this.dataset.copiedText) {
|
|
this.innerText = this.dataset.copiedText;
|
|
}
|
|
});
|
|
|
|
listen("click", ".result-detail-close", (event: Event) => {
|
|
event.preventDefault();
|
|
mutable.closeDetail?.();
|
|
});
|
|
|
|
listen("click", ".result-detail-previous", (event: Event) => {
|
|
event.preventDefault();
|
|
mutable.selectPrevious?.(false);
|
|
});
|
|
|
|
listen("click", ".result-detail-next", (event: Event) => {
|
|
event.preventDefault();
|
|
mutable.selectNext?.(false);
|
|
});
|
|
|
|
// listen for the back button to be pressed and dismiss the image details when called
|
|
window.addEventListener("hashchange", () => {
|
|
if (window.location.hash !== "#image-viewer") {
|
|
mutable.closeDetail?.();
|
|
}
|
|
});
|
|
|
|
const swipeHorizontal: NodeListOf<HTMLElement> = document.querySelectorAll<HTMLElement>(".swipe-horizontal");
|
|
for (const element of swipeHorizontal) {
|
|
listen("swiped-left", element, () => {
|
|
mutable.selectNext?.(false);
|
|
});
|
|
|
|
listen("swiped-right", element, () => {
|
|
mutable.selectPrevious?.(false);
|
|
});
|
|
}
|
|
|
|
window.addEventListener(
|
|
"scroll",
|
|
() => {
|
|
const backToTopElement = document.getElementById("backToTop");
|
|
const resultsElement = document.getElementById("results");
|
|
|
|
if (backToTopElement && resultsElement) {
|
|
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
|
|
const isScrolling = scrollTop >= 100;
|
|
resultsElement.classList.toggle("scrolling", isScrolling);
|
|
}
|
|
},
|
|
true
|
|
);
|