PageSourceSearch

https://www.fashion-insider.de/wp-content/cache/min/1/wp-content/p…/public/route-render.js?ver=1789793484

js fashion-insider.de collected 2026-10-02 11:41:46 UTC 10,822 bytes, 42 lines download raw bytes

1(()=>{'use strict';const LEAFLET_CSS=['https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.css','https://unpkg.com/[email protected]/dist/leaflet.css','https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.css',];const LEAFLET_JS=['https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.js','https://unpkg.com/[email protected]/dist/leaflet.js','https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.js',];const AIR_SOURCES=['https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat','https://cdn.jsdelivr.net/gh/jpatokal/openflights@master/data/airports.dat','https://raw.githubusercontent.com/davidmegginson/ourairports-data/main/airports.csv','https://cdn.jsdelivr.net/gh/davidmegginson/ourairports-data@main/airports.csv',];const NOMINATIM_ENDPOINT='https://nominatim.openstreetmap.org/search';function loadStyleOnce(href,ms=8000){return new Promise((resolve,reject)=>{if([...document.styleSheets].some(s=>s.href&&s.href.includes('leaflet')))
2return resolve();const l=document.createElement('link');l.rel='stylesheet';l.href=href;l.crossOrigin='anonymous';const t=setTimeout(()=>reject(new Error('style timeout '+href)),ms);l.onload=()=>{clearTimeout(t);resolve()};l.onerror=()=>{clearTimeout(t);reject(new Error('style error '+href))};document.head.appendChild(l)})}
3function loadScriptOnce(src,ms=8000){return new Promise((resolve,reject)=>{if(window.L)return resolve();const s=document.createElement('script');s.src=src;s.defer=!0;s.crossOrigin='anonymous';const t=setTimeout(()=>reject(new Error('script timeout '+src)),ms);s.onload=()=>{clearTimeout(t);resolve()};s.onerror=()=>{clearTimeout(t);reject(new Error('script error '+src))};document.head.appendChild(s)})}
4async function loadAny(urls,loader){for(const u of urls){try{await loader(u);return!0}catch(e){}}
5throw new Error('Alle Quellen fehlgeschlagen:\n'+urls.join('\n'))}
6const sleep=ms=>new Promise(r=>setTimeout(r,ms));const clean=v=>String(v||'').trim();const splitCSV=s=>clean(s).split(',').map(x=>x.trim()).filter(Boolean);function tryCoords(term){const m=String(term||'').trim().match(/^\s*(-?\d{1,3}(?:\.\d+)?)\s*[,;]\s*(-?\d{1,3}(?:\.\d+)?)\s*$/);if(!m)return null;const lat=+m[1],lon=+m[2];if(Math.abs(lat)>90||Math.abs(lon)>180)return null;return{lat,lon,name:term}}
7const LS_KEY_AIR='pk_air_iata_v5';const LS_KEY_CITY='pk_city_geo_v1';const LS_TTL_MS=1000*60*60*24*60;function lsRead(key){try{const obj=JSON.parse(localStorage.getItem(key)||'{}');if(!obj.t||(Date.now()-obj.t)>LS_TTL_MS)return{t:Date.now(),data:{}};return obj}catch(e){return{t:Date.now(),data:{}}}}
8function lsWrite(key,data){try{localStorage.setItem(key,JSON.stringify({t:Date.now(),data}))}catch(e){}}
9async function fetchText(url,ms=12000){const ctrl=new AbortController();const to=setTimeout(()=>ctrl.abort(),ms);try{const r=await fetch(url,{signal:ctrl.signal,mode:'cors',cache:'no-store'});if(!r.ok)throw new Error('HTTP '+r.status);return await r.text()}finally{clearTimeout(to)}}
10async function fetchJSON(url,ms=12000){const ctrl=new AbortController();const to=setTimeout(()=>ctrl.abort(),ms);try{const r=await fetch(url,{signal:ctrl.signal,mode:'cors',cache:'no-store',headers:{'Accept':'application/json','User-Agent':'preis-king-route/1.0 (+https://www.preis-king.com)'}});if(!r.ok)throw new Error('HTTP '+r.status);return await r.json()}finally{clearTimeout(to)}}
11function parseOpenFlights(text,wantedSet){const out={};const lines=text.split(/\r?\n/);for(const line of lines){if(!line)continue;const cells=[];let cur='',inQ=!1;for(let i=0;i<line.length;i++){const ch=line[i];if(ch==='"'){inQ=!inQ;continue}
12if(ch===','&&!inQ){cells.push(cur);cur='';continue}
13cur+=ch}
14cells.push(cur);if(cells.length<8)continue;const iata=clean(cells[4]);if(!iata||iata==='\\N')continue;if(wantedSet&&!wantedSet.has(iata))continue;const lat=parseFloat(cells[6]);const lon=parseFloat(cells[7]);if(!isFinite(lat)||!isFinite(lon))continue;out[iata]={lat,lon,name:cells[1]||iata,city:cells[2]||'',country:cells[3]||'',code:iata}}
15return out}
16function parseOurAirports(text,wantedSet){const out={};const lines=text.split(/\r?\n/);const hdr=lines.shift();if(!hdr)return out;const idx={};hdr.split(',').forEach((h,i)=>idx[h]=i);for(const line of lines){if(!line)continue;const cells=line.split(',');const iata=clean(cells[idx.iata_code]);if(!iata)continue;if(wantedSet&&!wantedSet.has(iata))continue;const lat=parseFloat(cells[idx.latitude_deg]);const lon=parseFloat(cells[idx.longitude_deg]);if(!isFinite(lat)||!isFinite(lon))continue;out[iata]={lat,lon,name:cells[idx.name]||iata,city:cells[idx.municipality]||'',country:cells[idx.iso_country]||'',code:iata}}
17return out}
18async function loadAirSubset(wanted){const store=lsRead(LS_KEY_AIR);const have=store.data||{};const missing=[...wanted].filter(c=>!have[c]);if(!missing.length)return have;for(const src of AIR_SOURCES){try{const txt=await fetchText(src);const parsed=src.endsWith('.csv')?parseOurAirports(txt,new Set(missing)):parseOpenFlights(txt,new Set(missing));Object.assign(have,parsed);if(missing.every(c=>have[c]))break}catch(e){}}
19const SEED={FRA:{lat:50.0379,lon:8.5622,name:'Frankfurt am Main',code:'FRA'},MUC:{lat:48.3538,lon:11.7861,name:'Munich',code:'MUC'},DUS:{lat:51.2895,lon:6.7668,name:'Düsseldorf',code:'DUS'},NUE:{lat:49.4987,lon:11.0669,name:'Nürnberg',code:'NUE'},LEJ:{lat:51.4239,lon:12.2367,name:'Leipzig/Halle',code:'LEJ'},HAM:{lat:53.6304,lon:9.9882,name:'Hamburg',code:'HAM'},BER:{lat:52.3628,lon:13.5038,name:'Berlin Brandenburg',code:'BER'},TFS:{lat:28.0445,lon:-16.5725,name:'Tenerife South',code:'TFS'}};for(const code of missing){if(!have[code]&&SEED[code])have[code]=SEED[code]}
20lsWrite(LS_KEY_AIR,have);return have}
21async function loadCitySubset(wanted){const store=lsRead(LS_KEY_CITY);const have=store.data||{};const missing=[...wanted].filter(n=>!have[n]);if(!missing.length)return have;for(const name of missing){try{const url=NOMINATIM_ENDPOINT+'?format=jsonv2&limit=1&q='+encodeURIComponent(name)+'&accept-language=de';const res=await fetchJSON(url);if(Array.isArray(res)&&res.length){const hit=res[0];const lat=parseFloat(hit.lat);const lon=parseFloat(hit.lon);if(isFinite(lat)&&isFinite(lon)){have[name]={lat,lon,name:hit.display_name||name,city:hit.name||name,country:(hit.address&&(hit.address.country||hit.address.country_code))||'',code:name}}}
22await sleep(200)}catch(e){}}
23lsWrite(LS_KEY_CITY,have);return have}
24function greatCircle(a,b,n=120){const toRad=x=>x*Math.PI/180,toDeg=x=>x*180/Math.PI;const φ1=toRad(a.lat),λ1=toRad(a.lon),φ2=toRad(b.lat),λ2=toRad(b.lon);const sinΔφ=Math.sin((φ2-φ1)/2),sinΔλ=Math.sin((φ2-φ1)/2);const Δ=2*Math.asin(Math.sqrt(sinΔφ*sinΔφ+Math.cos(φ1)*Math.cos(φ2)*sinΔλ*sinΔλ));if(!Δ||!isFinite(Δ))return[[a.lat,a.lon],[b.lat,b.lon]];const pts=[];for(let i=0;i<=n;i++){const f=i/n;const A=Math.sin((1-f)*Δ)/Math.sin(Δ);const B=Math.sin(f*Δ)/Math.sin(Δ);const x=A*Math.cos(φ1)*Math.cos(λ1)+B*Math.cos(φ2)*Math.cos(λ2);const y=A*Math.cos(φ1)*Math.sin(λ1)+B*Math.cos(φ2)*Math.sin(λ2);const z=A*Math.sin(φ1)+B*Math.sin(φ2);const φi=Math.atan2(z,Math.sqrt(x*x+y*y));const λi=Math.atan2(y,x);pts.push([toDeg(φi),toDeg(λi)])}
25return pts}
26function ensureHost(el){if(el.dataset.pkRouteReady==='1')return!1;el.dataset.pkRouteReady='1';if(!el.style.height)el.style.height='var(--pk-route-height, 480px)';el.style.position='relative';el.style.borderRadius='14px';el.style.overflow='hidden';return!0}
27function buildMap(el,dark){const map=L.map(el,{zoomControl:!0,attributionControl:!0});const url=dark==='1'?'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png':'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';const attr=dark==='1'?'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; CARTO':'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';L.tileLayer(url,{attribution:attr,maxZoom:12}).addTo(map);return map}
28async function renderOne(el){if(!ensureHost(el))return;await loadAny(LEAFLET_CSS,loadStyleOnce);await loadAny(LEAFLET_JS,loadScriptOnce);if(!window.L){el.textContent='Leaflet konnte nicht geladen werden.';return}
29await sleep(10);const mode=(el.getAttribute('data-mode')||'flight').toLowerCase();const dark=el.getAttribute('data-dark')||'0';const starts=splitCSV(el.getAttribute('data-start'));const stops=splitCSV(el.getAttribute('data-stops'));const ziel=clean(el.getAttribute('data-ziel'));const rawTerms=[...starts,...stops,ziel].filter(Boolean);let db={};if(mode==='ship'){const namesNeeded=new Set(rawTerms.filter(x=>!tryCoords(x)));db=await loadCitySubset(namesNeeded)}else{const codesNeeded=new Set(rawTerms.filter(x=>!tryCoords(x)).map(x=>x.toUpperCase()));db=await loadAirSubset(codesNeeded)}
30const resolve=(term)=>{const c=tryCoords(term);if(c)return{...c,code:undefined};if(!term)return null;if(mode==='ship'){const key=term;return db[key]||null}else{const code=String(term||'').trim().toUpperCase();return db[code]||null}};const startObjs=starts.map(resolve).filter(Boolean);const stopObjs=stops.map(resolve).filter(Boolean);const zielObj=resolve(ziel);if(!startObjs.length||!zielObj){const label=mode==='ship'?'⚠️ Orte konnten nicht aufgelöst werden.':'⚠️ Flughäfen konnten nicht aufgelöst werden.';el.innerHTML='<div style="position:absolute;inset:0;display:grid;place-items:center;font:600 14px/1.3 system-ui">'+label+'</div>';return}
31const map=buildMap(el,dark);const all=[];const addMarker=(p,label)=>{const m=L.marker([p.lat,p.lon],{interactive:!1}).addTo(map);m.bindTooltip(label,{permanent:!0,direction:'top',className:'pk-label'});all.push([p.lat,p.lon])};addMarker(zielObj,zielObj.code||zielObj.name||'Ziel');const addLeg=(a,b,label)=>{const pts=greatCircle(a,b,120);L.polyline(pts,{weight:3,opacity:0.9}).addTo(map);addMarker(a,label||a.code||a.name||(mode==='ship'?'Hafen':'Start'));all.push([b.lat,b.lon])};if(stopObjs.length){for(const s of startObjs){let prev=s;for(let i=0;i<stopObjs.length;i++){const st=stopObjs[i];addLeg(prev,st,prev.code);prev=st}
32addLeg(prev,zielObj,prev.code)}}else{for(const s of startObjs)addLeg(s,zielObj,s.code)}
33try{map.fitBounds(all,{padding:[28,28]})}catch(e){}
34if(!document.getElementById('pk-route-css')){const st=document.createElement('style');st.id='pk-route-css';st.textContent=`
35        .leaflet-tooltip.pk-label{
36          background:#111;border:0;border-radius:12px;color:#fff;
37          padding:4px 8px;font:600 12px/1.1 Inter,system-ui,Arial;
38          box-shadow:0 1px 4px rgba(0,0,0,.25);
39        }`;document.head.appendChild(st)}}
40function boot(){document.querySelectorAll('.pk-route').forEach(renderOne)}
41if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',boot)}else{boot()}
42new MutationObserver(boot).observe(document.documentElement,{childList:!0,subtree:!0})})()

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.