From cd76d94aac98e4d4ee40c84e99068d0a80e5d01c Mon Sep 17 00:00:00 2001 From: Zsolt Ero Date: Wed, 22 Oct 2025 12:35:46 +0200 Subject: [PATCH] mix --- website/public/debug/lang/mix.html | 28 ++++ website/public/debug/lang/mix.js | 239 ++++++++++++++++------------- 2 files changed, 164 insertions(+), 103 deletions(-) diff --git a/website/public/debug/lang/mix.html b/website/public/debug/lang/mix.html index d51d79a..dca462a 100644 --- a/website/public/debug/lang/mix.html +++ b/website/public/debug/lang/mix.html @@ -48,12 +48,40 @@ maxlength="5" /> + +
+ +
+ + + diff --git a/website/public/debug/lang/mix.js b/website/public/debug/lang/mix.js index 2bd7878..4058a03 100644 --- a/website/public/debug/lang/mix.js +++ b/website/public/debug/lang/mix.js @@ -1,37 +1,157 @@ +// ============================================ +// 1. MAIN EXECUTION (Entry Point) +// ============================================ + const map = new maplibregl.Map({ container: 'map', style: 'https://tiles.openfreemap.org/styles/liberty', center: [0, 0], zoom: 2, + hash: true, }) const line1Input = document.getElementById('line1') const line2Input = document.getElementById('line2') const langInput = document.getElementById('lang') -// Parse URL search params to get line1 and line2 -function parseParams() { +map.on('load', () => { const params = new URLSearchParams(window.location.search) - return { - line1: params.get('line1') || 'underscore,colon,name,latin', - line2: params.get('line2') || 'nonlatin', - lang: params.get('lang') || 'en', + + // Set defaults if no params present + if (!params.has('line1') && !params.has('line2') && !params.has('lang')) { + const url = new URL(window.location) + url.searchParams.set('line1', 'underscore,colon,name,latin') + url.searchParams.set('line2', 'nonlatin') + url.searchParams.set('lang', 'en') + window.history.replaceState({}, '', url) + } + + syncInputsFromParams() + applyConfiguration() + initializeInputListeners() + initializeModal() +}) + +// ============================================ +// 2. UI INITIALIZATION +// ============================================ + +function initializeInputListeners() { + line1Input.addEventListener('input', updateParamsFromInputs) + line2Input.addEventListener('input', updateParamsFromInputs) + langInput.addEventListener('input', updateParamsFromInputs) +} + +function initializeModal() { + const modal = document.getElementById('shareModal') + + document.getElementById('shareBtn').addEventListener('click', () => { + modal.classList.remove('hidden') + }) + + document.getElementById('closeModalBtn').addEventListener('click', () => { + modal.classList.add('hidden') + }) + + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && !modal.classList.contains('hidden')) { + modal.classList.add('hidden') + } + }) +} + +// ============================================ +// 3. CONFIGURATION & SYNC +// ============================================ + +function applyConfiguration() { + const { line1, line2, lang } = parseParams() + + if (!map.getStyle()) return + + const style = map.getStyle() + modifyStyle({ + style, + line1Config: line1 ?? '', + line2Config: line2 ?? '', + langCode: lang || 'en', + }) + map.setStyle(style, { diff: false }) +} + +function syncInputsFromParams() { + const { line1, line2, lang } = parseParams() + line1Input.value = line1 ?? '' + line2Input.value = line2 ?? '' + langInput.value = lang ?? '' +} + +function updateParamsFromInputs() { + const params = new URLSearchParams(window.location.search) + params.set('line1', line1Input.value) + params.set('line2', line2Input.value) + params.set('lang', langInput.value) + + const queryString = params.toString() + const hash = window.location.hash + const newUrl = `${window.location.pathname}?${queryString}${hash}` + + window.history.replaceState({}, '', newUrl) +} + +// ============================================ +// 4. STYLE MODIFICATION +// ============================================ + +function modifyStyle({ style, line1Config, line2Config, langCode }) { + for (const layer of style.layers) { + if (layer.source !== 'openmaptiles') continue + if (!layer.layout) continue + + const textField = layer.layout['text-field'] + if (!textField) continue + + if (JSON.stringify(textField) === JSON.stringify(['to-string', ['get', 'ref']])) continue + + const id = layer.id + const separator = id.includes('line') || id.includes('highway') ? ' ' : '\n' + + const line1Expr = buildFieldAccessor(line1Config, langCode) + const line2Expr = buildFieldAccessor(line2Config, langCode) + + if (line1Expr && line2Expr) { + layer.layout['text-field'] = ['concat', line1Expr, separator, line2Expr] + } else if (line1Expr) { + layer.layout['text-field'] = line1Expr + } else if (line2Expr) { + layer.layout['text-field'] = line2Expr + } else { + layer.layout['text-field'] = ['get', 'name'] + } } } -// Update URL search params -function updateParams(line1, line2, lang) { - const url = new URL(window.location) - url.searchParams.set('line1', line1) - url.searchParams.set('line2', line2) - url.searchParams.set('lang', lang) - window.history.replaceState({}, '', url) +// ============================================ +// 5. UTILITY FUNCTIONS +// ============================================ + +function parseParams() { + const params = new URLSearchParams(window.location.search) + return { + line1: params.get('line1'), + line2: params.get('line2'), + lang: params.get('lang'), + } } -// Build field accessor from config string function buildFieldAccessor(config, langCode) { + if (!config) return null + const parts = [] - const fields = config.split(',').map(f => f.trim()).filter(f => f) + const fields = config + .split(',') + .map((f) => f.trim()) + .filter((f) => f) for (const field of fields) { if (field === 'underscore') { @@ -45,96 +165,9 @@ function buildFieldAccessor(config, langCode) { } else if (field === 'nonlatin') { parts.push(['get', 'name:nonlatin']) } else { - // Custom field name parts.push(['get', field]) } } - return parts.length > 0 ? ['coalesce', ...parts] : ['get', 'name'] + return parts.length > 0 ? ['coalesce', ...parts] : null } - -function modifyStyle({ style, line1Config, line2Config, langCode }) { - for (const layer of style.layers) { - if (layer.source !== 'openmaptiles') continue - if (!layer.layout) continue - - const textField = layer.layout['text-field'] - if (!textField) continue - - // Skip ref-only fields - if (JSON.stringify(textField) === JSON.stringify(['to-string', ['get', 'ref']])) continue - - const id = layer.id - let separator = id.includes('line') || id.includes('highway') ? ' ' : '\n' - - const line1Expr = buildFieldAccessor(line1Config, langCode) - const line2Expr = buildFieldAccessor(line2Config, langCode) - - // Combine both lines - layer.layout['text-field'] = ['concat', line1Expr, separator, line2Expr] - } -} - -function applyConfiguration() { - const { line1, line2, lang } = parseParams() - - if (!map.getStyle()) return - - const style = map.getStyle() - modifyStyle({ style, line1Config: line1, line2Config: line2, langCode: lang }) - map.setStyle(style, { diff: false }) -} - -function syncInputsFromParams() { - const { line1, line2, lang } = parseParams() - line1Input.value = line1 - line2Input.value = line2 - langInput.value = lang -} - -// Update params when inputs change -line1Input.addEventListener('input', () => { - updateParams(line1Input.value, line2Input.value, langInput.value) -}) - -line2Input.addEventListener('input', () => { - updateParams(line1Input.value, line2Input.value, langInput.value) -}) - -langInput.addEventListener('input', () => { - updateParams(line1Input.value, line2Input.value, langInput.value) -}) - -// Apply configuration when Enter is pressed -line1Input.addEventListener('keypress', (e) => { - if (e.key === 'Enter') applyConfiguration() -}) - -line2Input.addEventListener('keypress', (e) => { - if (e.key === 'Enter') applyConfiguration() -}) - -langInput.addEventListener('keypress', (e) => { - if (e.key === 'Enter') applyConfiguration() -}) - -map.on('load', () => { - // Initialize params if not present - const params = new URLSearchParams(window.location.search) - if (!params.has('line1') || !params.has('line2') || !params.has('lang')) { - const url = new URL(window.location) - if (!params.has('line1')) url.searchParams.set('line1', 'underscore,colon,name,latin') - if (!params.has('line2')) url.searchParams.set('line2', 'nonlatin') - if (!params.has('lang')) url.searchParams.set('lang', 'en') - window.history.replaceState({}, '', url) - } - - syncInputsFromParams() - applyConfiguration() -}) - -// Listen for URL changes (e.g., browser back/forward) -window.addEventListener('popstate', () => { - syncInputsFromParams() - applyConfiguration() -}) \ No newline at end of file