PageSourceSearch

https://www.urbenia.es/app_support/pdccCloak/pdccCloak.js?v=3

js urbenia.es collected 2026-10-08 08:31:55 UTC 8,722 bytes, 194 lines download raw bytes

1/*
2Companion de "dormir" scripts e iframes de analitica/marketing (ver
3app_code/pS.Core/Security/TrackingScriptCloak.cs y el metodo
4IframeSeguimiento de web/DesktopModules/InmoBS3/layouts/inmuebles/WebInmobiliariaBase.cs).
5
6Motivo: PD Cookie Consent 1.5.4 intenta impedir la ejecucion de Google
7Analytics/Ads (GTM, gtag), Meta/Facebook Pixel, iframes de YouTube/Visita
8Virtual, etc. enganchandose al evento "beforescriptexecute", que Chrome y el
9resto de navegadores basados en Chromium ya no disparan (retirado). El
10selector sigue mostrando el aviso y "sabe" que deberia bloquear esos
11servicios, pero nunca llega a impedir que se ejecuten/carguen: la etiqueta
12carga igual, con o sin rechazo.
13
14En vez de bloquear DESPUES de que el recurso ya se ha cargado (imposible sin
15ese evento), el servidor sirve:
16  - los <script> de seguimiento como type="text/plain" (un tipo que el
17    navegador nunca ejecuta),
18  - los <iframe> de YouTube/Visita Virtual sin "src" (con "data-pdcc-src"),
19ambos marcados con "data-pdcc-cloak". Este companion los reactiva por su
20cuenta, leyendo la MISMA cookie "pd_cc" que ya mantiene PD Cookie Consent:
21
22  - accepted === true                          -> se activan todos
23  - blockList[].actived === true (por dominio) -> se activa solo ese servicio
24  - en cualquier otro caso                      -> se queda dormido (los
25    iframes muestran ademas un aviso con boton para cargarlo solo ese)
26
27No hace falta correr esto antes de que el navegador parsee la pagina: nada
28de esto se autoejecuta/autocarga, asi que no hay ninguna carrera que ganar.
29Basta con activarlo en DOMContentLoaded, y de nuevo cada vez que el
30visitante decide algo en el selector (igual que avisoSinCookies.js: PD
31Cookie Consent solo recarga la pagina al Aceptar/Guardar configuracion, asi
32que en la practica esto ultimo solo importa si algun dia dejase de recargar).
33
34Textos sin acentos a proposito (fichero ASCII puro, sin BOM, para no arriesgar
35la codificacion de un .js legacy servido tal cual desde disco).
36*/
37(function () {
38    'use strict';
39
40    var COOKIE = 'pd_cc';
41    var SELECTOR_SCRIPTS_DORMIDOS = 'script[type="text/plain"][data-pdcc-cloak]';
42    var SELECTOR_IFRAMES_DORMIDOS = 'iframe[data-pdcc-cloak]';
43
44    var TEXTOS = {
45        es: { aviso: 'Este contenido esta bloqueado por tu configuracion de cookies.', boton: 'Aceptar y cargar' },
46        ca: { aviso: 'Aquest contingut esta bloquejat per la teva configuracio de cookies.', boton: 'Acceptar i carregar' },
47        en: { aviso: 'This content is blocked by your cookie settings.', boton: 'Accept and load' },
48        eu: { aviso: 'Eduki hau blokeatuta dago zure cookie-ezarpenengatik.', boton: 'Onartu eta kargatu' },
49        gl: { aviso: 'Este contido esta bloqueado pola tua configuracion de cookies.', boton: 'Aceptar e cargar' }
50    };
51
52    function textos() {
53        var lang = (document.documentElement.lang || 'es').toLowerCase();
54        if (lang.indexOf('-') !== -1) lang = lang.split('-')[0];
55        return TEXTOS[lang] || TEXTOS.es;
56    }
57
58    // Mismo parseo que usa avisoSinCookies.js para la cookie de PD Cookie Consent.
59    function estadoCookies() {
60        var partes = decodeURIComponent(document.cookie).split(';');
61        for (var i = 0; i < partes.length; i++) {
62            var parte = partes[i];
63            while (parte.charAt(0) === ' ') parte = parte.substring(1);
64            if (parte.indexOf(COOKIE + '=') === 0) {
65                try {
66                    return JSON.parse(parte.substring(COOKIE.length + 1));
67                } catch (e) {
68                    return null;
69                }
70            }
71        }
72        return null;
73    }
74
75    function permitido(elemento, estado) {
76        if (!estado) return false;
77        if (estado.accepted === true) return true;
78
79        var lista = estado.blockList;
80        if (!lista || !lista.length) return false;
81
82        var src = elemento.getAttribute('src') || elemento.getAttribute('data-pdcc-src') || '';
83        var texto = elemento.textContent || '';
84
85        // Contenido de terceros que PDCC no cataloga como servicio propio (URL
86        // libre de un proveedor de tour virtual, por ejemplo): no hay categoria
87        // con la que emparejar por dominio. Si el visitante ha activado al menos
88        // una categoria no esencial y guardado configuracion (no ha dejado todo
89        // rechazado), se trata como consentido en espiritu: exigir ademas
90        // "Aceptar todas" para ver un video ya aceptado seria mas friccion de la
91        // que pide la ley.
92        var hayAlgunaCategoriaAceptada = false;
93
94        for (var i = 0; i < lista.length; i++) {
95            var item = lista[i];
96            if (!item || item.actived !== true) continue;
97            hayAlgunaCategoriaAceptada = true;
98            var patron = item.domain || item.contain;
99            if (!patron) continue;
100            if ((src && src.indexOf(patron) !== -1) || (texto && texto.indexOf(patron) !== -1)) {
101                return true;
102            }
103        }
104        return hayAlgunaCategoriaAceptada;
105    }
106
107    // Sustituye el <script type="text/plain"> por uno normal: cambiar solo el
108    // atributo "type" de un nodo ya insertado NO lo ejecuta, un <script> solo
109    // se ejecuta si el navegador lo ve nacer ya con un tipo ejecutable.
110    function activaScript(viejo) {
111        var nuevo = document.createElement('script');
112        for (var i = 0; i < viejo.attributes.length; i++) {
113            var attr = viejo.attributes[i];
114            if (attr.name === 'type' || attr.name === 'data-pdcc-cloak') continue;
115            nuevo.setAttribute(attr.name, attr.value);
116        }
117        if (!viejo.hasAttribute('src')) {
118            nuevo.textContent = viejo.textContent;
119        }
120        viejo.parentNode.replaceChild(nuevo, viejo);
121    }
122
123    function activaIframe(iframe) {
124        var aviso = iframe.parentNode && iframe.parentNode.querySelector
125            ? iframe.parentNode.querySelector('.pdccIframeAviso')
126            : null;
127        if (aviso && aviso.parentNode) aviso.parentNode.removeChild(aviso);
128
129        iframe.setAttribute('src', iframe.getAttribute('data-pdcc-src'));
130        iframe.removeAttribute('data-pdcc-cloak');
131    }
132
133    // Envuelve el iframe dormido en un contenedor con posicion relativa y le
134    // superpone un aviso con boton. El boton carga SOLO ese iframe (consentimiento
135    // puntual para ese contenido concreto), sin tocar la cookie ni recargar: no
136    // hace falta pasar por el selector completo para ver un unico video/tour.
137    function creaAviso(iframe) {
138        var wrap = document.createElement('div');
139        wrap.className = 'pdccIframeWrap';
140        // El iframe de YouTube lleva class="embed-responsive-item" (Bootstrap:
141        // position:absolute;width:100%;height:100%, posicionado respecto al
142        // ".embed-responsive" que lo envuelve). Al meter el wrap en medio, el wrap
143        // pasa a ser el ancestro posicionado mas cercano: tiene que ocupar el mismo
144        // hueco que ocupaba el iframe, o el video/aviso queda con altura 0.
145        if (iframe.classList.contains('embed-responsive-item')) {
146            wrap.className += ' pdccIframeWrap-absoluto';
147        }
148        iframe.parentNode.insertBefore(wrap, iframe);
149        wrap.appendChild(iframe);
150
151        var t = textos();
152        var aviso = document.createElement('div');
153        aviso.className = 'pdccIframeAviso';
154
155        var texto = document.createElement('p');
156        texto.className = 'pdccIframeAviso-texto';
157        texto.appendChild(document.createTextNode(t.aviso));
158
159        var boton = document.createElement('button');
160        boton.type = 'button';
161        boton.className = 'pdccIframeAviso-btn';
162        boton.appendChild(document.createTextNode(t.boton));
163        boton.addEventListener('click', function () {
164            activaIframe(iframe);
165        });
166
167        aviso.appendChild(texto);
168        aviso.appendChild(boton);
169        wrap.appendChild(aviso);
170    }
171
172    function reactivaPermitidos() {
173        var scripts = document.querySelectorAll(SELECTOR_SCRIPTS_DORMIDOS);
174        var iframes = document.querySelectorAll(SELECTOR_IFRAMES_DORMIDOS);
175        if (!scripts.length && !iframes.length) return;
176
177        var estado = estadoCookies();
178
179        for (var i = 0; i < scripts.length; i++) {
180            if (permitido(scripts[i], estado)) activaScript(scripts[i]);
181        }
182
183        for (var j = 0; j < iframes.length; j++) {
184            if (permitido(iframes[j], estado)) activaIframe(iframes[j]);
185            else creaAviso(iframes[j]);
186        }
187    }
188
189    if (document.readyState === 'loading') {
190        document.addEventListener('DOMContentLoaded', reactivaPermitidos);
191    } else {
192        reactivaPermitidos();
193    }
194})();

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.