PageSourceSearch

https://www.guardioladebergueda.cat/front/view/js/klaro-init.js?ver=1790244106

js guardioladebergueda.cat collected 2026-09-24 10:07:47 UTC 7,509 bytes, 175 lines download raw bytes

1/**
2 * Inicialització mínima de Klaro.
3 *
4 * Klaro v0.7.11 nativament gestiona:
5 *   - Banner + modal de consentiment.
6 *   - Bloqueig de <script type="text/plain" data-name="X">.
7 *   - Bloqueig de <iframe data-name="X" data-src="...">.
8 *   - Esborrat de galetes declarades a services[].cookies[] (config server-side).
9 *   - Persistència del consentiment a la galeta `klaro`.
10 *
11 * Aquest fitxer NOMÉS afegeix l'auditoria a BD: cada vegada que l'usuari
12 * canvia preferències, enviem un snapshot a /requestconsentsnapshot.
13 *
14 * No hi ha cap altra capa pròpia al front.
15 */
16(function () {
17    'use strict';
18
19    // Klaro accepta cookies[] com [name|RegExp, path, domain]. El PHP envia regex com
20    // string "/^_ga_.*$/". Cal convertir-los a objectes RegExp perquè Klaro pugui
21    // esborrar wildcards (com _ga_ABC123) al rebutjar el servei.
22    (function convertCookieRegexes() {
23        try {
24            var cfg = window.klaroConfig;
25            if (!cfg || !Array.isArray(cfg.services)) return;
26            cfg.services.forEach(function (svc) {
27                if (!Array.isArray(svc.cookies)) return;
28                svc.cookies = svc.cookies.map(function (c) {
29                    if (Array.isArray(c) && typeof c[0] === 'string' && /^\/.+\/[gimsuy]*$/.test(c[0])) {
30                        var m = c[0].match(/^\/(.+)\/([gimsuy]*)$/);
31                        if (m) {
32                            try { c[0] = new RegExp(m[1], m[2]); } catch (e) {}
33                        }
34                    }
35                    return c;
36                });
37            });
38        } catch (e) {}
39    })();
40
41    function getCookie(name) {
42        var parts = document.cookie.split(';');
43        for (var i = 0; i < parts.length; i++) {
44            var c = parts[i].trim();
45            if (c.indexOf(name + '=') === 0) {
46                return decodeURIComponent(c.substring(name.length + 1));
47            }
48        }
49        return '';
50    }
51
52    function getOrCreateConsentUserHash() {
53        var key = 'cookie_consent_user_hash';
54        try {
55            // sessionStorage: no persisteix entre sessions, no requereix consentiment previ
56            var existing = sessionStorage.getItem(key);
57            if (existing) return existing;
58            var rnd = Math.random().toString(16).slice(2) + Date.now().toString(16);
59            sessionStorage.setItem(key, rnd);
60            return rnd;
61        } catch (e) {
62            return 'anon_' + Date.now().toString(16);
63        }
64    }
65
66    // El dedupe es persisteix a sessionStorage: sense això, cada càrrega de pàgina
67    // enviava un snapshot idèntic i es disparava el rate-limit del servidor (429).
68    var __snapshotKey = 'cookie_consent_last_snapshot';
69    var __timer = null;
70
71    function getLastSerialized() {
72        try { return sessionStorage.getItem(__snapshotKey); } catch (e) { return null; }
73    }
74
75    function setLastSerialized(value) {
76        try { sessionStorage.setItem(__snapshotKey, value); } catch (e) {}
77    }
78
79    function sendConsentSnapshot(preferences) {
80        clearTimeout(__timer);
81        __timer = setTimeout(function () {
82            var audit = window.__cookieAudit || {};
83            var endpoint = audit.endpoint || '/requestconsentsnapshot';
84            var versionTag = audit.versionTag || (window.klaroConfig && window.klaroConfig.version) || 'v1';
85
86            var payload = {
87                user_hash: getOrCreateConsentUserHash(),
88                version_tag: versionTag,
89                preferences: preferences || {}
90            };
91            var serialized = JSON.stringify(payload);
92            if (serialized === getLastSerialized()) return;
93            setLastSerialized(serialized);
94
95            // fetch nativa: 0 dependències jQuery
96            try {
97                fetch(endpoint, {
98                    method: 'POST',
99                    headers: { 'Content-Type': 'application/json; charset=utf-8' },
100                    body: serialized,
101                    credentials: 'same-origin'
102                }).then(function (r) {
103                    // Si ha fallat per una causa transitòria, oblidem el dedupe per reintentar.
104                    // En 429 NO reintentem: agreujaria el rate-limit.
105                    if (!r.ok && r.status !== 429) setLastSerialized('');
106                }).catch(function () { setLastSerialized(''); });
107            } catch (e) {}
108        }, 300);
109    }
110
111    function hook() {
112        if (!window.klaro || typeof window.klaro.getManager !== 'function') return false;
113        var manager = window.klaro.getManager();
114        if (!manager || manager.__snapshotHooked) return true;
115        // Verificar que el manager esté completamente inicializado
116        if (!manager.consents || !manager.watch) return false;
117        manager.__snapshotHooked = true;
118
119        // Si l'usuari ja té la galeta klaro (visita de retorn), activem confirmed=true
120        // perquè el context notice mostri els dos botons: "Acceptar" i "Acceptar Sempre".
121        // Per a visites noves (sense galeta), s'activa en el primer saveConsents/applyConsents
122        // (just after banner interaction), evitant amagar el banner principal.
123        if (getCookie('klaro-v2') && !manager.confirmed) {
124            manager.confirmed = true;
125        }
126
127        // Snapshot inicial (estat actual de la galeta `klaro`)
128        try { sendConsentSnapshot(manager.consents || {}); } catch (e) {}
129
130        // Subscripció a l'API pública de Klaro (sense parxejar saveConsents)
131        if (typeof manager.watch === 'function') {
132            manager.watch({
133                update: function (obj, name) {
134                    // Després de la primera interacció amb el banner principal,
135                    // activem confirmed perquè el context notice mostri tots dos botons.
136                    if ((name === 'saveConsents' || name === 'applyConsents') && !manager.confirmed) {
137                        manager.confirmed = true;
138                    }
139                    if (name !== 'consents' && name !== 'saveConsents' && name !== 'applyConsents') return;
140                    try { sendConsentSnapshot(manager.consents || {}); } catch (e) {}
141                }
142            });
143        }
144        return true;
145    }
146
147    // Re-aplica consents quan el DOM és complet.
148    // Klaro es carrega al <head> i crida applyConsents() abans que el <body>
149    // existeixi: els iframes/scripts amb data-name no es troben i queden bloquejats.
150    // Només s'executa si ja existeix la galeta klaro (usuari de retorn amb consentiment
151    // previ). Per a primeres visites (sense galeta) no s'interfereix per no amagar el banner.
152    document.addEventListener('DOMContentLoaded', function () {
153        try {
154            if (!getCookie('klaro-v2')) return;
155            if (window.klaro && typeof window.klaro.getManager === 'function') {
156                var m = window.klaro.getManager();
157                if (m && typeof m.applyConsents === 'function') {
158                    m.applyConsents();
159                }
160            }
161        } catch (e) {}
162    });
163
164    // Klaro s'inicialitza per si sol llegint window.klaroConfig. Només cal
165    // esperar que el manager existeixi per a enganxar l'auditoria.
166    var tries = 0;
167    var t = setInterval(function () {
168        try {
169            if (hook() || tries++ > 80) clearInterval(t);
170        } catch (e) {
171            // silenci: potser klaro no està totalment inicialitzat encara
172            if (tries++ > 80) clearInterval(t);
173        }
174    }, 250);
175})();

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.