1/* iSpazio â Shortcodes JS 2 * Handles client-side behavior for inline shortcodes that need it. 3 * 4 * [video] lazy bootstrap: 5 * <video data-isp-video="src.mp4" [data-isp-autoplay="1"]> renders with no 6 * <source> until it enters the viewport. Then we attach <source> + load(), 7 * and (if autoplay) start playback muted+inline. Saves the full-file 8 * download triggered by preload="auto" + autoplay. 9 */ 10(function () { 11 'use strict'; 12 13 function initVideos(root) { 14 var nodes = (root || document).querySelectorAll('video[data-isp-video]'); 15 if (!nodes.length) return; 16 17 var promote = function (v) { 18 if (v.dataset.ispVideoLoaded === '1') return; 19 v.dataset.ispVideoLoaded = '1'; 20 var fig = v.closest('.isp-video'); 21 if (fig) fig.setAttribute('data-isp-video-loading', '1'); 22 23 var s = document.createElement('source'); 24 s.src = v.dataset.ispVideo; 25 s.type = 'video/mp4'; 26 v.appendChild(s); 27 28 var clear = function () { if (fig) fig.removeAttribute('data-isp-video-loading'); }; 29 v.addEventListener('loadeddata', clear, { once: true }); 30 v.addEventListener('error', clear, { once: true }); 31 32 v.load(); 33 34 if (v.dataset.ispAutoplay === '1') { 35 v.muted = true; 36 v.playsInline = true; 37 var p = v.play(); 38 if (p && typeof p.catch === 'function') p.catch(function () {}); 39 } 40 }; 41 42 if (!('IntersectionObserver' in window)) { 43 // Old browsers: just promote on first user interaction. 44 nodes.forEach(function (v) { 45 var once = function () { promote(v); document.removeEventListener('scroll', once); }; 46 document.addEventListener('scroll', once, { passive: true, once: true }); 47 }); 48 return; 49 } 50 51 var io = new IntersectionObserver(function (entries) { 52 entries.forEach(function (e) { 53 if (!e.isIntersecting) return; 54 promote(e.target); 55 io.unobserve(e.target); 56 }); 57 }, { rootMargin: '300px 0px' }); 58 59 nodes.forEach(function (v) { io.observe(v); }); 60 } 61 62 // [video] modalità controls: overlay play grande + click-ovunque-per-avviare. 63 // Il pulsante .isp-video__play copre tutto il player: un click qualunque 64 // avvia la riproduzione come il play nativo. Quando il video è in play 65 // l'overlay si nasconde (pointer-events:none) e i controlli nativi tornano 66 // pienamente utilizzabili; alla pausa/fine l'overlay riappare. 67 function initOverlays(root) { 68 var figs = (root || document).querySelectorAll('.isp-video--controls'); 69 Array.prototype.forEach.call(figs, function (fig) { 70 if (fig.dataset.ispOverlayInit === '1') return; 71 fig.dataset.ispOverlayInit = '1'; 72 var v = fig.querySelector('video'); 73 var btn = fig.querySelector('.isp-video__play'); 74 if (!v || !btn) return; 75 76 btn.addEventListener('click', function (e) { 77 e.preventDefault(); 78 var p = v.play(); 79 if (p && typeof p.catch === 'function') p.catch(function () {}); 80 }); 81 82 v.addEventListener('play', function () { fig.classList.add('isp-video--playing'); }); 83 v.addEventListener('pause', function () { fig.classList.remove('isp-video--playing'); }); 84 v.addEventListener('ended', function () { fig.classList.remove('isp-video--playing'); }); 85 }); 86 } 87 88 // [ispazio_about_timeline] â anno espandibile/comprimibile col chevron. 89 function initHistory(root) { 90 var btns = (root || document).querySelectorAll('.isp-history__year'); 91 Array.prototype.forEach.call(btns, function (btn) { 92 if (btn.dataset.ispHistoryInit === '1') return; 93 btn.dataset.ispHistoryInit = '1'; 94 var group = btn.closest('.isp-history__group'); 95 if (!group) return; 96 btn.addEventListener('click', function () { 97 var collapsed = group.classList.toggle('is-collapsed'); 98 btn.setAttribute('aria-expanded', collapsed ? 'false' : 'true'); 99 }); 100 }); 101 } 102 103 /* [instagram]: la pagina /embed/ di Instagram comunica la propria altezza 104 * con un messaggio "MEASURE". La ascoltiamo per adattare il riquadro senza 105 * caricare embed.js di Meta. Un solo listener per pagina. */ 106 function initInstagram(root) { 107 var frames = (root || document).querySelectorAll('.isp-ig__frame'); 108 if (!frames.length || window.__ispIgMeasure) return; 109 window.__ispIgMeasure = true; 110 111 window.addEventListener('message', function (e) { 112 if (e.origin !== 'https://www.instagram.com') return; 113 var data = e.data; 114 if (typeof data === 'string') { 115 try { data = JSON.parse(data); } catch (err) { return; } 116 } 117 if (!data || String(data.type).toUpperCase() !== 'MEASURE') return; 118 119 var h = data.details && parseInt(data.details.height, 10); 120 if (!h || h < 200 || h > 3000) return; 121 122 var all = document.querySelectorAll('.isp-ig__frame'); 123 for (var i = 0; i < all.length; i++) { 124 if (all[i].contentWindow === e.source && all[i].parentNode) { 125 all[i].parentNode.style.setProperty('--isp-ig-h', h + 'px'); 126 return; 127 } 128 } 129 }, false); 130 } 131 132 function init(root) { initVideos(root); initOverlays(root); initHistory(root); initInstagram(root); } 133 134 if (document.readyState === 'loading') { 135 document.addEventListener('DOMContentLoaded', function () { init(); }); 136 } else { 137 init(); 138 } 139})();
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.