1// Multilingual map preview for the language picker. 2// 3// The SDK is the vendored UMD build (assets/js/vendor/maptiler-sdk.umd.js), ~379 KB 4// gzipped, attached to window.maptilersdk. initHero calls this on the hero dialog's 5// first open, NOT when the markup is found â every page on the home layout carries the 6// picker and only /languages/:code/ opens the dialog, so gating on presence downloaded 7// the SDK site-wide for a map that could not be shown. 8 9const ZURICH_CENTER = [8.5417, 47.3769]; 10const ZURICH_ZOOM = 10.5; 11 12const parseBbox = (bbox) => bbox.split(",").map(parseFloat); 13 14let sdkPromise; 15 16function loadSdk(base) { 17 if (sdkPromise) return sdkPromise; 18 19 sdkPromise = new Promise((resolve, reject) => { 20 const css = document.createElement("link"); 21 css.rel = "stylesheet"; 22 css.href = `${base}/assets/js/vendor/maptiler-sdk.css`; 23 document.head.appendChild(css); 24 25 const script = document.createElement("script"); 26 script.src = `${base}/assets/js/vendor/maptiler-sdk.umd.js`; 27 script.onload = () => resolve(window.maptilersdk); 28 script.onerror = () => reject(new Error("Failed to load MapTiler SDK")); 29 document.head.appendChild(script); 30 }); 31 32 return sdkPromise; 33} 34 35function hasWebGL() { 36 const canvas = document.createElement("canvas"); 37 return Boolean( 38 canvas.getContext("webgl") || canvas.getContext("experimental-webgl") 39 ); 40} 41 42// Mirrors detectInitialCode(): explicit route language, else the first browser 43// preference the site supports, else English. 44function initialCode(root, languages) { 45 const active = root.getAttribute("data-active-language"); 46 if (active && languages.some((l) => l.code === active)) return active; 47 48 const supported = new Set(languages.map((l) => l.code)); 49 for (const pref of navigator.languages || [navigator.language]) { 50 const code = String(pref).split("-")[0]; 51 if (supported.has(code)) return code; 52 } 53 return "en"; 54} 55 56let started = false; 57 58export async function initLanguages(config) { 59 // Set before the first await: the dialog can be reopened, and two opens in the same 60 // tick would both pass a flag raised only after the SDK finished loading. 61 if (started) return; 62 started = true; 63 64 const root = document.querySelector("[data-languages-map]"); 65 if (!root) return; 66 67 const container = root.querySelector("[data-languages-canvas]"); 68 const titleEl = root.querySelector("[data-languages-title]"); 69 const noWebgl = root.querySelector("[data-languages-nowebgl]"); 70 71 const languages = config.languages || []; 72 const code = initialCode(root, languages); 73 const current = 74 languages.find((l) => l.code === code) || 75 languages.find((l) => l.code === "en") || 76 {}; 77 78 if (titleEl) titleEl.textContent = current.titlelocalized || current.title || ""; 79 80 if (!hasWebGL()) { 81 if (noWebgl) noWebgl.removeAttribute("hidden"); 82 return; 83 } 84 85 let sdk; 86 try { 87 sdk = await loadSdk(config.baseurl || ""); 88 } catch (err) { 89 console.error(err); 90 return; 91 } 92 93 sdk.config.apiKey = config.apiKey; 94 95 const map = new sdk.Map({ 96 container, 97 style: sdk.MapStyle.OPENSTREETMAP, 98 center: ZURICH_CENTER, 99 zoom: ZURICH_ZOOM, 100 attributionControl: {}, 101 // `hash` was tied to the non-embedded variant, which the site never renders. 102 hash: false, 103 navigationControl: false, 104 geolocateControl: false, 105 maptilerLogo: false, 106 }); 107 108 const applyLanguage = (value) => { 109 try { 110 map.setLanguage(value === "native" ? sdk.Language.LOCAL : value); 111 } catch { 112 // Language code the SDK does not know â ignored rather than treated as an error. 113 } 114 }; 115 116 map.on("load", () => { 117 map.resize(); 118 applyLanguage(code); 119 120 // The original deliberately stayed on Zurich for the initial load and only 121 // used a language's bbox on subsequent changes. 122 const explicit = root.getAttribute("data-active-language"); 123 if (explicit && current.bbox) { 124 map.fitBounds(parseBbox(current.bbox), { animate: true, padding: 10 }); 125 } 126 }); 127}
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.