PageSourceSearch

https://www.leinach.de/wp-content/plugins/wp-cosmema-ki-search/assets/js/borlabs-consent.js?ver=1.0.6

js leinach.de collected 2026-09-25 01:19:55 UTC 10,159 bytes, 348 lines download raw bytes

1(function () {
2    "use strict";
3
4    /**
5     * Borlabs owns consent; this module owns presentation and query relay only.
6     * Never grants consent directly — uses ContentBlocker.unblockServices.
7     */
8    var defaults = {
9        serviceId: "neurabot-chatbot",
10        serviceGroupId: "external-media",
11        dialogId: "cosmema-ki-search-consent",
12        /** Hash-Key (nicht Query-Param): Fragment wird nie an den Server gesendet. */
13        hashKey: "cosmema_ki_q",
14        widgetWaitMs: 12000,
15        debug: false,
16    };
17
18    var cfg = {};
19    var i18n = {};
20    var override = window.cosmemaKiSearchBorlabsConfig || {};
21    var pendingQuery = null;
22    var dialogOpen = false;
23    var listenersBound = false;
24
25    for (var key in defaults) {
26        cfg[key] = Object.prototype.hasOwnProperty.call(override, key) ? override[key] : defaults[key];
27    }
28
29    if (override.i18n) {
30        i18n = override.i18n;
31    }
32
33    function log() {
34        if (!cfg.debug || !window.console) {
35            return;
36        }
37        console.log.apply(console, ["[cosmema-ki-search/borlabs]"].concat([].slice.call(arguments)));
38    }
39
40    function borlabsReady() {
41        return !!(window.BorlabsCookie && window.BorlabsCookie.Consents);
42    }
43
44    function hasConsent() {
45        try {
46            return (
47                borlabsReady() &&
48                window.BorlabsCookie.Consents.hasConsent(cfg.serviceId, cfg.serviceGroupId) === true
49            );
50        } catch (error) {
51            return false;
52        }
53    }
54
55    function widgetReady() {
56        return !!(
57            window.neurabot &&
58            typeof window.neurabot.openWindowAndTrySendMessage === "function"
59        );
60    }
61
62    function sendQuery(query) {
63        if (typeof window.neurabot.openWindowAndTrySendMessage === "function") {
64            window.neurabot.openWindowAndTrySendMessage(query);
65            return;
66        }
67        if (typeof window.neurabot.openWindowAndSendMessage === "function") {
68            window.neurabot.openWindowAndSendMessage(query);
69            return;
70        }
71        throw new Error("neurabot send methods are not available");
72    }
73
74    function writePendingHash(query) {
75        var base = window.location.pathname + window.location.search;
76        var next = query
77            ? base + "#" + cfg.hashKey + "=" + encodeURIComponent(query)
78            : base;
79        window.history.replaceState(null, "", next);
80    }
81
82    function readPendingHash() {
83        var hash = window.location.hash.replace(/^#/, "");
84        if (!hash) {
85            return null;
86        }
87
88        var value = new URLSearchParams(hash).get(cfg.hashKey);
89        return value && value.trim() ? value.trim() : null;
90    }
91
92    function persistPendingQuery(query) {
93        pendingQuery = query || null;
94        writePendingHash(pendingQuery);
95    }
96
97    function clearPendingQuery() {
98        persistPendingQuery(null);
99    }
100
101    function restorePendingQuery() {
102        if (pendingQuery) {
103            return pendingQuery;
104        }
105
106        var fromHash = readPendingHash();
107        if (fromHash) {
108            pendingQuery = fromHash;
109            log("restored pending query from URL hash");
110        }
111
112        return pendingQuery;
113    }
114
115    function restoreInputValue(query) {
116        if (!query) {
117            return;
118        }
119
120        var inputs = document.querySelectorAll(".cosmema-ki-search input.chatbot-search");
121        for (var i = 0; i < inputs.length; i++) {
122            if (!inputs[i].value) {
123                inputs[i].value = query;
124            }
125        }
126    }
127
128    function openBorlabsConsent() {
129        try {
130            var contentBlocker = window.BorlabsCookie && window.BorlabsCookie.ContentBlocker;
131            if (contentBlocker && typeof contentBlocker.unblockServices === "function") {
132                contentBlocker.unblockServices([cfg.serviceId]);
133                log("consent opened via ContentBlocker.unblockServices");
134                return true;
135            }
136        } catch (error) {
137            log("unblockServices failed", error);
138        }
139
140        var fallbackButton = document.querySelector(
141            ".brlbs-cmpnt-content-blocker [data-borlabs-cookie-unblock]"
142        );
143        if (fallbackButton) {
144            fallbackButton.click();
145            return true;
146        }
147
148        if (window.console) {
149            console.warn("[cosmema-ki-search/borlabs] no Borlabs consent path available");
150        }
151        return false;
152    }
153
154    function removeDialog() {
155        var dialog = document.getElementById(cfg.dialogId);
156        if (dialog && dialog.parentNode) {
157            dialog.parentNode.removeChild(dialog);
158        }
159        dialogOpen = false;
160    }
161
162    function showConsentDialog() {
163        if (dialogOpen || document.getElementById(cfg.dialogId)) {
164            return;
165        }
166
167        dialogOpen = true;
168
169        var overlay = document.createElement("div");
170        overlay.id = cfg.dialogId;
171        overlay.className = "cosmema-ki-search-consent";
172        overlay.setAttribute("role", "presentation");
173
174        var card = document.createElement("div");
175        card.className = "cosmema-ki-search-consent__card";
176        card.setAttribute("role", "dialog");
177        card.setAttribute("aria-modal", "true");
178        card.setAttribute("aria-label", i18n.title || "KI-Chatbot");
179
180        var title = document.createElement("p");
181        title.className = "cosmema-ki-search-consent__title";
182        title.textContent = i18n.title || "KI-Chatbot";
183
184        var text = document.createElement("p");
185        text.className = "cosmema-ki-search-consent__text";
186        text.textContent =
187            i18n.text ||
188            "Der KI-Chatbot beantwortet Ihre Fragen. Zum Aktivieren ist Ihre Einwilligung nötig.";
189
190        var cta = document.createElement("button");
191        cta.type = "button";
192        cta.className = "cosmema-ki-search-consent__cta";
193        cta.textContent = i18n.cta || "KI-Chatbot aktivieren";
194
195        var close = document.createElement("button");
196        close.type = "button";
197        close.className = "cosmema-ki-search-consent__close";
198        close.textContent = i18n.close || "Schließen";
199
200        card.appendChild(title);
201        card.appendChild(text);
202        card.appendChild(cta);
203        card.appendChild(close);
204        overlay.appendChild(card);
205        document.body.appendChild(overlay);
206
207        function closeDialog(clearPending) {
208            if (clearPending) {
209                clearPendingQuery();
210            }
211            removeDialog();
212        }
213
214        overlay.addEventListener("click", function (event) {
215            if (event.target === overlay) {
216                closeDialog(true);
217            }
218        });
219
220        close.addEventListener("click", function () {
221            closeDialog(true);
222        });
223
224        cta.addEventListener("click", function () {
225            // Persist before Borlabs may reload the page after unblock.
226            restorePendingQuery();
227            removeDialog();
228            openBorlabsConsent();
229        });
230
231        log("consent dialog shown");
232    }
233
234    function flushPendingQuery() {
235        var query = restorePendingQuery();
236        if (!query) {
237            return;
238        }
239
240        try {
241            sendQuery(query);
242            clearPendingQuery();
243        } catch (error) {
244            log("sendQuery failed", error);
245            clearPendingQuery();
246        }
247    }
248
249    function waitAndSend() {
250        if (!restorePendingQuery()) {
251            return;
252        }
253
254        var start = Date.now();
255        var timer = setInterval(function () {
256            if (hasConsent() && widgetReady()) {
257                clearInterval(timer);
258                flushPendingQuery();
259            } else if (Date.now() - start > cfg.widgetWaitMs) {
260                clearInterval(timer);
261                log("widget not ready within timeout - dropping held query");
262                clearPendingQuery();
263            }
264        }, 250);
265    }
266
267    function onConsentStateChange() {
268        if (!borlabsReady() || !hasConsent() || !restorePendingQuery()) {
269            return;
270        }
271        waitAndSend();
272    }
273
274    function resumeAfterReload() {
275        var query = restorePendingQuery();
276        if (!query) {
277            return;
278        }
279
280        restoreInputValue(query);
281        bindConsentListeners();
282
283        if (!borlabsReady()) {
284            return;
285        }
286
287        if (hasConsent()) {
288            log("resuming pending query after reload");
289            waitAndSend();
290            return;
291        }
292
293        // Consent not yet readable (init race) — listeners will pick it up.
294        log("pending query present, waiting for Borlabs consent init");
295    }
296
297    function bindConsentListeners() {
298        if (listenersBound) {
299            return;
300        }
301        listenersBound = true;
302        document.addEventListener("borlabs-cookie-after-init", onConsentStateChange);
303        document.addEventListener("borlabs-cookie-consent-saved", onConsentStateChange);
304    }
305
306    function shouldGateSend() {
307        return borlabsReady() && !hasConsent();
308    }
309
310    function requestConsentAndSend(query) {
311        bindConsentListeners();
312
313        if (!borlabsReady()) {
314            sendQuery(query);
315            return;
316        }
317
318        if (hasConsent() && widgetReady()) {
319            sendQuery(query);
320            return;
321        }
322
323        persistPendingQuery(query);
324
325        if (!hasConsent()) {
326            log("search without consent - showing dialog, holding query");
327            showConsentDialog();
328            return;
329        }
330
331        waitAndSend();
332    }
333
334    window.cosmemaKiSearchBorlabs = {
335        isActive: borlabsReady,
336        hasConsent: hasConsent,
337        shouldGateSend: shouldGateSend,
338        requestConsentAndSend: requestConsentAndSend,
339    };
340
341    // After consent + page reload, pick up the stored query and send it.
342    if (document.readyState === "loading") {
343        document.addEventListener("DOMContentLoaded", resumeAfterReload);
344    } else {
345        resumeAfterReload();
346    }
347    document.addEventListener("borlabs-cookie-after-init", resumeAfterReload);
348})();

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.