PageSourceSearch

https://industriemuseum-herrenwyk.de/gcms6/cms_helper260310_pb.js?v=1790694555

js industriemuseum-herrenwyk.de collected 2026-10-04 23:22:01 UTC 51,997 bytes, 1,232 lines download raw bytes

1// Globale Variablen beibehalten
2let GCMS_MTRACK_DATA = [];
3let GCMS_enableHandler = false;
4let GCMS_enableHandler1 = false;
5let GCMS_MTIME = new Date();
6let GCMS_ONLINE = true;
7let GCMS_ANI = false;
8let GCMS_FORM = [];
9
10// Funktion zum Senden von POST-Daten (ersetzt $.post)
11async function GCMS_sendPostData(url, data) {
12    const formData = new URLSearchParams();
13    for (const key in data) {
14        if (Object.prototype.hasOwnProperty.call(data, key)) {
15            if (Array.isArray(data[key]) || (typeof data[key] === 'object' && data[key] !== null && ! (data[key] instanceof File))) {
16                formData.append(key, JSON.stringify(data[key]));
17            } else {
18                formData.append(key, data[key]);
19            }
20        }
21    }
22
23    try {
24        const response = await fetch(url, {
25            method: 'POST',
26            headers: {
27                'Content-Type': 'application/x-www-form-urlencoded',
28            },
29            body: formData
30        });
31        if (!response.ok) {
32            console.error('Network response was not ok:', response.statusText);
33            throw new Error(`HTTP error! status: ${response.status}`);
34        }
35        return response.text(); // Oder response.json(), je nachdem was der Server zurückgibt
36    } catch (error) {
37        console.error('Error sending POST data:', error);
38        throw error; // Fehler weiterleiten
39    }
40}
41
42// Prüfen auf mobile Geräte und Cursor setzen
43if (/ip(hone|od)|ipad/i.test(navigator.userAgent)) {
44    document.body.style.cursor = "pointer";
45}
46
47function GCMS_MTRACK(seid, spid, hash, time, event, typ, zusatz) {
48    var akt = new Date();
49    var diff = akt.getTime() - GCMS_MTIME.getTime();
50    var data = typ + ',' + diff + ',';
51    var send = false;
52    GCMS_MTIME = akt;
53    if (typ == "cl") {
54        data += window.innerWidth + ',' + event.pageX + ',' + event.pageY + ',' + zusatz;
55        send = true;
56    } else if (typ == "mo") {
57        data += event.pageX + ',' + event.pageY + ',' + window.scrollY + ',' + window.scrollX;
58    } else if (typ == "rc") {
59        data += event.pageX + ',' + event.pageY;
60    } else if (typ == "sc") {
61        data += window.scrollY + ',' + window.scrollX;
62    } else if (typ == "re") {
63        data += window.innerWidth + ',' + window.innerHeight;
64    } else if (typ == "ke") {
65        // Event data is not explicitly added here in the original, so keeping it consistent
66    }
67	GCMS_MTRACK_DATA.push(data);
68    if(GCMS_ONLINE){
69        const payload = { data0: seid + "," + spid + "," + hash + "," + time, data1: GCMS_MTRACK_DATA };
70        const jsonString = JSON.stringify(payload);
71        const byteSize = new TextEncoder().encode(jsonString).length;
72        if(byteSize > 60000){
73            // sendbeacon limit 64kb
74            GCMS_sendPostData("/index.php?gstat=3", { data0: seid + "," + spid + "," + hash + "," + time, data1: GCMS_MTRACK_DATA });
75			GCMS_MTRACK_DATA = [];
76        }
77    }
78    return true;
79}
80
81function GCMS_ZIEL(stzid){
82    const data = { data0: stzid, data1: GCMS_SL }; 
83    if (navigator.sendBeacon) {
84        const blob = new Blob([JSON.stringify(data)], { type: "application/json" });
85        navigator.sendBeacon("/index.php?gstat=4", blob);
86    } else {
87        GCMS_sendPostData("/index.php?gstat=4", data);
88    }
89}
90
91function GCMS_tr(seid, spid, hash, time, heatmap) {
92    window.addEventListener("pagehide", function () {
93        if (GCMS_MTRACK_DATA.length > 0) {
94            try {
95                const data = { data0: seid + "," + spid + "," + hash + "," + time, data1: GCMS_MTRACK_DATA };
96                const blob = new Blob([JSON.stringify(data)], { type: "application/json" });
97                if (navigator.sendBeacon) {
98                    GCMS_MTRACK_DATA = [];
99                    navigator.sendBeacon("/index.php?gstat=3", blob);
100                }
101            } catch (e) {
102                //console.error("Fehler beim Senden der Daten:", e);
103            }
104        }
105    });
106
107    if(heatmap) GCMS_MTRACK(seid, spid, hash, time, "", "re");
108
109    // Zielvorhaben
110    if (typeof GCMS_Z_TI !== 'undefined') {
111        GCMS_Z_TI.forEach(function(item, index) {
112            window.setTimeout(function(){
113                GCMS_ZIEL(index);
114            },item*1000);
115        });
116    }
117
118    if (typeof GCMS_Z_ELID !== 'undefined') {
119        GCMS_Z_ELID.forEach(function(item, index) {
120            CustomAppear.init('#' + item, { force_process: true });
121            document.body.addEventListener('appear', function(e) {
122                const target = e.detail.element;
123                if (target.matches('#' + item)) {
124                    if (!GCMS_Z_ELID1[index]) { 
125                        GCMS_Z_ELID1[index] = true;
126                        GCMS_ZIEL(index);
127                    }
128                }
129            });
130        });
131    }
132
133    if (typeof GCMS_Z_ELKLA !== 'undefined') {
134        GCMS_Z_ELKLA.forEach(function(item, index) {
135            let checkkla = item.split(" ");
136            let itemkla = '';
137            checkkla.forEach(function(item1) {
138                item1 = item1.trim();
139                if(item1 !== " ") itemkla += "." + item1;
140            });
141            CustomAppear.init(itemkla, { force_process: true });
142            document.body.addEventListener('appear', function(e) {
143                const target = e.detail.element;
144                if (target.matches(itemkla)) {
145                    if (!GCMS_Z_ELKLA1[index]) { 
146                        GCMS_Z_ELKLA1[index] = true;
147                        GCMS_ZIEL(index);
148                    }
149                }
150            });
151        });
152    }
153
154    if(heatmap){
155        document.body.addEventListener("mousemove", function(event) {
156            if (GCMS_enableHandler) {
157                GCMS_MTRACK(seid, spid, hash, time, event, "mo");
158                GCMS_enableHandler = false;
159            }
160        });
161        document.body.addEventListener("contextmenu", function(event) {
162            GCMS_MTRACK(seid, spid, hash, time, event, "rc");
163        });
164    }
165
166    document.addEventListener('click', function (event) {
167        const target = event.target;
168        // Funktion zur Erzeugung des DOM-Pfads
169        function GCMS_getDomPath(el) {
170            const path = [];
171            while (el && el.nodeType === Node.ELEMENT_NODE) {
172                let selector = el.tagName.toLowerCase();
173                if (el.id) {
174                    selector += `#${el.id}`;
175                }
176                if (el.className && typeof el.className === 'string') {
177                    const classNames = el.className.trim().split(/\s+/).filter(Boolean);
178                    if (classNames.length > 0) {
179                        selector += '.' + classNames.join('.');
180                    }
181                }
182                path.unshift(selector);
183                el = el.parentElement;
184            }
185            return path.join(' ');
186        }
187        let el_id =  target.id || null;
188        let el_class = target.className || null;
189        let el_href = target.tagName === 'A' ? target.href : null;
190        const onclickAttr = target?.getAttribute('onclick');
191        let el_onclickhref = null;
192        if (onclickAttr && onclickAttr.includes('location.href')) {
193            const match = onclickAttr.match(/location\.href\s*=\s*'([^']+)'/);
194            if (match && match[1]) {
195                el_onclickhref = match[1];
196                try {
197                    const absoluteUrl = new URL(el_onclickhref, window.location.href);
198                    el_onclickhref = absoluteUrl.href;
199                } catch (e) {
200                    // console.error("Invalid URL in onclick attribute:", e);
201                }
202            }
203        }
204        // Zielvorhaben
205        if(el_id && typeof GCMS_Z_KLID !== 'undefined') { 
206            GCMS_Z_KLID.forEach(function(item, index) {
207                if(el_id === item) GCMS_ZIEL(index);
208            });
209        }
210        if(el_class && typeof GCMS_Z_KLA !== 'undefined') {
211            let splitkla = el_class.split(" ");
212            GCMS_Z_KLA.forEach(function(item, index) {
213                let checkkla = item.split(" ");
214                let foundkla = false;
215                checkkla.forEach(function(item1) {
216                    if(splitkla.includes(item1)){
217                        foundkla = true;
218                    }
219                });
220                if(foundkla) GCMS_ZIEL(index);
221            });
222        }
223        if(el_href && typeof GCMS_Z_KLURL !== 'undefined') { 
224            GCMS_Z_KLURL.forEach(function(item, index) {
225                if(el_href === item || el_href === item + "/") GCMS_ZIEL(index);
226            });
227        }
228        if(el_onclickhref && typeof GCMS_Z_KLURL !== 'undefined') { 
229            GCMS_Z_KLURL.forEach(function(item, index) {
230                if(el_onclickhref === item || el_onclickhref === item + "/") GCMS_ZIEL(index);
231            });
232        }
233        if(heatmap) GCMS_MTRACK(seid, spid, hash, time, event, "cl", GCMS_getDomPath(target));
234    });
235
236    window.addEventListener('scroll', function() {
237        if (GCMS_enableHandler) {
238            if(heatmap) GCMS_MTRACK(seid, spid, hash, time, "", "sc");
239            GCMS_enableHandler = false;
240            // Zielvorhaben
241            if (typeof GCMS_Z_SCR !== 'undefined') { 
242                let scrollh = document.body.scrollHeight - window.innerHeight;
243                GCMS_Z_SCR.forEach(function(item, index) {
244                    if(!GCMS_Z_SCR1[index]){
245                        let prozw = scrollh * item / 100;
246                        if(window.scrollY >= prozw){
247                            GCMS_Z_SCR1[index] = true;
248                            GCMS_ZIEL(index);
249                        }
250                    }
251                });
252            }
253        }
254    });
255
256    if(heatmap){
257        window.addEventListener('resize', function() {
258            if (GCMS_enableHandler) {
259                GCMS_MTRACK(seid, spid, hash, time, "", "re");
260                GCMS_enableHandler = false;
261            }
262        });
263        document.querySelectorAll("input[type=text],textarea,input[type=password],input[type=number],input[type=date],input[type=month],input[type=week],input[type=time],input[type=datetime-local],input[type=email],input[type=search],input[type=tel],input[type=url]").forEach(function(element) {
264            element.addEventListener("keyup", function(event) {
265                if (GCMS_enableHandler1) {
266                    GCMS_MTRACK(seid, spid, hash, time, event, "ke");
267                    GCMS_enableHandler1 = false;
268                }
269            });
270        });
271    }
272
273    GCMS_timer = window.setInterval(function() {
274        GCMS_enableHandler = true;
275    }, 200);
276    GCMS_timer1 = window.setInterval(function() {
277        GCMS_enableHandler1 = true;
278    }, 500);
279}
280
281function gcms_umfrage_next(spid) {
282    $.post("/index.php?spid="+spid+"&UMFRAGERES=1&notype=1", $("#form_fumfrage").serialize(), function(data) {
283        if (data.substr(0, 5) == "false") $("#gcms_umfrage_load").html(data);
284        else $("#gcms_umfrage_inhalt").html(data);
285    });
286    return false;
287}
288function gcms_umfrage_prev(spid) {
289    $.post("/index.php?spid="+spid+"&UMFRAGERES=1&notype=1&page=" + GCMS_umfrage[$("#akt_page").val()], $("#form_fumfrage").serialize(), function(data) {
290        $("#gcms_umfrage_inhalt").html(data);
291    });
292    return false;
293}
294
295function gcms_nothing() { return; }
296
297let gcmsImageProtectEventListeners = {}; // Object to store event listeners for off/on behavior
298
299function gcms_image_protect() {
300    document.querySelectorAll("img:not(.gcms_image_protect)").forEach(function(th) {
301        if (!th.closest(".GCMS_NOPROTECT")) {
302            th.classList.add("gcms_image_protect");
303            th.style.webkitTouchCallout = "none";
304        }
305    });
306
307    // Remove existing specific event listeners before adding new ones
308    document.querySelectorAll('.gcms_image_protect').forEach(function(img) {
309        if (gcmsImageProtectEventListeners[img]) {
310            for (const eventType in gcmsImageProtectEventListeners[img]) {
311                img.removeEventListener(eventType, gcmsImageProtectEventListeners[img][eventType]);
312            }
313        }
314        gcmsImageProtectEventListeners[img] = {}; // Clear for this image
315    });
316
317    document.querySelectorAll('.gcms_image_protect').forEach(function(img) {
318        const handler = function(event) { event.preventDefault(); };
319        img.addEventListener('dragstart', handler);
320        img.addEventListener('contextmenu', handler);
321        img.addEventListener('mousedown', handler);
322        // For taphold, consider a custom implementation or a library if needed, as it's not a native event
323        // For simplicity, omitting taphold for now as it's jQuery Mobile specific.
324        
325        // Store for later removal
326        gcmsImageProtectEventListeners[img]['dragstart'] = handler;
327        gcmsImageProtectEventListeners[img]['contextmenu'] = handler;
328        gcmsImageProtectEventListeners[img]['mousedown'] = handler;
329    });
330    
331    // Delegated contextmenu and click events for .copy-context
332    // Removed existing listener based on namespace if it exists (simple approach)
333    document.removeEventListener("contextmenu", GCMS_handleCopyContextContextMenu);
334    document.removeEventListener("click", GCMS_handleCopyContextClick);
335
336    // Add new listeners
337    document.addEventListener("contextmenu", GCMS_handleCopyContextContextMenu);
338    document.addEventListener("click", GCMS_handleCopyContextClick);
339}
340
341function GCMS_handleCopyContextContextMenu(event) {
342    const target = event.target;
343    if (target.closest(".copy-context")) {
344        event.preventDefault();
345        event.stopImmediatePropagation();
346        const th = target.closest(".copy-context");
347        const copyright = th.dataset.copyright; // Replaced .data("copyright")
348        document.querySelectorAll(".gcms_copyright-tooltip").forEach(el => el.remove());
349        if (copyright !== undefined && copyright !== "") {
350            // Assume GCMS_BS is a global boolean
351            if(!window.GCMS_BS) event.preventDefault(); 
352            const tooltip = document.createElement('div');
353            tooltip.className = 'gcms_copyright-tooltip gcms_copyright-div';
354            tooltip.style.position = 'absolute';
355            tooltip.style.left = event.pageX + 'px';
356            tooltip.style.top = event.pageY + 'px';
357            tooltip.style.minWidth = '100px';
358            tooltip.style.textAlign = 'center';
359            tooltip.innerHTML = '<div class="gcms_copyright-div" style="padding-bottom:2px;font-weight:bold">Copyright</div>' + copyright;
360            document.body.appendChild(tooltip);
361        }
362    }
363}
364
365function GCMS_handleCopyContextClick(e) {
366    if (!e.target.closest(".gcms_copyright-div")) {
367        document.querySelectorAll(".gcms_copyright-tooltip").forEach(el => el.remove());
368    } else {
369        window.setTimeout(function() {
370            document.querySelectorAll(".gcms_copyright-tooltip").forEach(el => el.remove());
371        }, 5000);
372    }
373}
374
375async function gcms_save_cookie_extern(spid,ds,co) {
376    const data = {
377        dst: "2",
378        kat1: "true",
379        kat2: "true",
380        kat3: "true",
381        ds: ds,
382        co: co,
383        loc: encodeURIComponent(window.location.href)
384    };
385    try {
386        await GCMS_sendPostData("/index.php?gcookiesave=1&spid="+spid, data);
387        document.location.reload();
388    } catch (error) {
389        console.error("Error saving cookie externally:", error);
390    }
391} 
392
393/* Cookie v2 (2026-09-23): Button "Cookie-Einstellungen" im Platzhalter
394   (Variante ohne Inline-Schalter). Der Banner-Code (_CMS_show_cookie_
395   einstellung aus parse/cookie_v2.php) ist nur auf Seiten vorhanden, die
396   den Banner ausliefern - nach einer gespeicherten Entscheidung also
397   nicht mehr. Vorher lief der Klick dort in einen ReferenceError und der
398   Besucher konnte den Inhalt nie freigeben. Fallback: Cookie-Erklaerung
399   (dort liegt der Dialog versteckt bereit), sonst Datenschutzerklaerung. */
400function GCMS_openCookieSettings(el) {
401    var box = el && el.closest ? el.closest("[data-gcms-requires]") : null;
402    if (typeof window._CMS_show_cookie_einstellung === "function"
403        && (document.getElementById("gcms_cookie_manager") || document.getElementById("gcms_einwilligung_dialog"))) {
404        window._CMS_show_cookie_einstellung();
405        return false;
406    }
407    var ziel = box ? (parseInt(box.getAttribute("data-gcms-co"), 10) || parseInt(box.getAttribute("data-gcms-ds"), 10) || 0) : 0;
408    if (ziel > 0) window.location.href = "index.php?seid=" + ziel;
409    return false;
410}
411
412/* Cookie v2: Per-Element-Umschalter ohne Reload (an/aus). */
413function GCMS_gatedTarget(el, gatedId) {
414    if (gatedId && typeof gatedId === "string") {
415        var byId = document.getElementById(gatedId);
416        if (byId) return byId;
417    }
418    if (el && el.closest) {
419        var gated = el.closest("[data-gcms-gated]");
420        if (gated) return gated;
421        var ph = el.closest(".gcms_cookie_placeholder");
422        if (ph) return ph;
423        return el.closest("[id^='gcms_gated_']");
424    }
425    return null;
426}
427
428function GCMS_saveGatedPlaceholderHtml(target) {
429    if (!target || target.getAttribute("data-gcms-placeholder-html")) return;
430    target.setAttribute("data-gcms-placeholder-html", target.innerHTML);
431}
432
433function GCMS_restoreGatedPlaceholder(target) {
434    if (!target) return;
435    var html = target.getAttribute("data-gcms-placeholder-html");
436    if (!html) return;
437    target.innerHTML = html;
438    target.classList.remove("gcms_cookie_gated_active");
439    target.removeAttribute("data-gcms-activated");
440    var cb = target.querySelector(".gcms_extern_toggle input[type='checkbox']");
441    if (cb) cb.checked = false;
442}
443
444function GCMS_consentFromRequired(required, mergeCurrent) {
445    var cats = (required || "").split(",");
446    var kat1 = cats.indexOf("pref")   !== -1;
447    var kat2 = cats.indexOf("stat")   !== -1;
448    var kat3 = cats.indexOf("market") !== -1;
449    if (mergeCurrent && typeof window.GCMS_getConsent === "function") {
450        var cur = window.GCMS_getConsent();
451        if (cur.pref)   kat1 = true;
452        if (cur.stat)   kat2 = true;
453        if (cur.market) kat3 = true;
454    }
455    return { pref: kat1, stat: kat2, market: kat3 };
456}
457
458async function gcms_extern_noreload(el, spid, ds, co, required, gatedId) {
459    var target = GCMS_gatedTarget(el, gatedId);
460    if (!el) return;
461
462    if (!el.checked) {
463        await gcms_extern_revoke_noreload(spid, required, target);
464        return;
465    }
466
467    GCMS_saveGatedPlaceholderHtml(target);
468
469    var vorher = typeof window.GCMS_getConsent === "function"
470        ? window.GCMS_getConsent()
471        : { pref: false, stat: false, market: false };
472    var c = GCMS_consentFromRequired(required, true);
473    var data = {
474        kat1: c.pref ? "true" : "false",
475        kat2: c.stat ? "true" : "false",
476        kat3: c.market ? "true" : "false",
477        ds: ds,
478        co: co,
479        loc: encodeURIComponent(window.location.href)
480    };
481    /* 2026-09-23: Statistik sofort. Wird ueber die Box erstmals Statistik
482       freigegeben, zaehlt der gcookiesave-Handler in Page_pb.php den
483       AKTUELLEN Seitenaufruf direkt (stat=1 + orseid, gleicher Pfad wie
484       "Alle akzeptieren" im Banner) statt erst ab dem naechsten Klick.
485       seid/ink liefert getCookieGatedContent() als data-Attribute. */
486    if (c.stat && !vorher.stat && target && target.getAttribute("data-gcms-seid")) {
487        data.stat   = "1";
488        data.orseid = target.getAttribute("data-gcms-seid");
489        data.ink    = target.getAttribute("data-gcms-ink") || "0";
490        data.refer  = document.referrer || "";
491        data.st_res = screen.width + "x" + screen.height;
492        data.st_col = screen.colorDepth;
493        data.st_je  = navigator.javaEnabled && navigator.javaEnabled() ? 1 : 0;
494    }
495    try {
496        await GCMS_sendPostData("/index.php?gcookiesave=1&spid=" + spid, data);
497        document.dispatchEvent(new CustomEvent("gcms:consent:granted", {
498            detail: { pref: c.pref, stat: c.stat, market: c.market, source: "extern" }
499        }));
500    } catch (error) {
501        console.error("Error granting external content:", error);
502        document.location.reload();
503    }
504}
505
506async function gcms_extern_revoke_noreload(spid, required, target) {
507    var cur = typeof window.GCMS_getConsent === "function"
508        ? window.GCMS_getConsent()
509        : { pref: false, stat: false, market: false };
510    var cats = (required || "").split(",");
511    var kat1 = cur.pref;
512    var kat2 = cur.stat;
513    var kat3 = cur.market;
514    if (cats.indexOf("pref") !== -1)   kat1 = false;
515    if (cats.indexOf("stat") !== -1)   kat2 = false;
516    if (cats.indexOf("market") !== -1) kat3 = false;
517
518    var data = {
519        kat1: kat1 ? "true" : "false",
520        kat2: kat2 ? "true" : "false",
521        kat3: kat3 ? "true" : "false",
522        loc: encodeURIComponent(window.location.href)
523    };
524    /* Server liefert das Video schon ohne Platzhalter-HTML (nur gcms_video_out).
525       Dann erst speichern, danach neu laden. Vorher wurde nur neu geladen,
526       der Cookie blieb an und der Schalter sprang wieder auf ja. */
527    var restore = target && target.getAttribute("data-gcms-placeholder-html");
528    try {
529        await GCMS_sendPostData("/index.php?gcookiesave=1&spid=" + spid, data);
530        if (!restore) {
531            document.location.reload();
532            return;
533        }
534        var iframes = target.querySelectorAll("iframe[src]");
535        iframes.forEach(function (f) {
536            f.removeAttribute("src");
537        });
538        GCMS_restoreGatedPlaceholder(target);
539        document.dispatchEvent(new CustomEvent("gcms:consent:granted", {
540            detail: { pref: kat1, stat: kat2, market: kat3, source: "revoke" }
541        }));
542    } catch (error) {
543        console.error("Error revoking external content:", error);
544        document.location.reload();
545    }
546}
547
548async function gcms_unset_cookie_extern(spid,ds,co) {
549    const data = {
550        unset: "1",
551        ds: ds,
552        co: co,
553        loc: encodeURIComponent(window.location.href)
554    };
555    try {
556        await GCMS_sendPostData("/index.php?gcookiesave=1&spid="+spid, data);
557        document.location.reload();
558    } catch (error) {
559        console.error("Error unsetting cookie externally:", error);
560    }
561}  
562
563async function GCMS_checkformuh(formid,fo2id) {
564	if(formid && fo2id) {
565		var formuh = localStorage.getItem("formuh");
566		var uh = false;
567		if(formuh) {
568			var now = Date.now();
569			var uhsplit = formuh.split("|");
570			// 20 Minuten
571			if(now - uhsplit[0] > 20 * 60 * 1000){
572				localStorage.removeItem("formuh");
573			}else uh = uhsplit[1];
574		}
575		if(!uh) {
576            const feUhtmpElement = document.getElementById("fe_uhtmp"+formid);
577            if (feUhtmpElement) {
578                uh = feUhtmpElement.value; // Replaced .val()
579			    await GCMS_sendPostData("/index.php", { GFORMID: fo2id, GFORMUH: uh ,GFAKT: "open"}); // Replaced $.post
580            } else {
581                console.warn(`Element #fe_uhtmp${formid} not found.`);
582            }
583		}
584        const feUhElement = document.getElementById("fe_uh"+formid);
585        if (feUhElement) {
586            feUhElement.value = uh; // Replaced .val()
587        } else {
588            console.warn(`Element #fe_uh${formid} not found.`);
589        }
590		localStorage.setItem("formuh",Date.now()+"|"+uh);
591	}else if(formid){
592        const feUhElement = document.getElementById("fe_uh"+formid);
593        const feUhtmpElement = document.getElementById("fe_uhtmp"+formid);
594        if (feUhElement && feUhtmpElement) {
595            feUhElement.value = feUhtmpElement.value;
596        } else {
597            console.warn(`One or both elements (#fe_uh${formid}, #fe_uhtmp${formid}) not found.`);
598        }
599	}
600}
601
602async function GCMS_checkformfill(fo2id) {
603	if(fo2id) {
604		var formuh = localStorage.getItem("formuh");
605		var uh = false;
606		if(formuh) {
607			var uhsplit = formuh.split("|");
608			uh = uhsplit[1];
609			if(GCMS_FORM.indexOf(fo2id)==-1){
610				GCMS_FORM.push(fo2id); 
611				await GCMS_sendPostData("/index.php", { GFORMID: fo2id, GFORMUH: uh ,GFAKT: "fill"}); // Replaced $.post
612			}
613		}
614	}
615}
616
617async function GCMS_errorform(fo2id) {
618	if(fo2id) {
619		var formuh = localStorage.getItem("formuh");
620		var uh = false;
621		if(formuh) {
622			var uhsplit = formuh.split("|");
623			uh = uhsplit[1];
624			if(GCMS_FORM.indexOf(fo2id)==-1){
625				GCMS_FORM.push(fo2id); 
626				await GCMS_sendPostData("/index.php", { GFORMID: fo2id, GFORMUH: uh ,GFAKT: "error"}); // Replaced $.post
627			}
628		}
629	}
630}
631
632function GCMS_formback(formid){
633    const feFormbackElement = document.getElementById("fe_formback"+formid);
634    if (feFormbackElement) {
635        feFormbackElement.value = 0; // Replaced .val()
636    } else {
637        console.warn(`Element #fe_formback${formid} not found.`);
638    }
639	const form = document.getElementById("form_"+formid);
640    if (form) {
641        const tmpForm = document.createElement('form');
642        tmpForm.id = "gcms_tmp_form";
643        tmpForm.method = "post";
644        tmpForm.action = form.action; // Replaced .attr("action")
645        tmpForm.style.display = "none";
646        tmpForm.innerHTML = form.innerHTML; // Replaced .html()
647        document.body.appendChild(tmpForm); // Replaced $("body").append()
648        tmpForm.submit(); // Replaced .submit()
649    } else {
650        console.warn(`Form #form_${formid} not found.`);
651    }
652}
653
654function GCMS_form_reset(fo2id) {
655	var regex = new RegExp("([?;&])reload[^&;]*[;&]?");
656    var query = window.location.href.split("#")[0].replace(regex, "$1").replace(/&$/, "");
657    window.location.href =
658        (window.location.href.indexOf("?") < 0 ? "?" : query + (query.slice(-1) != "?" ? "&" : ""))
659        + "reload=" + new Date().getTime() + "#fo"+fo2id;
660}
661
662// GSAP Animation Definitions (from/to states for each animation type)
663const GSAP_ANIMATIONS = {
664    fadeIn:       { from: { opacity: 0 },                                  to: { opacity: 1 } },
665    fadeInUp:     { from: { opacity: 0, y: 50 },                           to: { opacity: 1, y: 0 } },
666    fadeInDown:   { from: { opacity: 0, y: -50 },                          to: { opacity: 1, y: 0 } },
667    fadeInLeft:   { from: { opacity: 0, x: -60 },                          to: { opacity: 1, x: 0 } },
668    fadeInRight:  { from: { opacity: 0, x: 60 },                           to: { opacity: 1, x: 0 } },
669    zoomIn:       { from: { opacity: 0, scale: 0.7 },                      to: { opacity: 1, scale: 1 } },
670    zoomInUp:     { from: { opacity: 0, scale: 0.7, y: 50 },               to: { opacity: 1, scale: 1, y: 0 } },
671    zoomInDown:   { from: { opacity: 0, scale: 0.7, y: -50 },              to: { opacity: 1, scale: 1, y: 0 } },
672    slideInUp:    { from: { opacity: 0, y: 100 },                          to: { opacity: 1, y: 0 } },
673    slideInDown:  { from: { opacity: 0, y: -100 },                         to: { opacity: 1, y: 0 } },
674    slideInLeft:  { from: { opacity: 0, x: -100 },                         to: { opacity: 1, x: 0 } },
675    slideInRight: { from: { opacity: 0, x: 100 },                          to: { opacity: 1, x: 0 } },
676    bounceIn:     { from: { opacity: 0, scale: 0.3 },                      to: { opacity: 1, scale: 1 } },
677    elsticIn:     { from: { opacity: 0, scale: 0.5 },                      to: { opacity: 1, scale: 1 } },
678    elsticInUp:   { from: { opacity: 0, scale: 0.5, y: 60 },               to: { opacity: 1, scale: 1, y: 0 } },
679    blurIn:       { from: { opacity: 0, filter: 'blur(20px)' },            to: { opacity: 1, filter: 'blur(0px)' } },
680    blurInUp:     { from: { opacity: 0, filter: 'blur(20px)', y: 40 },     to: { opacity: 1, filter: 'blur(0px)', y: 0 } },
681    flipInX:      { from: { opacity: 0, rotationX: 90, transformPerspective: 600 }, to: { opacity: 1, rotationX: 0 } },
682};
683
684function GCMS_easeFromStr(ease) {
685    switch(ease) {
686        case "none":      return "none";
687		case "easeOut":   return "power2.out";
688        case "easeInOut": return "power2.inOut";
689        case "backOut":   return "back.out(1.7)";
690        case "elastic":   return "elastic.out(1, 0.3)";
691        case "bounceOut": return "bounce.out";
692        default:          return "power2.out";
693    }
694}
695
696function GCMS_initGSAPAnimations() {
697    if (typeof gsap === 'undefined' || typeof ScrollTrigger === 'undefined') return;
698    gsap.registerPlugin(ScrollTrigger);
699
700    var prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
701
702    document.querySelectorAll('.GCMS_ANIMATE').forEach(function(el) {
703        var animData = el.dataset.animation;
704        if (!animData) return;
705
706        var parts = animData.split(',');
707        if (!parseInt(parts[0])) return;
708
709        var type        = parts[1] || 'fadeIn';
710        var duration    = parseFloat(parts[2]) || 1.0;
711        var delay       = parseFloat(parts[3]) || 0;
712        var easing      = prefersReducedMotion ? 'none' : GCMS_easeFromStr(parts[4] || 'easeOut');
713        var scrollStart = parseInt(parts[5]) || 80;
714        var textEnabled = parseInt(parts[6]) || 0;
715        var textType    = parts[7] || 'fadeInUp';
716        var textEach    = parseFloat(parts[8]) || 0.15;
717        var textDur     = parseFloat(parts[9]) || 0.6;
718
719        if (prefersReducedMotion) { duration = 0.01; textDur = 0.01; }
720
721        var animDef = GSAP_ANIMATIONS[type];
722        if (!animDef) return;
723
724        var textChildren = textEnabled ? Array.from(el.querySelectorAll('h1,h2,h3,h4,h5,h6,p,li')) : [];
725        var textDef = (textEnabled && textChildren.length > 0) ? (GSAP_ANIMATIONS[textType] || GSAP_ANIMATIONS['fadeInUp']) : null;
726
727        // Set initial hidden state immediately
728        gsap.set(el, animDef.from);
729        if (textDef) gsap.set(textChildren, textDef.from);
730
731        ScrollTrigger.create({
732            trigger: el,
733            start: 'top ' + scrollStart + '%',
734            once: true,
735            onEnter: function() {
736                var tl = gsap.timeline();
737                tl.fromTo(el, animDef.from, Object.assign({}, animDef.to, { duration: duration, delay: delay, ease: easing }));
738                if (textDef) {
739                    tl.fromTo(
740                        textChildren,
741                        textDef.from,
742                        Object.assign({}, textDef.to, { duration: textDur, ease: easing, stagger: { each: textEach } }),
743                        '>-0.2'
744                    );
745                }
746            }
747        });
748    });
749}
750
751function GCMS_computeHoverCSS(type, intensity) {
752	intensity = intensity || 1.0;
753	let result = {};
754	
755	switch(type) {
756		case 'lift':
757			result.transform = `translateY(${-8 * intensity}px)`;
758			result.boxShadow = `0 ${Math.round(20 * intensity)}px ${Math.round(40 * intensity)}px rgba(0,0,0,${0.1 + 0.05 * intensity})`;
759			break;
760		case 'scale':
761			result.transform = `scale(${1 + 0.06 * intensity})`;
762			break;
763		case 'glow':
764			result.filter = `brightness(${1 + 0.08 * intensity})`;
765			result.boxShadow = `0 0 ${Math.round(20 * intensity)}px rgba(0,143,213,${0.2 + 0.1 * intensity})`;
766			break;
767		case 'shadow':
768			result.transform = `translateY(${-2 * intensity}px)`;
769			result.boxShadow = `0 ${Math.round(8 * intensity)}px ${Math.round(20 * intensity)}px rgba(0,0,0,${0.08 + 0.04 * intensity})`;
770			break;
771		case 'brighten':
772			result.filter = `brightness(${1 + 0.12 * intensity}) saturate(${1 + 0.2 * intensity})`;
773			break;
774		case 'darken':
775			result.filter = `brightness(${1 - 0.18 * intensity}) contrast(${1 + 0.05 * intensity})`;
776			break;
777		case 'dropShadow':
778			result.filter = `drop-shadow(0 ${Math.round(8 * intensity)}px ${Math.round(20 * intensity)}px rgba(0,0,0,${0.18 + 0.08 * intensity}))`;
779			break;
780		case 'shrink':
781			result.transform = `scale(${1 - 0.05 * intensity})`;
782			break;
783		case 'slideUp':
784			result.transform = `translateY(${-6 * intensity}px)`;
785			break;
786		case 'grayscale':
787			result.filter = `grayscale(${Math.min(1, 0.6 + 0.4 * intensity)}) brightness(${1 + 0.05 * intensity})`;
788			break;
789		case 'float':
790			result.transform = `translateY(${-14 * intensity}px)`;
791			break;
792		case 'squeeze':
793			result.transform = `scaleX(${1 - 0.04 * intensity}) scaleY(${1 + 0.04 * intensity})`;
794			break;
795		case 'pushDown':
796			result.transform = `translateY(${5 * intensity}px) scale(${1 - 0.01 * intensity})`;
797			break;
798		case 'contrast':
799			result.filter = `contrast(${1 + 0.2 * intensity}) brightness(${1 + 0.02 * intensity})`;
800			break;
801			
802	}
803	return result;
804}
805
806// Vanilla JS Ersatz für jQuery.appear
807const CustomAppear = (function() {
808    const selectors = [];
809    const priorAppeared = []; // Array of arrays, one for each selector
810    let checkBinded = false;
811    let checkLock = false; // Prevents process() from running concurrently or being scheduled too often
812    const defaults = {
813        interval: 250,
814        force_process: false
815    };
816    let globalOptions = { ...defaults }; // Stores global options like interval
817
818    function isAppeared(element) {
819        // Check if element is truly visible (not display:none, visibility:hidden, or detached from DOM)
820        if (!element.offsetParent || element.style.display === 'none' || element.style.visibility === 'hidden') {
821            return false;
822        }
823
824        const rect = element.getBoundingClientRect();
825        const windowHeight = window.innerHeight || document.documentElement.clientHeight;
826        const windowWidth = window.innerWidth || document.documentElement.clientWidth;
827
828        const topOffset = parseFloat(element.dataset.appearTopOffset || 0);
829        const leftOffset = parseFloat(element.dataset.appearLeftOffset || 0);
830
831        // Check vertical visibility
832        const verticallyVisible = (rect.bottom >= 0) && (rect.top - topOffset <= windowHeight);
833        
834        // Check horizontal visibility (added for full jQuery.appear parity)
835        const horizontallyVisible = (rect.right >= 0) && (rect.left - leftOffset <= windowWidth);
836
837        return verticallyVisible && horizontallyVisible;
838    }
839
840    function process() {
841        if (checkLock) {
842            // A process is already running or scheduled, so skip this call
843            return;
844        }
845        checkLock = true; // Set lock to prevent new processes from starting immediately
846
847        setTimeout(() => {
848            for (let i = 0; i < selectors.length; i++) {
849                const currentSelector = selectors[i];
850                const elements = Array.from(document.querySelectorAll(currentSelector));
851                const appearedElements = elements.filter(isAppeared);
852
853                const prevAppeared = priorAppeared[i] || [];
854
855                // Dispatch 'appear' for newly visible elements
856                appearedElements.forEach(el => {
857                    if (!prevAppeared.includes(el)) {
858                        el.dispatchEvent(new CustomEvent('appear', { detail: { element: el }, bubbles: true }));
859                    }
860                });
861
862                // Dispatch 'disappear' for elements that are no longer visible or no longer exist
863                prevAppeared.forEach(el => {
864                    if (!elements.includes(el) || !appearedElements.includes(el)) {
865                        el.dispatchEvent(new CustomEvent('disappear', { detail: { element: el }, bubbles: true }));
866                    }
867                });
868                
869                priorAppeared[i] = appearedElements; // Update for next cycle
870            }
871            checkLock = false; // Release lock after all processing is done
872        }, globalOptions.interval); // Use the global interval for the processing delay
873    }
874
875    function addSelector(selector) {
876        // Only add if not already present
877        if (!selectors.includes(selector)) {
878            selectors.push(selector);
879            priorAppeared.push([]); // Initialize tracking array for this selector
880        }
881    }
882
883    function setupEventListeners() {
884        if (!checkBinded) {
885            window.addEventListener('scroll', process);
886            window.addEventListener('resize', process);
887            checkBinded = true;
888        }
889    }
890
891    return {
892        // Public method to register elements for appearance checks
893        init: function(selector, options = {}) {
894            // Merge options, but interval/force_process will act globally if multiple init calls have different values.
895            // This behavior mimics jQuery.appear which used a single interval for all elements.
896            globalOptions = { ...defaults, ...options }; 
897
898            setupEventListeners();
899            addSelector(selector);
900
901            // Force a process immediately if requested, but only if not already locked
902            if (globalOptions.force_process && !checkLock) {
903                process();
904            }
905        },
906        // Public method to force an appearance check
907        forceAppear: function() {
908            if (checkBinded) {
909                process();
910                return true;
911            }
912            return false;
913        }
914    };
915})();
916
917document.addEventListener('DOMContentLoaded', function() { 
918
919    if(window.GCMS_BS) { // Assuming GCMS_BS is a global boolean
920        gcms_image_protect();
921		window.setTimeout(function() {
922            gcms_image_protect();
923        },500);
924        window.addEventListener("resize", function() {
925            gcms_image_protect();
926        });
927        // $(document).on("ajaxComplete") is tricky in vanilla JS as there's no native global ajaxComplete event.
928        // You'd need to hook into your own fetch/XHR calls. For now, this part is omitted or needs manual integration.
929        // Placeholder: If you have custom AJAX, call gcms_image_protect() in its success/complete callback.
930        const observer = new MutationObserver(() => gcms_image_protect());
931        observer.observe(document.body, { childList: true, subtree: true });
932
933        document.addEventListener("mouseup", function() {
934            window.setTimeout(function() {
935                gcms_image_protect();
936            },200);
937            window.setTimeout(function() {
938                gcms_image_protect();
939            },1100);
940        });
941     } else {
942        // Redundant with gcms_image_protect logic, but kept for consistency if GCMS_BS is false
943        // These listeners are already managed by gcms_image_protect,
944        // which removes and re-adds them. Keeping this block here for
945        // explicit intent, though the effect is the same as the function call.
946        document.removeEventListener("contextmenu", GCMS_handleCopyContextContextMenu); // Ensure cleanup
947        document.removeEventListener("click", GCMS_handleCopyContextClick); // Ensure cleanup
948
949        document.addEventListener("contextmenu", GCMS_handleCopyContextContextMenu);
950        document.addEventListener("click", GCMS_handleCopyContextClick);
951    }
952
953    // alle cookie switch back auf checked bei reload
954    document.querySelectorAll(".gcms_extern_toggle1 .gcms_extern_switch input[type='checkbox']").forEach(function(checkbox) {
955        checkbox.checked = true; // Replaced .prop("checked",true)
956    });
957    // alle cookie switch auf nicht checked bei reload
958    document.querySelectorAll(".gcms_extern_toggle .gcms_extern_switch input[type='checkbox']").forEach(function(checkbox) {
959        checkbox.checked = false; // Replaced .prop("checked",false)
960    });
961
962    // Event delegation für GCMS_HOVER (auch nachträglich hinzugefügte Elemente)
963    document.addEventListener('mouseenter', function(e) {
964        if (e.target instanceof Element && e.target.matches('.GCMS_HOVER')) {
965            var hover_data = e.target.dataset.hover.split(",");
966            var css = GCMS_computeHoverCSS(hover_data[1], hover_data[2]);
967            Object.assign(e.target.style, css);
968        }
969    }, true);
970    document.addEventListener('mouseleave', function(e) {
971        if (e.target instanceof Element && e.target.matches('.GCMS_HOVER')) {
972            e.target.style.transform = "";
973            e.target.style.filter = "";
974        }
975    }, true);
976
977    // Lottie animations
978    CustomAppear.init('.gcms_lottie', { force_process: true });
979    document.body.addEventListener('appear', function(e) {
980        const element = e.detail.element;
981        if (element.matches('.gcms_lottie')) {
982            var para = "";
983            var dataplay = "";
984            if(element.dataset.play) dataplay = element.dataset.play; // Replaced .data("play")
985            if(dataplay=="autoplay") para += " autoplay";
986            else if(dataplay=="hover") para += " hover";
987            else if(dataplay=="view") para += ' class="gcms_lootieview"';
988            if(element.dataset.loop) para += " loop"; // Replaced .data("loop")
989            if(element.dataset.controls) para += " controls"; // Replaced .data("controls")
990            if(element.dataset.mode) para += ' mode="'+element.dataset.mode+'"'; // Replaced .data("mode")
991            if(element.dataset.direction) para += ' direction="'+element.dataset.direction+'"'; // Replaced .data("direction")
992            if(element.dataset.speed) para += ' speed="'+element.dataset.speed+'"'; // Replaced .data("speed")
993            para += ' src="'+element.dataset.src+'"'; // Replaced .data("src")
994            element.insertAdjacentHTML('afterend', '<lottie-player background="transparent"'+para+'></lottie-player>'); // Replaced .after()
995            element.parentNode.removeChild(element); // Replaced .remove()
996        }
997    });
998
999    CustomAppear.init('.gcms_lootieview', { force_process: true });
1000    document.body.addEventListener('appear', function(e) {
1001        const element = e.detail.element;
1002        if (element.matches('.gcms_lootieview')) {
1003            if (element.play) element.play(); // Check if play method exists
1004        }
1005    });
1006    document.body.addEventListener('disappear', function(e) {
1007        const element = e.detail.element;
1008        if (element.matches('.gcms_lootieview')) {
1009            if (element.pause) element.pause(); // Check if pause method exists
1010        }
1011    });
1012});
1013
1014// Original online/offline event listeners (already vanilla JS)
1015if (window.addEventListener) {
1016    window.addEventListener("offline", function() {
1017        GCMS_ONLINE = false;
1018    }, false);
1019    window.addEventListener("online", function() {
1020        GCMS_ONLINE = true;
1021    }, false);
1022} else if (window.attachEvent) { // For older IE versions
1023    window.attachEvent("offline", function() {
1024        GCMS_ONLINE = false;
1025    });
1026    window.attachEvent("online", function() {
1027        GCMS_ONLINE = true;
1028    });
1029}
1030
1031/* =============================================================================
1032 * GCMS Cookie v2 – No-Reload-Aktivierung externer Inhalte
1033 * -----------------------------------------------------------------------------
1034 * Lauscht auf das DOM-Event `gcms:consent:granted`, das das v2-Banner nach
1035 * erfolgreicher Speicherung dispatcht:
1036 *     document.dispatchEvent(new CustomEvent('gcms:consent:granted', {
1037 *         detail: { pref: true|false, stat: ..., market: ..., source: 'banner' }
1038 *     }));
1039 *
1040 * Aktiviert anschließend alle Inhalte, die für die jeweilige Kategorie gegated
1041 * sind. Drei einfache, kombinierbare Patterns werden unterstützt:
1042 *
1043 *   1) <iframe data-gcms-src="https://..." data-gcms-requires="pref"></iframe>
1044 *      → bei Consent wird `src` gesetzt (lazy iframe)
1045 *
1046 *   2) <link rel="stylesheet" data-gcms-href="https://..." data-gcms-requires="pref">
1047 *      → bei Consent wird `href` gesetzt (z. B. Google Fonts)
1048 *
1049 *   3) <div class="gcms_cookie_placeholder" data-gcms-requires="pref">
1050 *          ...Platzhalter-Markup...
1051 *          <template data-gcms-requires="pref" data-gcms-target="#id">
1052 *              ...echtes HTML mit iframe/script/...
1053 *          </template>
1054 *      </div>
1055 *      → bei Consent wird der Inhalt des <template> in #id eingefügt.
1056 *
1057 * Ist beim Seitenaufruf bereits Consent vorhanden, wird das Event beim Laden
1058 * der Seite automatisch einmal nachgefeuert (Replay), damit die Aktivierung
1059 * idempotent funktioniert.
1060 * ============================================================================= */
1061(function () {
1062    function GCMS_currentConsent() {
1063        var raw = '';
1064        var ca = document.cookie.split(';');
1065        for (var i = 0; i < ca.length; i++) {
1066            var c = ca[i].trim();
1067            if (c.indexOf('cms_cookie=') === 0) { raw = decodeURIComponent(c.substring('cms_cookie='.length)); break; }
1068        }
1069        if (!raw || raw === '1') return { pref: false, stat: false, market: false };
1070        try {
1071            var j = JSON.parse(raw);
1072            return { pref: !!j.pref, stat: !!j.stat, market: !!j.market };
1073        } catch (e) { return { pref: false, stat: false, market: false }; }
1074    }
1075
1076    function GCMS_categoriesGranted(detail) {
1077        var d = detail || GCMS_currentConsent();
1078        var granted = [];
1079        if (d.pref)   granted.push('pref');
1080        if (d.stat)   granted.push('stat');
1081        if (d.market) granted.push('market');
1082        granted.push('req'); // notwendig: immer
1083        return granted;
1084    }
1085
1086    /** Eine Kategorie oder kommagetrennt (z. B. stat,market = beide nötig). */
1087    function GCMS_requiresMet(req, granted) {
1088        if (!req) return false;
1089        var parts = req.split(',');
1090        if (parts.length > 1) {
1091            for (var i = 0; i < parts.length; i++) {
1092                var r = parts[i].trim();
1093                if (r && granted.indexOf(r) === -1) return false;
1094            }
1095            return true;
1096        }
1097        return granted.indexOf(req) !== -1;
1098    }
1099
1100    function GCMS_activateGated(granted) {
1101        // 1) Lazy iframes (data-gcms-src)
1102        var iframes = document.querySelectorAll('iframe[data-gcms-src][data-gcms-requires]');
1103        iframes.forEach(function (el) {
1104            var req = el.getAttribute('data-gcms-requires');
1105            if (!GCMS_requiresMet(req, granted)) return;
1106            if (el.getAttribute('src')) return; // schon aktiv
1107            el.setAttribute('src', el.getAttribute('data-gcms-src'));
1108            el.removeAttribute('data-gcms-src');
1109        });
1110
1111        // 2) Lazy stylesheets (data-gcms-href)
1112        var links = document.querySelectorAll('link[data-gcms-href][data-gcms-requires]');
1113        links.forEach(function (el) {
1114            var req = el.getAttribute('data-gcms-requires');
1115            if (!GCMS_requiresMet(req, granted)) return;
1116            if (el.getAttribute('href')) return;
1117            el.setAttribute('href', el.getAttribute('data-gcms-href'));
1118            el.removeAttribute('data-gcms-href');
1119        });
1120
1121        // 3) Lazy scripts (data-gcms-src auf <script>)
1122        var scripts = document.querySelectorAll('script[type="text/plain"][data-gcms-src][data-gcms-requires]');
1123        scripts.forEach(function (el) {
1124            var req = el.getAttribute('data-gcms-requires');
1125            if (!GCMS_requiresMet(req, granted)) return;
1126            var s = document.createElement('script');
1127            s.src = el.getAttribute('data-gcms-src');
1128            if (el.async) s.async = true;
1129            if (el.defer) s.defer = true;
1130            el.parentNode.insertBefore(s, el.nextSibling);
1131            el.parentNode.removeChild(el);
1132        });
1133
1134        // 4) Placeholder + <template>. innerHTML statt cloneNode, danach
1135        //    Skripte neu einhaengen: aus <template> geklonte <script> laufen
1136        //    sonst nicht (Karten, Social-Embeds blieben leer).
1137        //    data-gcms-activated: das Banner aktiviert dieselbe Box schon
1138        //    inline, dieser Lauf darf sie nicht ein zweites Mal leeren.
1139        var templates = document.querySelectorAll('template[data-gcms-requires]');
1140        templates.forEach(function (tmpl) {
1141            var req = tmpl.getAttribute('data-gcms-requires');
1142            if (!GCMS_requiresMet(req, granted)) return;
1143            var sel = tmpl.getAttribute('data-gcms-target');
1144            var target = sel ? document.querySelector(sel) : tmpl.parentNode;
1145            if (!target || target.getAttribute('data-gcms-activated') === '1') return;
1146            var html = tmpl.innerHTML;
1147            if (!html || !html.replace(/\s/g, '')) return;
1148            GCMS_saveGatedPlaceholderHtml(target);
1149            target.setAttribute('data-gcms-activated', '1');
1150            target.innerHTML = html;
1151            target.classList.add('gcms_cookie_gated_active');
1152            target.querySelectorAll('script').forEach(function (old) {
1153                if (!old.parentNode) return;
1154                var s = document.createElement('script');
1155                for (var a = 0; a < old.attributes.length; a++) {
1156                    s.setAttribute(old.attributes[a].name, old.attributes[a].value);
1157                }
1158                s.text = old.text || old.textContent || '';
1159                old.parentNode.replaceChild(s, old);
1160            });
1161            var backCb = target.querySelector('.gcms_extern_toggle1 input[type="checkbox"]');
1162            if (backCb) backCb.checked = true;
1163            if (typeof window._CMS_unwrap_video_gate === 'function') {
1164                window._CMS_unwrap_video_gate(target);
1165            } else if (target.classList && target.classList.contains('gcms_extern')) {
1166                var video = target.querySelector(':scope > .gcms_video_out');
1167                if (video && target.parentNode) {
1168                    var rest = [];
1169                    for (var c = 0; c < target.children.length; c++) {
1170                        if (target.children[c] !== video) rest.push(target.children[c]);
1171                    }
1172                    rest.forEach(function (el) { video.appendChild(el); });
1173                    target.parentNode.replaceChild(video, target);
1174                }
1175            }
1176        });
1177        /* Alte Video-Box (gcms_save_cookie_extern, ohne template): Schalter
1178         * umlegen und einmal neu laden, wenn Präferenzen + Marketing frei
1179         * sind. Nicht die onclick-Funktion ausführen (die setzt alle
1180         * Kategorien). Flag verhindert eine Reload-Schleife. */
1181        if (granted.indexOf('pref') !== -1 && granted.indexOf('market') !== -1) {
1182            var legacy = document.querySelectorAll('.gcms_extern_toggle input[type="checkbox"]');
1183            var offen = [];
1184            legacy.forEach(function (cb) {
1185                var oc = cb.getAttribute('onchange') || '';
1186                if (oc.indexOf('gcms_save_cookie_extern') === -1 || cb.checked) return;
1187                offen.push(cb);
1188            });
1189            try {
1190                if (!offen.length) {
1191                    sessionStorage.removeItem('gcms_legacy_extern_reload');
1192                } else if (!window.__gcmsLegacyReload) {
1193                    offen.forEach(function (cb) { cb.checked = true; });
1194                    if (sessionStorage.getItem('gcms_legacy_extern_reload') === '1') {
1195                        sessionStorage.removeItem('gcms_legacy_extern_reload');
1196                    } else {
1197                        window.__gcmsLegacyReload = true;
1198                        sessionStorage.setItem('gcms_legacy_extern_reload', '1');
1199                        document.location.reload();
1200                    }
1201                }
1202            } catch (e) { /* still */ }
1203        }
1204    }
1205
1206    function GCMS_onConsentGranted(ev) {
1207        var detail = (ev && ev.detail) ? ev.detail : null;
1208        GCMS_activateGated(GCMS_categoriesGranted(detail));
1209    }
1210
1211    // Event-Listener
1212    document.addEventListener('gcms:consent:granted', GCMS_onConsentGranted);
1213
1214    // Replay bei vorhandenem Consent (idempotent)
1215    function GCMS_consentReplay() {
1216        var c = GCMS_currentConsent();
1217        if (c.pref || c.stat || c.market) {
1218            GCMS_activateGated(GCMS_categoriesGranted(c));
1219        }
1220    }
1221    if (document.readyState === 'loading') {
1222        document.addEventListener('DOMContentLoaded', GCMS_consentReplay);
1223    } else {
1224        GCMS_consentReplay();
1225    }
1226
1227    // Öffentlich verfügbar machen (für manuelle Auslöser, Tests)
1228    window.GCMS_activateGatedContent = function (detail) {
1229        GCMS_activateGated(GCMS_categoriesGranted(detail || null));
1230    };
1231    window.GCMS_getConsent = GCMS_currentConsent;
1232})();

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.