Skip to content

Instantly share code, notes, and snippets.

@DickHorner
Last active May 3, 2026 10:42
Show Gist options
  • Select an option

  • Save DickHorner/ff8ab6c321d46bde2cf63647c1bbc43a to your computer and use it in GitHub Desktop.

Select an option

Save DickHorner/ff8ab6c321d46bde2cf63647c1bbc43a to your computer and use it in GitHub Desktop.
Userscript: Landesarchiv Berlin: Bild öffnen
// ==UserScript==
// @name Landesarchiv Berlin: Bild öffnen
// @homepageURL https://gist.github.com/DickHorner/ff8ab6c321d46bde2cf63647c1bbc43a
// @namespace DickHorner
// @author Dick Horner
// @version 1.0.4
// @description Öffnet eingebettete Bilder in Landesarchiv-Findbuch-Ansichten per Klick als Rohbild in einem neuen Tab.
// @match https://www.landesarchiv-berlin.findbuch.net/*
// @match http://www.landesarchiv-berlin.findbuch.net/*
// @run-at document-start
// @grant GM_openInTab
// ==/UserScript==
(function () {
'use strict';
const IMAGE_EXT_RE = /\.(jpe?g|png|gif|webp|tif|tiff)(?:[?#].*)?$/i;
const URL_KEYS = ['path', 'file', 'filename', 'image', 'img', 'src', 'url'];
function isRawImagePage() {
if (/^image\//i.test(document.contentType || '')) {
return true;
}
if (IMAGE_EXT_RE.test(window.location.pathname)) {
return true;
}
return document.body
&& document.body.children.length === 1
&& document.body.firstElementChild instanceof HTMLImageElement;
}
function toAbsoluteUrl(value) {
if (!value) {
return null;
}
const trimmed = String(value).trim().replace(/^['"]|['"]$/g, '');
if (!trimmed || /^(?:data|blob|javascript):/i.test(trimmed)) {
return null;
}
try {
return new URL(trimmed, window.location.href).href;
} catch (_error) {
return null;
}
}
function isImageUrl(url) {
return !!url && IMAGE_EXT_RE.test(url);
}
function getImageUrlFromParams(params) {
for (const key of URL_KEYS) {
const url = toAbsoluteUrl(params.get(key));
if (isImageUrl(url)) {
return url;
}
}
for (const value of params.values()) {
const url = toAbsoluteUrl(value);
if (isImageUrl(url)) {
return url;
}
}
return null;
}
function getImageUrlFromLocation() {
const queryUrl = getImageUrlFromParams(new URLSearchParams(window.location.search));
if (queryUrl) {
return queryUrl;
}
const hash = window.location.hash.replace(/^#&?/, '');
return getImageUrlFromParams(new URLSearchParams(hash));
}
function getRawImageUrlFromImg(img) {
if (!img) {
return null;
}
const candidates = [
img.currentSrc,
img.src,
img.getAttribute('src'),
img.getAttribute('data-src'),
img.getAttribute('data-original'),
img.getAttribute('data-url')
];
for (const candidate of candidates) {
const url = toAbsoluteUrl(candidate);
if (isImageUrl(url)) {
return url;
}
}
return null;
}
function getRawImageUrlFromElement(element) {
const target = element && element.closest('img, canvas, a, [style*="background"], [data-src], [data-url]');
if (!target) {
return null;
}
if (target instanceof HTMLImageElement) {
return getRawImageUrlFromImg(target) || getImageUrlFromLocation();
}
if (target instanceof HTMLAnchorElement) {
const hrefUrl = toAbsoluteUrl(target.href);
if (isImageUrl(hrefUrl)) {
return hrefUrl;
}
}
const dataUrl = toAbsoluteUrl(target.getAttribute('data-src') || target.getAttribute('data-url'));
if (isImageUrl(dataUrl)) {
return dataUrl;
}
const backgroundMatch = (target.getAttribute('style') || '').match(/url\(([^)]+)\)/i);
const backgroundUrl = backgroundMatch ? toAbsoluteUrl(backgroundMatch[1]) : null;
if (isImageUrl(backgroundUrl)) {
return backgroundUrl;
}
return getImageUrlFromLocation();
}
function openRawImage(rawUrl) {
if (typeof GM_openInTab === 'function') {
GM_openInTab(rawUrl, { active: true, insert: true, setParent: true });
return;
}
window.open(rawUrl, '_blank', 'noopener,noreferrer');
}
function enhanceImage(img) {
if (img.dataset.rawImageClickEnabled === 'true') {
return;
}
const rawUrl = getRawImageUrlFromImg(img) || getImageUrlFromLocation();
if (!rawUrl) {
return;
}
img.dataset.rawImageClickEnabled = 'true';
img.style.cursor = 'zoom-in';
img.title = 'Rohbild in neuem Tab öffnen';
img.addEventListener('click', function (event) {
if (isRawImagePage()) {
return;
}
event.preventDefault();
event.stopPropagation();
openRawImage(getRawImageUrlFromImg(img) || rawUrl);
});
}
function enhanceAllImages() {
document.querySelectorAll('img').forEach(enhanceImage);
}
document.addEventListener('click', function (event) {
if (isRawImagePage()) {
return;
}
const rawUrl = getRawImageUrlFromElement(event.target);
if (!rawUrl) {
return;
}
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
openRawImage(rawUrl);
}, true);
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', enhanceAllImages, { once: true });
} else {
enhanceAllImages();
}
const observer = new MutationObserver(enhanceAllImages);
function startObserver() {
if (!document.documentElement) {
return;
}
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', startObserver, { once: true });
} else {
startObserver();
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment