source: Klonkt/src/assets/js/mod/lib.js@ 4b5db37

main
Last change on this file since 4b5db37 was 4b5db37, checked in by Robin <roboburr@…>, 5 weeks ago

Modules herstarten per paginawissel: de editor leeft weer na een terugkeer (shaer-5s1)

Drie klachten, een wortel. De oude inline scripts draaiden bij ELKE render;
een ES-module draait zijn top-level EEN keer per sessie, en de bootstrap
importeert een geladen module nooit opnieuw. Dus:

  • /posts/new na een htmx-terugkeer: geen toolbar, geen serialisatie -- het verborgen veld kreeg de chips nooit terug (shortcodes 'opgegeten')
  • /admin/audio na een terugkeer: de eigen kopieerhandler dood, en de klik viel door naar de GEDELEGEERDE handler van admin-media, die voor mediapaden terecht location.origin voorplakt -- vandaar https://site[[track:uuid]] op het klembord

De afspraak is nu: een module die per render moet draaien exporteert init(),
en de bootstrap roept die aan bij elke wissel waarop de module actief is.
Modules zonder init houden hun oude gedrag. Listeners op document/window
overleven de swap met closures naar dode elementen; makeSweeper in lib.js
veegt bij elke init de vorige lichting weg. Gedelegeerde handlers die
bewust blijven leven (media/videos) krijgen een paginawacht, want data-copy
betekent daar een PAD en elders een shortcode.

Omgezet: post-edit, admin-audio, admin-playlists. Bewaakt: admin-media,
admin-videos. playlist-editor en track-editor waren al swap-bestendig
(globale functie, gedelegeerd met eigen guards).

Co-Authored-By: Claude Opus 5 <noreply@…>

  • Property mode set to 100644
File size: 2.4 KB
Line 
1// Gedeeld gereedschap voor de pagina-modules (shaer-bqr).
2
3/**
4 * De servergegevens van deze pagina.
5 *
6 * Een module is een statisch bestand, dus er kan geen EJS in. Wat het script van
7 * de server nodig heeft -- vertalingen, ids, instellingen -- zet de pagina in
8 * een <script type="application/json"> via partials/page-data.ejs, en dit leest
9 * het terug.
10 *
11 * ELKE KEER OPNIEUW LEZEN en niet eenmalig onthouden: bij een htmx-navigatie
12 * wisselt de inhoud terwijl de module blijft leven, dus een gegevensblok dat je
13 * bij het laden vasthoudt is een pagina later verouderd.
14 *
15 * Nooit een uitzondering: een module die valt over ontbrekende gegevens neemt de
16 * hele pagina mee. Wat er niet is, is een leeg object.
17 */
18export function pageData() {
19 try {
20 var el = document.querySelector('script[type="application/json"][data-page-data]');
21 return el ? (JSON.parse(el.textContent) || {}) : {};
22 } catch (e) {
23 return {};
24 }
25}
26
27/**
28 * Een enkele waarde, met een terugval. Scheelt in elke module hetzelfde
29 * gedoe met ontbrekende sleutels.
30 */
31export function pageValue(key, fallback) {
32 var d = pageData();
33 return (d && Object.prototype.hasOwnProperty.call(d, key)) ? d[key] : fallback;
34}
35
36/**
37 * Listeners op document en window overleven een paginawissel; de pagina zelf
38 * niet. Een module die per navigatie opnieuw start (export init) registreert
39 * zulke listeners hier, en veegt bij elke start de vorige lichting weg --
40 * anders stapelen ze, elk met een closure naar elementen die al weg zijn.
41 *
42 * Listeners op ELEMENTEN hoeven hier niet doorheen: die sterven met hun
43 * element bij de swap. Alleen wat het document overleeft, moet geveegd.
44 */
45export function makeSweeper() {
46 let list = [];
47 return {
48 on(target, ev, fn, opts) { target.addEventListener(ev, fn, opts); list.push([target, ev, fn, opts]); },
49 sweep() { for (const [t, ev, fn, opts] of list) t.removeEventListener(ev, fn, opts); list = []; },
50 };
51}
52
53/**
54 * Een tekst veilig in HTML zetten.
55 *
56 * De modules bouwen op sommige plekken HTML met stringplakwerk. Vroeger ging een
57 * vertaling daar door de escapende EJS-tag heen; nu niet meer. Zonder deze functie
58 * breekt een apostrof in een vertaling het attribuut af waar hij in staat -- het
59 * soort fout dat pas in een andere taal opvalt.
60 */
61export function esc(s) {
62 return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
63 return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
64 });
65}
Note: See TracBrowser for help on using the repository browser.