1document.addEventListener("keydown", (e) => { 2 // Eingabefelder ignorieren 3 const targetTag = e.target.tagName.toLowerCase(); 4 if (targetTag === "input" || targetTag === "textarea") return; 5 6 const key = e.key.toLowerCase(); 7 8 // Suche nach den Links im .blog-prevnext Bereich 9 const nav = document.querySelector(".blog-prevnext"); 10 if (!nav) return; 11 12 const prevLink = nav.querySelector(".nav-links:first-of-type a"); 13 const nextLink = nav.querySelector(".nav-links:last-of-type a"); 14 15 if (key === "j" && prevLink) { 16 window.location.href = prevLink.href; 17 } else if (key === "k" && nextLink) { 18 window.location.href = nextLink.href; 19 } 20}); 21 22function initCopyLinkButtons() { 23 document.querySelectorAll(".note-action--copy").forEach((button) => { 24 const url = button.dataset.copyUrl; 25 if (!url) return; 26 27 const label = button.querySelector(".note-action__label"); 28 const defaultLabel = label ? label.textContent : button.textContent; 29 30 button.addEventListener("click", async () => { 31 try { 32 await navigator.clipboard.writeText(url); 33 button.classList.add("is-copied"); 34 if (label) { 35 label.textContent = "kopiert!"; 36 } 37 setTimeout(() => { 38 button.classList.remove("is-copied"); 39 if (label) { 40 label.textContent = defaultLabel; 41 } 42 }, 2000); 43 } catch { 44 window.prompt("URL kopieren:", url); 45 } 46 }); 47 }); 48} 49 50function initEditButton() { 51 const path = window.location.pathname.replace(/\/+$/, ""); 52 53 let panelId = null; 54 let match; 55 56 if ((match = path.match(/^\/articles\/([^/]+)/))) { 57 panelId = `articles+${decodeURIComponent(match[1])}`; 58 } else if ((match = path.match(/^\/sofortbilder\/([^/]+)/))) { 59 panelId = `sofortbilder+${decodeURIComponent(match[1])}`; 60 } else if ((match = path.match(/^\/checkins\/([^/]+)/))) { 61 panelId = `checkins+${decodeURIComponent(match[1])}`; 62 } else if ((match = path.match(/^\/favoriten\/([^/]+)/))) { 63 panelId = `favoriten+${decodeURIComponent(match[1])}`; 64 } else if ((match = path.match(/^\/bookmarks\/([^/]+)/))) { 65 panelId = `bookmarks+${decodeURIComponent(match[1])}`; 66 } else if ((match = path.match(/^\/lesezeichen\/([^/]+)/))) { 67 panelId = `bookmarks+${decodeURIComponent(match[1])}`; 68 } else if ((match = path.match(/^\/replies\/([^/]+)/))) { 69 panelId = `replies+${decodeURIComponent(match[1])}`; 70 } else if ((match = path.match(/^\/mediamenu\/([^/]+)/))) { 71 panelId = `mediamenu+${decodeURIComponent(match[1])}`; 72 } 73 74 if (!panelId) return; 75 76 fetch("/authcheck") 77 .then((res) => (res.ok ? res.json() : Promise.reject(res))) 78 .then((data) => { 79 if (!data?.loggedIn) return; 80 81 const link = document.createElement("a"); 82 link.href = `/panel/pages/${panelId}`; 83 link.className = "note-action note-action--edit"; 84 link.setAttribute("aria-label", "im panel bearbeiten"); 85 86 const editSpan = document.getElementById("edit-article"); 87 const inBeilageActions = editSpan?.closest(".beilage-actions"); 88 const inCopyNav = editSpan?.closest(".note-actions--secondary"); 89 90 if (inBeilageActions || inCopyNav) { 91 link.innerHTML = '<span class="note-action__label">edit</span>'; 92 } else { 93 link.textContent = "edit"; 94 } 95 96 if (editSpan) { 97 editSpan.appendChild(link); 98 return; 99 } 100 101 const footer = document.querySelector("footer.note-footer"); 102 const copyNav = footer?.querySelector( 103 '.note-actions--secondary[aria-label="kopieren und export"]' 104 ); 105 106 if (copyNav) { 107 const slot = document.createElement("span"); 108 slot.id = "edit-article"; 109 copyNav.appendChild(slot); 110 slot.appendChild(link); 111 return; 112 } 113 114 if (!footer) return; 115 }) 116 .catch(() => { /* still silent if fetch fails */ }); 117} 118 119function bootNoteFooter() { 120 initCopyLinkButtons(); 121 initEditButton(); 122 if (typeof initCopyMarkdownButtons === "function") { 123 initCopyMarkdownButtons(); 124 } 125} 126 127if (document.readyState === "loading") { 128 document.addEventListener("DOMContentLoaded", bootNoteFooter); 129} else { 130 bootNoteFooter(); 131}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.