1(()=>{ 2'use strict'; 3const q=(s,r=document)=>r.querySelector(s), qa=(s,r=document)=>Array.from(r.querySelectorAll(s)); 4const clamp=(n,a,b)=>Math.max(a,Math.min(b,n)); 5const directChild=(el,sel)=>Array.from(el?.children||[]).find(x=>x.matches(sel)); 6 7/* Canonical navigation tree preserved from the full homepage menu. Some policy 8 pages only carried a partial/broken mobile tree in the legacy source, so every 9 route receives the same permanent archive navigation before dropdowns are built. */ 10const CANONICAL_MOBILE_MENU_HTML="<ul class=\"wsite-menu-default\">\n<li class=\"wsite-menu-item-wrap\" id=\"active\">\n<a class=\"wsite-menu-item\" href=\"/\">\n\t\t\t\tHome\n\t\t\t</a>\n</li>\n<li class=\"wsite-menu-item-wrap has-submenu\" id=\"pg586723196324815242\">\n<a class=\"wsite-menu-item\" href=\"/about.html\">\n\t\t\t\tAbout\n\t\t\t</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-425179657384509877\">\n<a class=\"wsite-menu-subitem\" href=\"/about.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tWhy Compete?\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-822424364151753704\">\n<a class=\"wsite-menu-subitem\" href=\"/about.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tAwards Categories\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-484477609457991267\">\n<a class=\"wsite-menu-subitem\" href=\"/about.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tOur Jury Team\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-621411280795896699\">\n<a class=\"wsite-menu-subitem\" href=\"/about.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tTerms & Conditions\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-item-wrap\" id=\"pg543697130636997019\">\n<a class=\"wsite-menu-item\" href=\"https://www.moviemaker.com/the-filmhaus-evolution-a-new-jury-and-a-vision-renewed/\" target=\"_blank\">\n\t\t\t\tNews\n\t\t\t</a>\n</li>\n<li class=\"wsite-menu-item-wrap has-submenu\" id=\"pg959143843760578545\">\n<a class=\"wsite-menu-item\">\n\t\t\t\tResults\n\t\t\t</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-845697680202976948\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\t2025\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-199266912944601379\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\t29-Oct Finalists\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-857135867177168178\">\n<a class=\"wsite-menu-subitem\" href=\"/2025-winners-nominees.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tWinners & Nominees\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-520285231357968100\">\n<a class=\"wsite-menu-subitem\" href=\"/2025-semifinals.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tSemi-Finalists\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-504473690237696038\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\t2024\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-780505697483928801\">\n<a class=\"wsite-menu-subitem\" href=\"/2024-3-results.html\">\n<span class=\"wsite-menu-title\">\n\t\t\t31-Oct Finalists\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-755660665988087845\">\n<a class=\"wsite-menu-subitem\" href=\"/2024-3-results.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tWinners & Nominees\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-782904378461531749\">\n<a class=\"wsite-menu-subitem\" href=\"/2024-3-results.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tSemi-Finalists\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-745669139187034368\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\t12-Jun Finalists\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-822118939255319373\">\n<a class=\"wsite-menu-subitem\" href=\"/2024-2-results-winners-nominees.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tWinners & Nominees\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-788935615212808216\">\n<a class=\"wsite-menu-subitem\" href=\"/2024-2-results-semi-finalists.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tSemi-Finalists\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-815510221843053569\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\t4-Mar Finalists\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-677739252535721791\">\n<a class=\"wsite-menu-subitem\" href=\"/2024-1-results-winners-nominees.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tWinners & Nominees\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-989290623410691742\">\n<a class=\"wsite-menu-subitem\" href=\"/2024-1-results-semi-finalists.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tSemi-Finalists\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-714928568887149543\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\t2023\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-893789841841106669\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\t27-October Finalists\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-474328147730937123\">\n<a class=\"wsite-menu-subitem\" href=\"/2023-2-results-winners-nominees.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tWinners & Nominees\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-268379218119407032\">\n<a class=\"wsite-menu-subitem\" href=\"/2023-2-results-semifinalists.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tSemi-Finalists\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-809046856259107649\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\t24-April Finalists\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-503540590736517328\">\n<a class=\"wsite-menu-subitem\" href=\"/2023-1-results-winners-nominees.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tWinners & Nominees\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-175023518219251338\">\n<a class=\"wsite-menu-subitem\" href=\"/2023-1-results-finalists.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tOther Finalists\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-997608781809016125\">\n<a class=\"wsite-menu-subitem\" href=\"/2023-1-results-semifinalists.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tSemi-Finalists\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-subitem-wrap has-submenu\" id=\"wsite-nav-309632566330144511\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\t2022\n\t\t</span><span class=\"wsite-menu-arrow\">></span>\n</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-814066915420491933\">\n<a class=\"wsite-menu-subitem\" href=\"/2022-results.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tWinners & Nominees\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-240569501811368432\">\n<a class=\"wsite-menu-subitem\" href=\"/2022-finals.html\">\n<span class=\"wsite-menu-title\">\n\t\t\tOther Finalists\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-945101594301954953\">
10\n<a class=\"wsite-menu-subitem\" href=\"/2021.html\">\n<span class=\"wsite-menu-title\">\n\t\t\t2021\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-850261941533089396\">\n<a class=\"wsite-menu-subitem\" href=\"/2020.html\">\n<span class=\"wsite-menu-title\">\n\t\t\t2020\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-item-wrap has-submenu\" id=\"pg513485669766347496\">\n<a class=\"wsite-menu-item\">\n\t\t\t\tShowcase\n\t\t\t</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-753341163433951676\">\n<a class=\"wsite-menu-subitem\" href=\"/2025-showcase.html\">\n<span class=\"wsite-menu-title\">\n\t\t\t2025\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-492352240527833258\">\n<a class=\"wsite-menu-subitem\" href=\"/2024-showcase.html\">\n<span class=\"wsite-menu-title\">\n\t\t\t2024 (Closed)\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-318611594281750498\">\n<a class=\"wsite-menu-subitem\" href=\"/2023-showcase.html\">\n<span class=\"wsite-menu-title\">\n\t\t\t2023 (Closed)\n\t\t</span>\n</a>\n</li>\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-711775656286941571\">\n<a class=\"wsite-menu-subitem\" href=\"/2022-showcase.html\">\n<span class=\"wsite-menu-title\">\n\t\t\t2022 (Closed)\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n<li class=\"wsite-menu-item-wrap\" id=\"pg973119840694798189\">\n<a class=\"wsite-menu-item\" href=\"https://filmfreeway.com/filmhaus\" rel=\"noopener noreferrer\" target=\"_blank\">\n\t\t\t\tSubmit\n\t\t\t</a>\n</li>\n<li class=\"wsite-menu-item-wrap has-submenu\" id=\"pg376864275210229934\">\n<a class=\"wsite-menu-item\">\n\t\t\t\tContact\n\t\t\t</a><span class=\"icon-caret\"></span>\n<div class=\"wsite-menu-wrap\" style=\"display:none\">\n<ul class=\"wsite-menu\">\n<li class=\"wsite-menu-subitem-wrap\" id=\"wsite-nav-930762605800218402\">\n<a class=\"wsite-menu-subitem\">\n<span class=\"wsite-menu-title\">\n\t\t\[email protected]\n\t\t</span>\n</a>\n</li>\n</ul>\n</div>\n</li>\n</ul>\n"; 11 12/* ---------- Header order, sticky transition, menus ---------- */ 13const banner=q('.banner-wrap'); 14const header=q('.dusk-header'); 15function syncAffix(){ 16 if(!banner||!header||innerWidth<=992){document.body.classList.remove('affix');return;} 17 document.body.classList.toggle('affix',scrollY>=banner.offsetHeight); 18} 19addEventListener('scroll',syncAffix,{passive:true}); 20addEventListener('resize',syncAffix); 21 22function stripCloneIds(node){ 23 if(node.id)node.removeAttribute('id'); 24 qa('[id]',node).forEach(x=>x.removeAttribute('id')); 25 qa('[style]',node).forEach(x=>{ 26 const s=x.getAttribute('style')||''; 27 x.setAttribute('style',s.replace(/(^|;)\s*(display|position|top|left|right|bottom)\s*:[^;]*/gi,'$1')); 28 }); 29} 30function labelOf(a){return (a?.textContent||'').replace(/\s+/g,' ').trim().toLowerCase();} 31function setupMenus(){ 32 const burger=q('.hamburger'); 33 if(burger){ 34 burger.addEventListener('click',e=>{e.preventDefault();document.body.classList.toggle('nav-open');}); 35 } 36 37 const mobile=q('.mobile-nav'); 38 if(mobile){ 39 mobile.innerHTML=CANONICAL_MOBILE_MENU_HTML; 40 qa('a',mobile).forEach(a=>{ 41 if(labelOf(a)==='[email protected]')a.href='mailto:[email protected]'; 42 }); 43 qa('li.has-submenu',mobile).forEach(li=>{ 44 const caret=directChild(li,'.icon-caret'); 45 const wrap=directChild(li,'.wsite-menu-wrap'); 46 const a=directChild(li,'a'); 47 if(!wrap)return; 48 const toggle=e=>{ 49 e&&e.preventDefault();e&&e.stopPropagation(); 50 const open=!wrap.classList.contains('open'); 51 wrap.classList.toggle('open',open); 52 li.classList.toggle('fh-submenu-open',open); 53 caret&&caret.setAttribute('aria-expanded',String(open)); 54 }; 55 caret&&caret.addEventListener('click',toggle); 56 if(a&&!a.getAttribute('href'))a.addEventListener('click',toggle); 57 }); 58 qa('a[href]',mobile).forEach(a=>a.addEventListener('click',()=>{ 59 if(a.getAttribute('href')&&a.getAttribute('href')!=='#')document.body.classList.remove('nav-open'); 60 })); 61 } 62 63 const desktop=q('.desktop-nav'); 64 if(desktop&&mobile){ 65 const targets={about:'about',results:'results',showcase:'showcase',contact:'contact'}; 66 qa(':scope > ul >
66 li',desktop).forEach(li=>{ 67 const top=directChild(li,'a.wsite-menu-item'); 68 const key=labelOf(top); 69 if(key==='contact'&&top&&!top.getAttribute('href'))top.href='mailto:[email protected]'; 70 if(!targets[key])return; 71 if(directChild(li,'.fh-desktop-menu'))return; 72 const source=qa(':scope > ul > li',mobile).find(mli=>labelOf(directChild(mli,'a.wsite-menu-item'))===key); 73 const wrap=source&&directChild(source,'.wsite-menu-wrap'); 74 if(!wrap)return; 75 const clone=wrap.cloneNode(true); 76 stripCloneIds(clone); 77 clone.classList.add('fh-desktop-menu'); 78 li.classList.add('fh-has-submenu'); 79 li.appendChild(clone); 80 qa('a',clone).forEach(a=>{if(labelOf(a)==='[email protected]')a.href='mailto:[email protected]';}); 81 }); 82 } 83 const runtime=q('#wsite-menus'); 84 if(runtime)runtime.id='_filmhaus_runtime_menu_source'; 85} 86setupMenus(); 87 88/* Desktop menus must work on click/tap as well as hover. */ 89function setupDesktopMenuClicks(){ 90 const desktop=q('.desktop-nav');if(!desktop)return; 91 const closeAll=(except=null)=>qa('.fh-menu-open',desktop).forEach(li=>{if(li!==except)li.classList.remove('fh-menu-open');}); 92 qa('li.fh-has-submenu',desktop).forEach(li=>{ 93 const top=directChild(li,'a.wsite-menu-item');if(!top)return; 94 const label=labelOf(top); 95 top.setAttribute('aria-haspopup','true');top.setAttribute('aria-expanded','false'); 96 /* About and Contact are genuine destinations and must remain normal links. 97 Results / Showcase use click as an explicit menu toggle; hover/focus still 98 works through CSS and their hrefs remain useful as no-JS fallbacks. */ 99 if(label!=='results'&&label!=='showcase')return; 100 top.addEventListener('click',e=>{ 101 e.preventDefault();e.stopPropagation(); 102 const open=!li.classList.contains('fh-menu-open'); 103 closeAll(li);li.classList.toggle('fh-menu-open',open);top.setAttribute('aria-expanded',String(open)); 104 }); 105 }); 106 qa('.fh-desktop-menu li.has-submenu',desktop).forEach(li=>{ 107 const a=directChild(li,'a.wsite-menu-subitem');if(!a)return; 108 a.addEventListener('click',e=>{ 109 const nested=directChild(li,'.wsite-menu-wrap'); 110 if(!nested)return; 111 e.preventDefault();e.stopPropagation(); 112 const open=!li.classList.contains('fh-menu-open'); 113 Array.from(li.parentElement?.children||[]).forEach(s=>{if(s!==li)s.classList.remove('fh-menu-open')}); 114 li.classList.toggle('fh-menu-open',open); 115 }); 116 }); 117 document.addEventListener('click',e=>{if(!desktop.contains(e.target))closeAll();}); 118 document.addEventListener('keydown',e=>{if(e.key==='Escape')closeAll();}); 119} 120setupDesktopMenuClicks(); 121 122/* Submission links are intentionally external and direct to FilmFreeway. */ 123const FILMFREEWAY='https://filmfreeway.com/filmhaus'; 124qa('a').forEach(a=>{ 125 const label=(a.textContent||'').replace(/\s+/g,' ').trim().toLowerCase(); 126 if((a.classList.contains('wsite-menu-item')&&label==='submit') || label==='here' && /submit your project/i.test(a.parentElement?.textContent||'')){ 127 a.href=FILMFREEWAY;a.target='_blank';a.rel='noopener noreferrer'; 128 } 129}); 130 131/* ---------- Captured video hero heights ---------- */ 132const hero=q('.wsite-header-section'); 133function syncHero(){ 134 if(!hero)return; 135 const d=parseFloat(document.body.dataset.fhHeroDesktop||''); 136 const m=parseFloat(document.body.dataset.fhHeroMobile||''); 137 const h=innerWidth<=992?(m||d):(d||m); 138 if(h)hero.style.setProperty('height',h+'px','important'); 139} 140addEventListener('resize',syncHero); 141syncHero(); 142 143/* ---------- Viewport-width marketplace elements ---------- */ 144function syncFullWidth(){ 145 qa('.wad_full_width_element:not(.content_width)').forEach(el=>{ 146 el.style.setProperty('width','100vw','important'); 147 el.style.setProperty('left','calc(50% - 50vw)','important'); 148 }); 149} 150addEventListener('resize',syncFullWidth); 151syncFullWidth(); 152 153/* ---------- Local video playback ---------- */ 154qa('.wsite-section-bg-video video').forEach(v=>{ 155 v.muted=true;v.loop=true;v.autoplay=true;v.playsInline=true; 156 const p=v.play();if(p&&p.catch)p.catch(()=>{}); 157}); 158 159/* ---------- Boo/FlexSlider local runtime ---------- */
160qa('.booFullwidthSlider').forEach(slider=>{ 161 const ul=q('.flex-viewport > ul.slides',slider);const viewport=q('.flex-viewport',slider);if(!ul||!viewport)return; 162 qa(':scope > li.clone',ul).forEach(x=>x.remove()); 163 const slides=qa(':scope > li',ul);if(!slides.length)return; 164 let index=slides.findIndex(x=>x.classList.contains('flex-active-slide'));if(index<0)index=0; 165 const dots=qa('.flex-control-nav a',slider),prev=q('.flex-prev',slider),next=q('.flex-next',slider); 166 function naturalHeight(slide){ 167 const img=q('.booImage img',slide); 168 const imageH=img?(img.getBoundingClientRect().width*(img.naturalHeight||9)/(img.naturalWidth||16)):0; 169 const content=q('.booSlideContent',slide); 170 let contentH=0; 171 if(content){ 172 const oldH=content.style.height;content.style.height='auto'; 173 contentH=content.scrollHeight+(slider.classList.contains('setWidth-normal')?100:0); 174 content.style.height=oldH; 175 } 176 return Math.max(100,Math.ceil(imageH),Math.ceil(contentH)); 177 } 178 function capturedHeight(){ 179 const pairs=Object.keys(slider.dataset).filter(k=>/^fhHeight-?\d+$/.test(k)).map(k=>[parseInt(k.replace(/\D/g,''),10),parseFloat(slider.dataset[k])]).filter(p=>Number.isFinite(p[0])&&Number.isFinite(p[1])).sort((a,b)=>a[0]-b[0]); 180 if(!pairs.length)return null; 181 const w=innerWidth; 182 const exact=pairs.find(p=>Math.abs(p[0]-w)<1);if(exact)return exact[1]; 183 if(w<=pairs[0][0])return pairs[0][1]; 184 if(w>=pairs[pairs.length-1][0])return pairs[pairs.length-1][1]; 185 for(let i=1;i<pairs.length;i++)if(w<pairs[i][0]){ 186 const [w0,h0]=pairs[i-1],[w1,h1]=pairs[i],t=(w-w0)/(w1-w0); 187 return h0+(h1-h0)*t; 188 } 189 return null; 190 } 191 function size(){ 192 const h=Math.max(100,Math.round(capturedHeight()||naturalHeight(slides[index]))); 193 slider.style.setProperty('height',h+'px','important'); 194 viewport.style.setProperty('height',h+'px','important'); 195 ul.style.setProperty('height',h+'px','important'); 196 slides.forEach(s=>{ 197 s.style.setProperty('height',h+'px','important'); 198 const image=q('.booImage',s),img=q('.booImage img',s); 199 image?.style.setProperty('height',h+'px','important'); 200 if(img){ 201 img.style.setProperty('width','100%','important'); 202 img.style.setProperty('height','100%','important'); 203 img.style.setProperty('max-width','none','important'); 204 img.style.setProperty('object-fit','cover','important'); 205 img.style.setProperty('object-position','center center','important'); 206 } 207 }); 208 } 209 function show(i){ 210 index=(i+slides.length)%slides.length; 211 ul.style.transform=`translate3d(${-index*100}%,0,0)`; 212 slides.forEach((s,j)=>s.classList.toggle('flex-active-slide',j===index)); 213 dots.forEach((d,j)=>d.classList.toggle('flex-active',j===index)); 214 requestAnimationFrame(size); 215 } 216 prev&&prev.addEventListener('click',e=>{e.preventDefault();show(index-1)}); 217 next&&next.addEventListener('click',e=>{e.preventDefault();show(index+1)}); 218 dots.forEach((d,j)=>d.addEventListener('click',e=>{e.preventDefault();show(j)})); 219 qa('img',slider).forEach(img=>{if(!img.complete)img.addEventListener('load',size,{once:true});}); 220 addEventListener('resize',()=>show(index)); 221 show(index); 222}); 223 224/* ---------- WAddons/Owl local runtime ---------- */ 225qa('.waddons_carousel_slider').forEach(car=>{ 226 const outer=q('.waddons-car-wrapper-outer',car),track=q('.waddons-car-wrapper',car);if(!outer||!track)return; 227 const items=qa(':scope > .waddons-car-element',track);if(!items.length)return; 228 const prev=q('.owl-prev',car),next=q('.owl-next',car),controls=q('.owl-controls',car); 229 let index=0,itemW=0,visible=1,timer=null; 230 231 /* The captured PlatformElementSettings are embedded as data attributes by the 232 reconstruction pass. These are the original Owl Carousel responsive counts. */ 233 const num=(name,fallback=1)=>Math.max(1,parseInt(car.dataset[name]||fallback,10)||fallback); 234 const flag=(name)=>String(car.dataset[name]||'false')==='true'; 235 const px=(name)=>{const v=parseFloat(car.dataset[name]||'');return Number.isFinite(v)&&v>0?v:null}; 236 function evidenceGeometry(){ 237 const w=innerWidth; 238 let item=null,canvas=null,controls=null,visibleCount=null; 239 if(w>=993){ 240 /* User-directed refinement: keep the audited number of visible cards, but 241 let that set span the actual browser width instead of the legacy 1024px 242 Weebly canvas. 249â4-up, 341/338â3-up, 507â2-up, 169â6-up. */ 243 const sourceItem=px('fhDesktopItem')||px('fh1280Item'); 244 const inferred=sourceItem?Math.max(1,Math.round(1024/sourceItem)):num('fhItemsLarge',4); 245 visibleCount=Math.max(1,Math.min(items.length,inferred)); 246 canvas=Math.max(1,document.documentElement.clientWidth||w); 247 item=canvas/visibleCount; 248 controls=w>
248=1280?(car.dataset.fh1280Controls||car.dataset.fhDesktopControls):(car.dataset.fhDesktopControls||car.dataset.fh1280Controls); 249 } else if(w>=768){ 250 item=px('fhTabletItem')||px('fhDesktopItem')||px('fhMobileItem');canvas=Math.min(698,Math.max(1,outer.clientWidth));controls=car.dataset.fhTabletControls||car.dataset.fhMobileControls; 251 } else if(w<=375){ 252 item=px('fh375Item')||px('fhMobileItem')||px('fhDesktopItem');canvas=Math.min(306,Math.max(1,outer.clientWidth));controls=car.dataset.fh375Controls||car.dataset.fhMobileControls; 253 } else { 254 item=px('fhMobileItem')||px('fh375Item')||px('fhDesktopItem');canvas=Math.min(320,Math.max(1,outer.clientWidth));controls=car.dataset.fhMobileControls||car.dataset.fh375Controls; 255 } 256 if(!item){ 257 const count=w>1000?num('fhItemsLarge',4):w>768?num('fhItemsTablets',2):num('fhItemsPhone',1); 258 item=Math.max(1,Math.floor((outer.clientWidth||canvas||320)/count)); 259 } 260 if(w>=993){ 261 const visible=visibleCount||Math.max(1,Math.min(items.length,Math.round(canvas/item)||1)); 262 return {item,visible,canvas,controls}; 263 } 264 canvas=Math.min(canvas||outer.clientWidth,item*items.length,outer.parentElement?.clientWidth||Infinity); 265 const visible=Math.max(1,Math.min(items.length,Math.round(canvas/item)||1)); 266 return {item,visible,canvas:item*visible,controls}; 267 } 268 269 /* The lazy audit preserved a builder-runtime artefact where later cards sometimes 270 inherited the first card's CSS background. The source upload image nested inside 271 each card is the authoritative, card-specific binary. Re-appl
271y it to the visible 272 background window exactly as the live add-on does after initialization. */ 273 items.forEach(item=>{ 274 const bg=q('.wad_full_width_element.use_fw_bg_img',item); 275 const src=q('.upload_img_bg_wad_fw_element img',item); 276 if(bg&&src){ 277 const url=src.getAttribute('src')||src.currentSrc; 278 if(url)bg.style.setProperty('background-image',`url("${url}")`,'important'); 279 } 280 }); 281 282 function maxIndex(){return Math.max(0,items.length-visible)} 283 let evidenceControls=null; 284 function syncControls(){ 285 const canMove=items.length>visible; 286 const hideArrows=flag('fhHideArrows'); 287 const hideDots=flag('fhHideDots'); 288 const auditAllows=evidenceControls!=='none'; 289 if(controls)controls.style.setProperty('display',canMove&&auditAllows&&(!hideArrows||!hideDots)?'block':'none','important'); 290 const buttons=q('.owl-buttons',car); 291 if(buttons)buttons.style.setProperty('display',canMove&&auditAllows&&!hideArrows?'block':'none','important'); 292 const pagination=q('.owl-pagination',car); 293 if(pagination)pagination.style.setProperty('display',canMove&&auditAllows&&!hideDots?'block':'none','important'); 294 prev?.classList.toggle('disabled',index<=0); 295 next?.classList.toggle('disabled',index>=maxIndex()); 296 } 297 function place(animate=true){ 298 track.style.transition=animate?'transform .55s ease':'none'; 299 track.style.transform=`translate3d(${-index*itemW}px,0,0)`; 300 syncControls(); 301 } 302 function sync(){ 303 const g=evidenceGeometry(); 304 visible=g.visible;itemW=g.item;evidenceControls=g.controls; 305 outer.style.setProperty('max-width',Math.round(g.canvas)+'px','important'); 306 outer.style.setProperty('width',innerWidth>=993?Math.round(g.canvas)+'px':'100%','important'); 307 car.style.setProperty('--fh-item-width',itemW+'px'); 308 index=clamp(index,0,maxIndex()); 309 place(false); 310 requestAnimationFrame(()=>{track.style.transition='transform .55s ease';}); 311 restart(); 312 } 313 function go(delta){ 314 if(items.length<=visible)return; 315 index=clamp(index+delta,0,maxIndex()); 316 place(true); 317 } 318 prev&&prev.addEventListener('click',e=>{e.preventDefault();go(-1);restart()}); 319 next&&next.addEventListener('click',e=>{e.preventDefault();go(1);restart()}); 320 321 function restart(){ 322 clearInterval(timer);timer=null; 323 if(!flag('fhAutoplay')||items.length<=visible)return; 324 const interval=Math.max(1000,(parseFloat(car.dataset.fhInterval||'3')||3)*1000); 325 timer=setInterval(()=>{ 326 index=index>=maxIndex()?0:index+1; 327 place(true); 328 },interval); 329 } 330 if(flag('fhStopOnHover')){ 331 car.addEventListener('mouseenter',()=>{clearInterval(timer);timer=null}); 332 car.addEventListener('mouseleave',restart); 333 } 334 addEventListener('resize',sync); 335 if('ResizeObserver' in window)new ResizeObserver(sync).observe(outer); 336 sync(); 337}); 338 339/* ---------- Classic Weebly thumbnail slideshow local runtime ---------- */ 340qa('.wslide').forEach(root=>{ 341 const slides=qa('.wslide-slides > .wslide-slide',root),links=qa('.wslide-links .wslide-link',root),linksBox=q('.wslide-links',root),linksInner=q('.wslide-links-inner',root); 342 if(!slides.length)return; 343 let index=slides.findIndex(s=>s.style.display!=='none');if(index<0)index=0; 344 let timer=null; 345 function size(){ 346 const content=q('.wslide-content',root);if(!content)return; 347 const h=Math.round(content.clientWidth*9/16); 348 content.style.setProperty('height',h+'px','important'); 349 if(linksBox)linksBox.style.setProperty('height',h+'px','important'); 350 } 351 function keepLinkVisible(){ 352 if(!linksBox||!linksInner||!links[index])return; 353 const a=links[index];const top=a.offsetTop,bottom=top+a.offsetHeight; 354 const current=-parseFloat(linksInner.style.top||'0')||0; 355 let nextTop=current; 356 if(top<current)nextTop=top;else if(bottom>current+linksBox.clientHeight)nextTop=bottom-linksBox.clientHeight; 357 linksInner.style.top=-Math.max(0,nextTop)+'px'; 358 } 359 function show(i){ 360 index=(i+slides.length)%slides.length; 361 slides.forEach((s,j)=>s.style.display=j===index?'block':'none'); 362 links.forEach((a,j)=>a.classList.toggle('wslide-link-active',j===index));
363 keepLinkVisible(); 364 } 365 links.forEach((a,j)=>a.addEventListener('click',e=>{e.preventDefault();show(j);restart();})); 366 q('.wslide-prev',root)?.addEventListener('click',e=>{e.preventDefault();show(index-1);restart();}); 367 q('.wslide-next',root)?.addEventListener('click',e=>{e.preventDefault();show(index+1);restart();}); 368 function restart(){clearInterval(timer);timer=setInterval(()=>show(index+1),5000);} 369 root.addEventListener('mouseenter',()=>clearInterval(timer));root.addEventListener('mouseleave',restart); 370 addEventListener('resize',()=>{size();keepLinkVisible();}); 371 size();show(index);restart(); 372}); 373 374 375/* ---------- Compact tabbed results runtime (2023 archive) ---------- */ 376qa('.tabbed-box').forEach(box=>{ 377 const tabs=qa('.tabbed-box-tab',box),contents=qa('.tabbed-box-content',box);if(!tabs.length||!contents.length)return; 378 function show(tab){ 379 const rel=tab.getAttribute('rel')||''; 380 tabs.forEach(t=>t.classList.toggle('active',t===tab)); 381 contents.forEach(c=>{const on=c.classList.contains(rel);c.style.display=on?'block':'none';c.setAttribute('aria-hidden',String(!on));}); 382 tab.setAttribute('aria-selected','true');
383 tabs.forEach(t=>{if(t!==tab)t.setAttribute('aria-selected','false')}); 384 const rail=tab.parentElement;if(rail){const left=tab.offsetLeft-Math.max(0,(rail.clientWidth-tab.offsetWidth)/2);rail.scrollTo?.({left:Math.max(0,left),behavior:'smooth'});} 385 } 386 tabs.forEach(tab=>{tab.setAttribute('role','tab');tab.addEventListener('click',e=>{e.preventDefault();show(tab)});}); 387 const active=tabs.find(t=>t.classList.contains('active'))||tabs[0];show(active); 388}); 389 390/* ---------- Consistent footer signature ---------- */ 391function enhanceFooter(){ 392 let wrap=q('.footer-wrap'); 393 if(!wrap){wrap=document.createElement('div');wrap.className='footer-wrap';const mobile=q('.mobile-nav');(mobile||document.body.lastChild)?.parentNode?.insertBefore(wrap,mobile||null);} 394 wrap.classList.add('fh-footer-enhanced'); 395 wrap.innerHTML=`<div class="container"><footer class="fh-signature-footer" aria-label="FilmHaus footer"> 396 <div class="fh-signature-top"> 397 <a class="fh-signature-logo" href="/" aria-label="FilmHaus home"><img src="/assets/source-filmhaus/uploads/1/2/9/9/129999471/published/2022-filmhaus-logo2__q-3f45dcf0.png" alt="FilmHaus"></a> 398 <div class="fh-signature-tagline">Home of Hidden Cinematic Treasures</div> 399 <nav class="fh-signature-links" aria-label="Legal"><a href="/cookies-policy.html">Cookies</a><a href="/legal-notice.html">Legal Notice</a><a href="/privacy-policy.html">Privacy</a><a href="/intellectual-property-policy.html">Content Rights</a></nav> 400 </div> 401 <div class="fh-signature-rule"></div> 402 <div class="fh-signature-bottom"><strong>FILMHAUS · DIGITAL BERLIN · EST. 2020</strong><span>© 2020â2026 FilmHaus · FILMFINITY SL · All Rights Reserved</span></div> 403 </footer></div>`; 404} 405enhanceFooter(); 406 407if(['/cookies-policy.html','/legal-notice.html','/privacy-policy.html','/intellectual-property-policy.html'].includes(document.body.dataset.fhRoute||'')){ 408 document.body.classList.add('fh-legal-route'); 409 qa('[class*=\"elfsight-app-\"],.eui-tooltip,#newsvd_popupMenu,#newsvdPrice,#newvtPopupMenu').forEach(el=>el.remove()); 410 qa('.fh-legal-route .main-wrap a[href]').forEach(a=>{ 411 const href=a.getAttribute('href')||''; 412 if(/^https?:/i.test(href)){a.target='_blank';a.rel='noopener noreferrer';} 413 }); 414} 415 416/* v5 final navigation safety: native destinations remain independently usable. */ 417const fhDesktop=q('.desktop-nav'); 418if(fhDesktop){ 419 const destinations={home:'/',about:'/about.html',news:'https://www.moviemaker.com/the-filmhaus-evolution-a-new-jury-and-a-vision-renewed/',results:'/2025-winners-nominees.html',showcase:'/2025-showcase.html',submit:'https://filmfreeway.com/filmhaus',contact:'mailto:[email protected]'}; 420 qa(':scope > ul > li',fhDesktop).forEach(li=>{ 421 const a=directChild(li,'a.wsite-menu-item');if(!a)return; 422 const label=labelOf(a);if(destinations[label])a.href=destinations[label]; 423 a.style.pointerEvents='auto'; 424 }); 425} 426 427syncAffix(); 428})(); 429 430/* ========================================================================== */ 431/* FilmHaus v6 â final archive/navigation refinement */ 432/* ========================================================================== */ 433(()=>{ 434'use strict'; 435const q=(s,r=document)=>r.querySelector(s), qa=(s,r=document)=>Array.from(r.querySelectorAll(s)); 436const direct=(el,sel)=>Array.from(el?.children||[]).find(x=>x.matches(sel)); 437const label=a=>(a?.textContent||'').replace(/\s+/g,' ').trim().toLowerCase(); 438 439/* Rebuild only the two archive dropdowns. This deliberately supersedes the 440 deeply-nested legacy Weebly menu with the broad Results panel visible in the 441 supplied reference screenshots. */ 442const desktop=q('.desktop-nav'); 443if(desktop){ 444 const topItems=qa(':scope > ul > li',desktop); 445 const resultsLi=topItems.find(li=>label(direct(li,'a.wsite-menu-item'))==='results'); 446 const showcaseLi=topItems.find(li=>label(direct(li,'a.wsite-menu-item'))==='showcase'); 447 448 if(resultsLi){ 449 direct(resultsLi,'.fh-desktop-menu')?.remove(); 450 const mega=document.createElement('div'); 451 mega.className='fh-desktop-menu fh-results-mega'; 452 mega.setAttribute('role','menu'); 453 mega.innerHTML=`<div class="fh-results-grid"> 454 <section class="fh-results-group"><h3>2025</h3><a href="/2025-winners-nominees.html">29-Oct · Winners & Nominees</a><a href="/2025-semifinals.html">29-Oct · Semi-Finalists</a></section> 455 <section class="fh-results-group"><h3>2024</h3><a href="/2024-3-results.html">31-Oct Finalists</a><a href="/2024-2-results-winners-nominees.html">12-Jun · Winners & Nominees</a><a href="/2024-2-results-semi-finalists.html">12-Jun · Semi-Finalists</a><a href="/2024-1-results-winners-nominees.html">4-Mar · Winners & Nominees</a><a href="/2024-1-results-semi-finalists.html">4-Mar · Semi-Finalists</a></section> 456 <section class="fh-results-group"><h3>2023</h3><a href="/2023-2-results-winners-nominees.html">27-Oct · Winners & Nominees</a><a href="/2023-2-results-semifinalists.html">27-Oct · Semi-Finalists</a><a href="/2023-1-results-winners-nominees.html">24-Apr · Winners & Nominees</a><a href="/2023-1-results-finalists.html">24-Apr · Other Finalists</a><a href="/2023-1-results-semifinalists.html">24-Apr · Semi-Finalists</a></section> 457 <section class="fh-results-group"><h3>2022</h3><a href="/2022-results.html">Winners & Nominees</a><a href="/2022-finals.html">Other Finalists</a></section> 458 <section class="fh-results-group"><h3>2021</h3><a href="/2021.html">Results Archive</a></section> 459 <section class="fh-results-group"><h3>2020</h3><a href="/2020.html">Results Archive</a></section> 460 </div>`; 461 resultsLi.appendChild(mega); 462 } 463 464 if(showcaseLi){ 465 direct(showcaseLi,'.fh-desktop-menu')?.remove(); 466 const menu=document.createElement('div'); 467 menu.className='fh-desktop-menu fh-showcase-menu'; 468 menu.setAttribute('role','menu'); 469 menu.innerHTML=`<a href="/2025-showcase.html">2025 (Closed)</a><a href="/2024-showcase.html">2024 (Closed)</a><a href="/2023-showcase.html">2023 (Closed)</a><a href="/2022-showcase.html">2022 (Closed)</a>`; 470 showcaseLi.appendChild(menu); 471 } 472 473 const syncMenuTop=()=>{ 474 const header=q('.dusk-header'); 475 if(!header)return; 476 const bottom=Math.max(0,Math.round(header.getBoundingClientRect().bottom)); 477 document.documentElement.style.setProperty('--fh-nav-bottom',bottom+'px'); 478 }; 479 syncMenuTop(); 480 addEventListener('scroll',syncMenuTop,{passive:true}); 481 addEventListener('resize',syncMenuTop); 482} 483 484/* Keep the Results year neutral; the closed state belongs to Showcase. */ 485const mobile=q('.mobile-nav'); 486if(mobile){ 487 qa(':scope > ul > li',mobile).forEach(li=>{ 488 const top=direct(li,'a.wsite-menu-item'); 489 const topLabel=label(top); 490 const wrap=direct(li,'.wsite-menu-wrap'); 491 if(!wrap)return; 492 if(topLabel==='results'){ 493 const y=qa(':scope > ul > li',wrap).find(yearLi=>label(direct(yearLi,'a.wsite-menu-subitem')).startsWith('2025')); 494 const title=y&&q('.wsite-menu-title',y); if(title)title.textContent='2025'; 495 } 496 if(topLabel==='showcase'){ 497 const y=qa(':scope > ul > li',wrap).find(yearLi=>label(direct(yearLi,'a.wsite-menu-subitem')).startsWith('2025')); 498 const title=y&&q('.wsite-menu-title',y); if(title)title.textContent='2025 (Closed)'; 499 } 500 }); 501} 502 503/* The six empty 31-Oct-2024 builder carousels contain literal template tokens 504 rather than content. Remove only those broken widgets; the page layout itself 505 is intentionally left untouched. */ 506if((document.body.dataset.fhRoute||'')==='/2024-3-results.html'){ 507 qa('.inner_content_car').forEach(inner=>{ 508 if(!/\{slide_0:content\}/i.test(inner.textContent||''))return; 509 const platform=inner.closest('.platform-element-contents'); 510 if(platform)platform.remove(); 511 else inner.closest('.waddons_carousel_slider')?.remove(); 512 }); 513} 514
515/* Consistent archive presentation begins with the 12-Jun-2024 results and runs 516 backward. 2025, 31-Oct-2024 and every Showcase route are excluded by design. */ 517const legacyResults=new Set([ 518 '/2024-2-results-winners-nominees.html','/2024-2-results-semi-finalists.html', 519 '/2024-1-results-winners-nominees.html','/2024-1-results-semi-finalists.html', 520 '/2023-2-results-winners-nominees.html','/2023-2-results-semifinalists.html', 521 '/2023-1-results-winners-nominees.html','/2023-1-results-finalists.html','/2023-1-results-semifinalists.html', 522 '/2022-results.html','/2022-finals.html','/2021.html','/2020.html' 523]); 524if(legacyResults.has(document.body.dataset.fhRoute||''))document.body.classList.add('fh-unified-results'); 525})(); 526 527 528/* FilmHaus v8 â normalize the selected archive pages to the 2022 result shell. */ 529(()=>{ 530 const routes=new Set([ 531 '/2024-2-results-winners-nominees.html','/2024-2-results-semi-finalists.html', 532 '/2024-1-results-winners-nominees.html','/2024-1-results-semi-finalists.html', 533 '/2023-2-results-winners-nominees.html','/2023-2-results-semifinalists.html', 534 '/2023-1-results-winners-nominees.html','/2023-1-results-finalists.html','/2023-1-results-semifinalists.html', 535 '/2022-finals.html' 536 ]); 537 if(!routes.has(document.body.dataset.fhRoute||''))return; 538 document.body.classList.add('fh-2022-layout'); 539 540 // Keep the top result slideshow proportional when the viewport changes. 541 const resizeSlides=()=>{ 542 document.querySelectorAll('#wsite-content .wslide').forEach(root=>{ 543 const content=root.querySelector('.wslide-content'); 544 if(!content)return; 545 const h=Math.round(content.clientWidth*9/16); 546 content.style.setProperty('height',h+'px','important'); 547 }); 548 }; 549 resizeSlides(); 550 addEventListener('resize',resizeSlides,{passive:true}); 551})();
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.