PageSourceSearch

https://trondheim24.no/wp-content/plugins/trondheim24-reel/assets/js/reel.js?ver=1.2

js trondheim24.no collected 2026-10-01 12:19:18 UTC 4,145 bytes, 115 lines download raw bytes

1// assets/reel.js
2(function(){
3  const $  = (s, r=document)=>r.querySelector(s);
4  const $$ = (s, r=document)=>[...r.querySelectorAll(s)];
5  const YT_HOVER = 'autoplay=1&mute=1&playsinline=1&controls=0&modestbranding=1&rel=0&iv_load_policy=3&cc_load_policy=0&fs=0&disablekb=1';
6
7  const ytId = (src)=>{
8    try{
9      const u=new URL(src,location.origin);
10      if(u.hostname.includes('youtu.be')) return u.pathname.split('/').pop();
11      if(u.searchParams.get('v')) return u.searchParams.get('v');
12      const p=u.pathname.split('/'); const i=p.findIndex(x=>['embed','shorts','watch'].includes(x));
13      return (i>=0 && p[i+1])?p[i+1]:p.pop();
14    }catch{ return src.split('/').pop(); }
15  };
16
17  function ensureHit(thumb, label='Åpne video'){
18    let hit = thumb.querySelector('.reel-hit');
19    if (!hit){
20      hit = document.createElement('button');
21      hit.className = 'reel-hit';
22      hit.type = 'button';
23      hit.setAttribute('aria-label', label);
24      thumb.appendChild(hit);
25    }
26    return hit;
27  }
28
29  function mountLocalHover(thumb, src, poster){
30    if(thumb.__mount) return;
31    const v=document.createElement('video');
32    v.src=src; if(poster) v.poster=poster;
33    v.muted=true; v.playsInline=true; v.loop=true; v.preload='metadata';
34    v.addEventListener('canplay', ()=>{ thumb.classList.add('is-ready'); v.play().catch(()=>{}); }, {once:true});
35    thumb.appendChild(v);
36    thumb.__mount=v;
37  }
38
39  function mountYTHover(thumb, src){
40    if(thumb.__mount) return;
41    const id=ytId(src);
42    const ifr=document.createElement('iframe');
43    ifr.src=`https://www.youtube.com/embed/${id}?${YT_HOVER}`;
44    ifr.allow='autoplay; encrypted-media; picture-in-picture';
45    ifr.setAttribute('allowfullscreen','');
46    ifr.addEventListener('load', ()=>{ thumb.classList.add('is-ready'); }, {once:true});
47    thumb.appendChild(ifr);
48    thumb.__mount=ifr;
49  }
50
51  function unmountHover(thumb){
52    if(!thumb.__mount) return;
53    thumb.__mount.pause?.();
54    thumb.__mount.remove();
55    thumb.__mount=null;
56    thumb.classList.remove('is-ready');
57  }
58
59  const root = $('[data-reel-carousel]'); if(!root) return;
60
61  // Pause lokale videoer når kort er utenfor view
62  const io = new IntersectionObserver(ents=>{
63    ents.forEach(e=>{
64      const v=e.target.querySelector('video');
65      if(!v) return;
66      e.isIntersecting ? v.play().catch(()=>{}) : v.pause();
67    });
68  },{threshold:.8});
69
70  // Bind hover + legg klikk-lag (klikk håndteres av reel-modal.js via event bubbling)
71  $$('.reel-item', root).forEach(card=>{
72    io.observe(card);
73    const thumb = card.querySelector('.reel-thumb'); if(!thumb) return;
74    ensureHit(thumb, 'Spill av i fullskjerm');
75
76    if (window.matchMedia('(pointer:fine)').matches){
77      thumb.addEventListener('mouseenter', ()=>{
78        const {type, src, poster}=card.dataset;
79        if(type==='local') mountLocalHover(thumb, src, poster);
80        else if(type==='youtube') mountYTHover(thumb, src);
81      });
82      thumb.addEventListener('mouseleave', ()=> unmountHover(thumb));
83    }
84  });
85})();
86
87// Piler
88document.addEventListener('DOMContentLoaded', ()=>{
89  const carousels = document.querySelectorAll('[data-reel-carousel]');
90  carousels.forEach(car => {
91    const list = car.querySelector('.reel-list');
92    if (!list) return;
93
94    // lag piler
95    const makeBtn = (dir) => {
96      const b = document.createElement('button');
97      b.className = `reel-arrow ${dir}`;
98      b.type = 'button';
99      b.innerHTML = dir === 'prev'
100        ? '<svg viewBox="0 0 24 24"><path fill="currentColor" d="M15.4 3.4 9 9.8 15.4 16.2 14 17.6 6.4 10 14 2.4z"/></svg>'
101        : '<svg viewBox="0 0 24 24"><path fill="currentColor" d="M8.6 3.4 15 9.8 8.6 16.2 10 17.6 17.6 10 10 2.4z"/></svg>';
102      return b;
103    };
104
105    const prev = makeBtn('prev');
106    const next = makeBtn('next');
107    car.appendChild(prev);
108    car.appendChild(next);
109
110    const scrollStep = () => list.clientWidth * 0.8;
111
112    prev.addEventListener('click', ()=> list.scrollBy({ left: -scrollStep(), behavior: 'smooth' }));
113    next.addEventListener('click', ()=> list.scrollBy({ left: scrollStep(), behavior: 'smooth' }));
114  });
115});

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.