1/* ============================================================================ 2 MOTION · comportamentele care nu se pot face doar din CSS 3 1. barÄ de progres la scroll 4 2. întârziere în cascadÄ la reveal (--i pe fiecare copil dintr-o grilÄ) 5 3. înclinare uÈoarÄ a cardurilor dupÄ cursor (doar pe mouse, nu pe touch) 6 4. parallax fin pe fotografiile mari 7 5. eticheta âVezi traseul" injectatÄ Ã®n cardurile de traseu 8 6. numÄrÄtoare pentru cifre, dacÄ pagina nu are deja propriul mecanism 9 Totul se dezactiveazÄ la prefers-reduced-motion. 10 RuleazÄ Èi dupÄ schimbarea paginii în propunerea 6 (MutationObserver). 11 ============================================================================ */ 12(function(){ 13 var reduce = matchMedia('(prefers-reduced-motion: reduce)').matches; 14 var fine = matchMedia('(hover: hover) and (pointer: fine)').matches; 15 16 /* ---- 1. barÄ de progres ---- */ 17 var bar=document.getElementById('sprog'); 18 if(!bar){bar=document.createElement('div');bar.id='sprog';document.body.appendChild(bar);} 19 function prog(){ 20 var h=document.documentElement.scrollHeight-innerHeight; 21 bar.style.width=(h>0? (scrollY/h*100):0)+'%'; 22 } 23 addEventListener('scroll',prog,{passive:true}); 24 addEventListener('resize',prog); prog(); 25 26 /* ---- 2. cascadÄ pe reveal ---- */ 27 function stagger(){ 28 document.querySelectorAll('.g2,.g3,.g4,.tgrid,.sup,.evl,.dash,.blz-row').forEach(function(grid){ 29 var i=0; 30 [].forEach.call(grid.children,function(c){ 31 if(c.classList.contains('rv')||c.classList.contains('tc')||c.classList.contains('cd')||c.classList.contains('evr')){ 32 c.style.setProperty('--i',i++); 33 } 34 }); 35 }); 36 } 37 38 /* ---- 3. înclinare dupÄ cursor pe cardurile de traseu ---- */ 39 function tilt(){ 40 if(reduce||!fine)return; 41 document.querySelectorAll('.tc:not([data-tilt])').forEach(function(card){ 42 card.dataset.tilt='1'; card.classList.add('tilt'); 43 card.addEventListener('mousemove',function(e){ 44 var r=card.getBoundingClientRect(); 45 var px=(e.clientX-r.left)/r.width-.5, py=(e.clientY-r.top)/r.height-.5; 46 card.style.setProperty('--ry',(px*5).toFixed(2)+'deg'); 47 card.style.setProperty('--rx',(-py*4).toFixed(2)+'deg'); 48 }); 49 card.addEventListener('mouseleave',function(){ 50 card.style.setProperty('--ry','0deg'); card.style.setProperty('--rx','0deg'); 51 }); 52 }); 53 } 54 55 /* ---- 4. parallax pe fotografii mari ---- */ 56 var pars=[]; 57 function collectPar(){ 58 pars=[]; 59 if(reduce)return; 60 document.querySelectorAll('.hph img,.evi img,.story .im img,.h2img img').forEach(function(img){ 61 if(img.closest('.hv'))return; /* hero-ul video nu se atinge */ 62 img.classList.add('par'); pars.push(img); 63 }); 64 } 65 function runPar(){ 66 if(reduce||!pars.length)return; 67 var vh=innerHeight;
68 pars.forEach(function(img){ 69 var r=img.parentElement.getBoundingClientRect(); 70 if(r.bottom<-100||r.top>vh+100)return; 71 var p=(r.top+r.height/2-vh/2)/vh; // -1 .. 1 72 img.style.setProperty('--py',(p*-16).toFixed(1)+'px'); 73 }); 74 } 75 addEventListener('scroll',function(){requestAnimationFrame(runPar)},{passive:true}); 76 77 /* ---- 5. eticheta GPX în cardurile de traseu ---- */ 78 function gpx(){ 79 document.querySelectorAll('.tc .ph:not([data-gx])').forEach(function(ph){ 80 ph.dataset.gx='1'; 81 var s=document.createElement('span'); 82 s.className='gx'; s.textContent='Vezi traseul'; 83 ph.appendChild(s); 84 }); 85 } 86 87 /* ---- 6. numÄrÄtoare, dacÄ pagina nu are deja ---- */ 88 function counters(){ 89 if(window.__hasCounters)return; 90 if(reduce)return; 91 var io=new IntersectionObserver(function(es){es.forEach(function(x){ 92 if(!x.isIntersecting)return; io.unobserve(x.target); 93 var t=parseFloat(x.target.dataset.c),s=performance.now(); 94 (function f(n){var p=Math.min((n-s)/1200,1); 95 x.target.textContent=Math.round(t*(1-Math.pow(1-p,3))); 96 if(p<1)requestAnimationFrame(f)})(s); 97 })},{threshold:.6}); 98 document.querySelectorAll('[data-c]:not([data-done])').forEach(function(el){el.dataset.done='1';io.observe(el)}); 99 } 100 101 /* ---- orchestrare defensivÄ ---- 102 Observatorul se deconecteazÄ cât timp ruleazÄ, ca modificÄrile pe care le 103 face chiar el (adÄugare de clase) sÄ nu îl declanÈeze din nou. Plus debounce, 104 ca zecile de clase .in adÄugate la scroll sÄ nu producÄ zeci de treceri. */ 105 var mo=null, t=null, running=false; 106 function all(){ 107 if(running)return; running=true; 108 if(mo)mo.disconnect(); 109 try{ stagger(); tilt(); collectPar(); runPar(); gpx(); } 110 catch(err){ console.warn('motion.js:',err); } 111 if(mo)mo.observe(document.body,{subtree:true,childList:true}); 112 running=false; 113 } 114 function schedule(){ clearTimeout(t); t=setTimeout(all,180); } 115 all(); 116 /* la schimbarea paginii în propunerea 6, elementele noi primesc acelaÈi tratament. 117 UrmÄrim doar apariÈia de noduri, nu schimbÄrile de clasÄ. */ 118 mo=new MutationObserver(function(recs){ 119 /* ignorÄm complet mutaÈiile din interiorul hero-ului video */ 120 for(var i=0;i<recs.length;i++){ 121 var t=recs[i].target; 122 if(t&&t.closest&&t.closest('.hv'))continue; 123 return schedule(); 124 } 125 }); 126 mo.observe(document.body,{subtree:true,childList:true}); 127 addEventListener('hashchange',schedule); 128})();
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.