Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
// Footnotes: finding a reference's note, and the popover that shows it
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
// ---------------------------------------------------------------------------
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
// The whole book is one concatenated DOM, and ids like "fn1" repeat per
|
|
|
|
|
// chapter file: a note is looked up in the chapter its link points into (the
|
|
|
|
|
// link's original href, kept in data-footnote-href by sanitizeEpubHtml), and
|
|
|
|
|
// only exactly the note is shown — not the parent around an id that sits on
|
|
|
|
|
// the note's own <p>/<aside>/<li>, which can be a whole chapter. The same
|
|
|
|
|
// lookup serves the popover here, the notes at the foot of a page
|
|
|
|
|
// (63-pages.js) and the apps' note sheet (diora-android native-ui.js).
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
const _NOTE_INLINE = /^(A|SPAN|SUP|SUB|B|I|EM|STRONG|SMALL|CODE)$/;
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
function noteHrefOf(link) {
|
|
|
|
|
return link.dataset.footnoteHref || ('#' + (link.dataset.footnoteRef || ''));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _noteChapterFor(fromEl, href) {
|
|
|
|
|
const chapter = fromEl.closest('[data-epub-src]');
|
|
|
|
|
const file = href.split('#')[0];
|
|
|
|
|
if (!file || !chapter) return chapter;
|
|
|
|
|
const src = chapter.dataset.epubSrc || '';
|
|
|
|
|
const dir = src.includes('/') ? src.slice(0, src.lastIndexOf('/') + 1) : '';
|
|
|
|
|
const target = resolveEpubPath(dir, file);
|
|
|
|
|
return document.querySelector(`#reader-content > [data-epub-src="${CSS.escape(target)}"]`) || chapter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The element `href` (as written in the book, relative to fromEl's chapter) points at.
|
|
|
|
|
function resolveNoteTarget(fromEl, href) {
|
|
|
|
|
const id = decodeURIComponent(href.slice(href.indexOf('#') + 1));
|
|
|
|
|
const scope = _noteChapterFor(fromEl, href);
|
|
|
|
|
const content = document.getElementById('reader-content');
|
|
|
|
|
let el = id && scope ? scope.querySelector(`[id="${CSS.escape(id)}"]`) : null;
|
|
|
|
|
if (!el && id && content) el = content.querySelector(`[id="${CSS.escape(id)}"]`);
|
|
|
|
|
if (!el && !id) el = scope; // link to a whole chapter file
|
|
|
|
|
return el;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Converters (zeno.org / e-artnow, some Calibre output) park an empty
|
|
|
|
|
// <a id="F537"></a> right *before* the note's paragraph instead of inside it —
|
|
|
|
|
// or at the start of it (then the paragraph is the note, not what follows).
|
|
|
|
|
function _noteAfterEmptyAnchor(target) {
|
|
|
|
|
if ((target.textContent || '').trim() || target.querySelector('img')) return null;
|
|
|
|
|
const own = target.closest('p, li, dd, dt, td, blockquote');
|
|
|
|
|
const ownText = own && !own.hasAttribute('data-epub-src') ? (own.textContent || '').trim() : '';
|
|
|
|
|
if (ownText && !/^[\[(]?\d{1,4}[\])]?\.?$/.test(ownText)) return own;
|
|
|
|
|
if (ownText) {
|
|
|
|
|
// Only the number: the note (a poem, a long quote) runs on in the next
|
|
|
|
|
// paragraphs, up to the next note's anchor.
|
|
|
|
|
const box = document.createElement('div');
|
|
|
|
|
box.appendChild(own.cloneNode(true));
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
let len = 0;
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
for (let next = own.nextElementSibling; next && len < 6000; next = next.nextElementSibling) {
|
|
|
|
|
if (next.matches('h1, h2, h3, h4, h5, h6') || next.querySelector('[id]')) break;
|
|
|
|
|
if (!(next.textContent || '').trim()) continue;
|
|
|
|
|
box.appendChild(next.cloneNode(true));
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
len += next.textContent.length;
|
|
|
|
|
}
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
return box;
|
|
|
|
|
}
|
|
|
|
|
for (let el = target; el && !el.hasAttribute('data-epub-src'); el = el.parentElement) {
|
|
|
|
|
let next = el.nextElementSibling;
|
|
|
|
|
while (next && !(next.textContent || '').trim()) next = next.nextElementSibling;
|
|
|
|
|
if (next) return next.matches('h1, h2, h3, h4, h5, h6') ? null : next;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _noteBox(target) {
|
|
|
|
|
const following = _noteAfterEmptyAnchor(target);
|
|
|
|
|
if (following) return following;
|
|
|
|
|
let box = target.closest(_NOTE_BOX_SELECTOR); // 40-epub.js
|
|
|
|
|
if (box && (box.hasAttribute('data-epub-src') || box.id === 'reader-content')) box = null;
|
|
|
|
|
if (!box) box = _NOTE_INLINE.test(target.tagName) ? (target.closest('p, li, dd, div, td, blockquote') || target) : target;
|
|
|
|
|
// Never a whole chapter or section: fall back to the paragraph around the target.
|
|
|
|
|
if (box.hasAttribute('data-epub-src') || (box.textContent || '').length > 6000) {
|
|
|
|
|
box = target.closest('p, li, dd') || target;
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
}
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
return box;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A copy of the note at `target`, ready to show outside the book.
|
|
|
|
|
function noteContentFor(target, label) {
|
|
|
|
|
const clone = _noteBox(target).cloneNode(true);
|
|
|
|
|
clone.querySelectorAll('[role="doc-backlink"], [epub\\:type~="backlink"]').forEach(e => e.remove());
|
|
|
|
|
// A page of the printed edition that starts inside the note.
|
|
|
|
|
clone.querySelectorAll('.epub-pagenum, [role="doc-pagebreak"], [epub\\:type~="pagebreak"]').forEach(e => e.remove());
|
|
|
|
|
// Links back to the text ("↩", or the note's own number at its start).
|
|
|
|
|
clone.querySelectorAll('a').forEach(a => {
|
|
|
|
|
const t = (a.textContent || '').trim();
|
|
|
|
|
if (/^[↩↑⤴^]+$/.test(t)) a.remove();
|
|
|
|
|
});
|
|
|
|
|
// The note's own number at its very start ("3 Endnote…", "[4] …"): whatever
|
|
|
|
|
// shows the note labels it already.
|
|
|
|
|
const first = Array.prototype.find.call(clone.querySelectorAll('a, sup, span, b, strong'),
|
|
|
|
|
e => (e.textContent || '').trim());
|
|
|
|
|
const firstText = first ? (first.textContent || '').trim() : '';
|
|
|
|
|
const bare = t => t.replace(/[\[\]().\s]/g, '');
|
|
|
|
|
if (first && firstText && (clone.textContent || '').trim().startsWith(firstText) &&
|
|
|
|
|
(bare(firstText) === bare(label || '') || /^[\[(]?(\d{1,4}|[*†‡§]+)[\])]?\.?$/.test(firstText))) {
|
|
|
|
|
first.remove();
|
|
|
|
|
// …and the space that followed it.
|
|
|
|
|
const walker = document.createTreeWalker(clone, NodeFilter.SHOW_TEXT, null, false);
|
|
|
|
|
const t = walker.nextNode();
|
|
|
|
|
if (t) t.nodeValue = t.nodeValue.replace(/^\s+/, '');
|
|
|
|
|
}
|
|
|
|
|
// No duplicate ids in the page (getElementById must keep finding the book's).
|
|
|
|
|
clone.removeAttribute('id');
|
|
|
|
|
clone.querySelectorAll('[id]').forEach(e => e.removeAttribute('id'));
|
|
|
|
|
clone.querySelectorAll('mark.tts-current, mark.reader-search-match').forEach(m => m.replaceWith(...m.childNodes));
|
|
|
|
|
return clone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The note of a reference link, or null.
|
|
|
|
|
function noteForLink(link) {
|
|
|
|
|
const target = resolveNoteTarget(link, noteHrefOf(link));
|
|
|
|
|
return target ? noteContentFor(target, (link.textContent || '').trim()) : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let currentFootnotePopover = null;
|
|
|
|
|
let _footnotePopoverTimer = null;
|
|
|
|
|
|
|
|
|
|
function showFootnotePopover(link) {
|
|
|
|
|
dismissFootnotePopover();
|
|
|
|
|
const note = noteForLink(link);
|
|
|
|
|
if (!note) return;
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
|
|
|
|
|
const popover = document.createElement('div');
|
|
|
|
|
popover.className = 'footnote-popover';
|
|
|
|
|
const _overlay = document.getElementById('reader-overlay');
|
|
|
|
|
['reader-theme-sepia', 'reader-theme-bright'].forEach(cls => {
|
|
|
|
|
if (_overlay?.classList.contains(cls)) popover.classList.add(cls);
|
|
|
|
|
});
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
popover.appendChild(note);
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
|
|
|
|
|
const closeBtn = document.createElement('button');
|
|
|
|
|
closeBtn.className = 'footnote-popover-close';
|
|
|
|
|
closeBtn.textContent = '✕';
|
|
|
|
|
closeBtn.addEventListener('click', dismissFootnotePopover);
|
|
|
|
|
popover.appendChild(closeBtn);
|
|
|
|
|
|
|
|
|
|
const rect = link.getBoundingClientRect();
|
|
|
|
|
popover.style.top = (rect.bottom + 8) + 'px';
|
|
|
|
|
popover.style.left = Math.max(8, rect.left - 8) + 'px';
|
|
|
|
|
|
|
|
|
|
popover.addEventListener('mouseenter', () => clearTimeout(_footnotePopoverTimer));
|
|
|
|
|
popover.addEventListener('mouseleave', () => {
|
|
|
|
|
_footnotePopoverTimer = setTimeout(dismissFootnotePopover, 250);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
document.body.appendChild(popover);
|
|
|
|
|
currentFootnotePopover = popover;
|
|
|
|
|
currentFootnotePopover._refLink = link;
|
|
|
|
|
|
|
|
|
|
const pr = popover.getBoundingClientRect();
|
|
|
|
|
if (pr.right > window.innerWidth - 8) popover.style.left = (window.innerWidth - pr.width - 8) + 'px';
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
if (pr.bottom > window.innerHeight - 8) popover.style.top = Math.max(8, rect.top - pr.height - 8) + 'px';
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.
Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function dismissFootnotePopover() {
|
|
|
|
|
clearTimeout(_footnotePopoverTimer);
|
|
|
|
|
currentFootnotePopover?.remove();
|
|
|
|
|
currentFootnotePopover = null;
|
|
|
|
|
}
|