Last active
May 3, 2026 10:42
-
-
Save DickHorner/ff8ab6c321d46bde2cf63647c1bbc43a to your computer and use it in GitHub Desktop.
Userscript: Landesarchiv Berlin: Bild öffnen
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==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