1document.addEventListener('DOMContentLoaded',()=>{ 2 const toggle=document.querySelector('.ffe-menu-toggle'), nav=document.querySelector('.ffe-nav'); 3 if(toggle&&nav) toggle.addEventListener('click',()=>nav.classList.toggle('open')); 4 5 const hero=document.getElementById('ffe-search-now'); 6 if(!hero) return; 7 8 const tabs=hero.querySelectorAll('.ffe-tab'); 9 const panels=hero.querySelectorAll('.ffe-tab-panel'); 10 const badge=document.getElementById('ffe-search-badge'); 11 const intro=document.getElementById('ffe-search-intro'); 12 13 function loadHotelWidget(){ 14 const holder=document.getElementById('ffe-hero-hotel-widget'); 15 if(!holder || holder.dataset.loaded==='1') return; 16 17 const src=holder.dataset.widgetSrc; 18 if(!src) return; 19 20 holder.dataset.loaded='1'; 21 holder.innerHTML=''; 22 23 const script=document.createElement('script'); 24 script.async=true; 25 script.src=src; 26 script.charset='utf-8'; 27 script.onerror=function(){ 28 holder.dataset.loaded='0'; 29 holder.innerHTML='<div class="ffe-widget-error"><strong>Hotel search could not load.</strong><span>Please refresh the page and try again.</span></div>'; 30 }; 31 holder.appendChild(script); 32 } 33
34 tabs.forEach(btn=>btn.addEventListener('click',()=>{ 35 const type=btn.dataset.tab; 36 37 tabs.forEach(x=>x.classList.remove('active')); 38 panels.forEach(x=>x.classList.remove('active')); 39 btn.classList.add('active'); 40 41 const panel=document.getElementById('ffe-tab-'+type); 42 if(panel) panel.classList.add('active'); 43 44 if(type==='hotels'){ 45 if(badge) badge.textContent='⣠Find Your Perfect Hotel'; 46 if(intro) intro.textContent='Compare accommodation options and hotel deals for your next stay.'; 47 /* Wait until the panel is visible before Travelpayouts calculates size. */ 48 window.requestAnimationFrame(()=>window.setTimeout(loadHotelWidget,80)); 49 }else{ 50 if(badge) badge.textContent='â Find Your Perfect Flight'; 51 if(intro) intro.textContent='Compare fares from leading airlines and booking sites.'; 52 } 53 })); 54}); 55 56document.addEventListener('DOMContentLoaded',()=>{ 57 const select=document.getElementById('ffe-departure-select'); 58 const link=document.getElementById('ffe-departure-link'); 59 const title=document.getElementById('ffe-deals-title'); 60 if(select&&link&&title){ 61 const updateDeparture=()=>{ 62 const opt=select.options[select.selectedIndex]; 63 const city=opt.text.split(' (')[0]; 64 const slug=select.value; 65 link.href=(window.ffeHomeUrl||'/')+'cheap-flights-from-'+slug+'/'; 66 link.textContent='See deals from '+city+' â'; 67 title.textContent='Popular flights from '+city; 68 document.querySelectorAll('.ffe-deal-origin').forEach(el=>el.textContent='From '+city); 69 try{localStorage.setItem('ffeDeparture',slug)}catch(e){} 70 }; 71 try{const saved=localStorage.getItem('ffeDeparture');if(saved&&select.querySelector('option[value="'+saved+'"]')) select.value=saved;}catch(e){} 72 select.addEventListener('change',updateDeparture);updateDeparture(); 73 } 74}); 75 76document.addEventListener('DOMContentLoaded',()=>{ 77 const countries={ 78 GB:{name:'United Kingdom',currency:'GBP',language:'en',origin:'london',city:'London',popular:['Paris','Dubai','New York','Tokyo']}, 79 US:{name:'United States',currency:'USD',language:'en',origin:'new-york',city:'New York',popular:['London','Cancun','Tokyo','Paris']}, 80 CA:{name:'Canada',currency:'CAD',language:'en',origin:'toronto',city:'Toronto',popular:['New York','London','Cancun','Paris']}, 81 AU:{name:'Australia',currency:'AUD',language:'en',origin:'sydney',city:'Sydney',popular:['Bali','Tokyo','Singapore','Auckland']}, 82 NZ:{name:'New Zealand',currency:'NZD',language:'en',origin:'auckland',city:'Auckland',popular:['Sydney','Bali','Tokyo','Singapore']}, 83 SG:{name:'Singapore',currency:'SGD',language:'en',origin:'singapore',city:'Singapore',popular:['Bali','Tokyo','Bangkok','Sydney']}, 84 AE:{name:'United Arab Emirates',currency:'AED',language:'en',origin:'dubai',city:'Dubai',popular:['London','Paris','Bangkok','Singapore']}, 85 JP:{name:'Japan',currency:'JPY',language:'ja',origin:'tokyo',city:'Tokyo',popular:['Singapore','Bali','Sydney','Honolulu']}, 86 IN:{name:'India',currency:'INR',language:'en',origin:'delhi',city:'Delhi',popular:['Dubai','Bangkok','Singapore','London']}, 87 DE:{name:'Germany',currency:'EUR',language:'de',origin:'frankfurt',city:'Frankfurt',popular:['London','Paris','Rome','Dubai']}, 88 FR:{name:'France',currency:'EUR',language:'fr',origin:'paris',city:'Paris',popular:['London','Rome','New York','Dubai']}, 89 ES:{name:'Spain',currency:'EUR',language:'es',origin:'madrid',city:'Madrid',popular:['London','Paris','Rome','New York']}, 90 IT:{name:'Italy',currency:'EUR',language:'it',origin:'rome',city:'Rome',popular:['Paris','London','Barcelona','New York']}, 91 NL:{name:'Netherlands',currency:'EUR',language:'en',origin:'amsterdam',city:'Amsterdam',popular:['London','Paris','Rome','New York']}, 92 ZA:{name:'South Africa',currency:'ZAR',language:'en',origin:'cape-town',city:'Cape Town',popular:['Dubai','London','Singapore','Paris']}, 93 MX:{name:'Mexico',currency:'MXN',language:'es',origin:'mexico-city',city:'Mexico City',popular:['Cancun','New York','Los Angeles','Paris']},
94 BR:{name:'Brazil',currency:'BRL',language:'pt',origin:'sao-paulo',city:'São Paulo',popular:['New York','Paris','London','Cancun']}, 95 TR:{name:'Türkiye',currency:'TRY',language:'en',origin:'istanbul',city:'Istanbul',popular:['London','Paris','Dubai','Rome']}, 96 HK:{name:'Hong Kong',currency:'HKD',language:'en',origin:'hong-kong',city:'Hong Kong',popular:['Tokyo','Singapore','Bali','Bangkok']}, 97 KR:{name:'South Korea',currency:'KRW',language:'en',origin:'seoul',city:'Seoul',popular:['Tokyo','Singapore','Bali','Los Angeles']}, 98 MY:{name:'Malaysia',currency:'MYR',language:'en',origin:'kuala-lumpur',city:'Kuala Lumpur',popular:['Singapore','Bali','Bangkok','Tokyo']}, 99 ID:{name:'Indonesia',currency:'IDR',language:'en',origin:'jakarta',city:'Jakarta',popular:['Bali','Singapore','Tokyo','Sydney']}, 100 PH:{name:'Philippines',currency:'PHP',language:'en',origin:'manila',city:'Manila',popular:['Tokyo','Singapore','Bali','Sydney']} 101 }; 102 const localeCountry={en:'GB','en-US':'US','en-CA':'CA','en-AU':'AU','en-NZ':'NZ','en-SG':'SG','ja-JP':'JP','de-DE':'DE','fr-FR':'FR','es-ES':'ES','it-IT':'IT','pt-BR':'BR','es-MX':'MX','ko-KR':'KR'}; 103 const languageNames={en:'English',es:'Español',fr:'Français',de:'Deutsch',it:'Italiano',pt:'Português',ja:'æ¥æ¬èª'}; 104 const slugs={'Bali':'bali','Tokyo':'tokyo','Dubai':'dubai','New York':'new-york','Paris':'paris','London':'london','Cancun':'cancun','Singapore':'singapore','Auckland':'auckland','Sydney':'sydney','Bangkok':'bangkok','Rome':'rome','Barcelona':'barcelona','Honolulu':'honolulu','Los Angeles':'los-angeles'}; 105 const countrySel=document.getElementById('ffe-country-select'), currencySel=document.getElementById('ffe-currency-select'), languageSel=document.getElementById('ffe-language-select'), depSel=document.getElementById('ffe-departure-select'); 106 if(!countrySel||!currencySel||!languageSel) return; 107 let saved={};try{saved=JSON.parse(localStorage.getItem('ffeLocale')||'{}')}catch(e){} 108 let inferred=localeCountry[navigator.language]||localeCountry[(navigator.languages||[])[0]]||((navigator.language||'').endsWith('-AU')?'AU':null)||window.ffeLocaleDefaults?.country||'GB'; 109 let cc=saved.country&&countries[saved.country]?saved.country:(countries[inferred]?inferred:'GB'); 110 const apply=(manual=false)=>{ 111 const c=countries[cc]||countries.GB; 112 countrySel.value=cc; 113 if(!manual||!currencySel.dataset.touched) currencySel.value=saved.currency||c.currency; 114 if(!manual||!languageSel.dataset.touched) languageSel.value=saved.language||c.language; 115 const currency=currencySel.value, lang=languageSel.value; 116 document.documentElement.lang=lang; 117 const label=document.getElementById('ffe-localised-label'),sub=document.getElementById('ffe-localised-sub'),sum=document.getElementById('ffe-region-summary'),rc=document.getElementById('ffe-region-country'),rCur=document.getElementById('ffe-region-currency'),rLang=document.getElementById('ffe-region-language'); 118 if(label) label.textContent='Travel search for '+c.name; 119 if(sub) sub.textContent='Suggested departure: '+c.city+' · '+currency; 120 if(sum) sum.textContent='Popular flight ideas from '+c.city; 121 if(rc) rc.textContent='Country: '+c.name; 122 if(rCur) rCur.textContent='Currency: '+currency; 123 if(rLang) rLang.textContent='Search language: '+(languageNames[lang]||lang.toUpperCase()); 124 if(depSel){const opt=depSel.querySelector('option[value="'+c.origin+'"]');if(opt){depSel.value=c.origin;depSel.dispatchEvent(new Event('change'));}} 125 const cards=[...document.querySelectorAll('.ffe-personalised-deal')]; c.popular.forEach((name,i)=>{const card=cards[i]; if(!card)return; const strong=card.querySelector('strong'); if(strong)strong.textContent=name; const slug=slugs[name]; if(slug){card.dataset.dest=slug; card.href=(window.ffeHomeUrl||'/')+'cheap-flights-to-'+slug+'/';}}); 126 try{localStorage.setItem('ffeLocale',JSON.stringify({country:cc,currency,language:lang}))}catch(e){} 127 document.cookie='ffe_country='+encodeURIComponent(cc)+';path=/;max-age=31536000;SameSite=Lax'; 128 document.cookie='ffe_currency='+encodeURIComponent(currency)+';path=/;max-age=31536000;SameSite=Lax'; 129 document.cookie='ffe_language='+encodeURIComponent(lang)+';path=/;max-age=31536000;SameSite=Lax'; 130 }; 131 countrySel.addEventListener('change',()=>{cc=countrySel.value;saved={};currencySel.dataset.touched='';languageSel.dataset.touched='';apply(false)}); 132 currencySel.addEventListener('change',()=>{currencySel.dataset.touched='1';apply(true)}); 133 languageSel.addEventListener('change',()=>{languageSel.dataset.touched='1';apply(true)}); 134 apply(false); 135});
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.