diff --git a/about.html b/about.html index 300c57f..15f69e2 100644 --- a/about.html +++ b/about.html @@ -6,12 +6,7 @@ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> - - - - - - hvvstuhl.de | Was ist das? + Barrierefreie Aufzugs-Liste | Was ist das?

Barrierefreie Aufzugs-Liste

@@ -30,19 +25,18 @@
-
-

Worum geht's hier?

-

- Diese Seite ermöglicht einen barrierefreien Zugang zu den Aufzugs-Informationen im HVV. - Der HVV selbst zeigt diese Informationen nur auf einer (vor allem ohne Ortskenntnis) schwer zu navigierenden - Karte an: - HVV Webseite zu Aufzügen -

-

- Dieses Projekt wurde unter der AGPL-3 Lizenz entwickelt und ist hier zu finden: - git.kritzl.dev -

-
+
+

Worum geht's hier?

+

+ Diese Seite ermöglicht einen barrierefreien Zugang zu den Aufzugs informationen im HVV. + Der HVV selbst zeigt diese Informationen nur auf einer (vor allem ohne Ortskenntnis) schwer zu navigierenden Karte an: + HVV Webseite zu Aufzügen +

+

+ Dieses Projekt wurde unter AGPL-3 entwickelt und ist hier zu finden: + git.kritzl.dev +

+
\ No newline at end of file diff --git a/colors.css b/colors.css deleted file mode 100644 index f48e716..0000000 --- a/colors.css +++ /dev/null @@ -1,3 +0,0 @@ - - -/*# sourceMappingURL=colors.css.map */ diff --git a/colors.css.map b/colors.css.map deleted file mode 100644 index 6ee84d1..0000000 --- a/colors.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sourceRoot":"","sources":[],"names":[],"mappings":"","file":"colors.css"} \ No newline at end of file diff --git a/colors.scss b/colors.scss deleted file mode 100644 index 5c32430..0000000 --- a/colors.scss +++ /dev/null @@ -1,271 +0,0 @@ -@mixin tailwindColors { - /* Colors from Tailwind CSS: https://github.com/tailwindlabs/tailwindcss - - MIT License - - Copyright (c) Tailwind Labs, Inc. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - --color-black: #000; - --color-white: #fff; - --color-slate-50: #f8fafc; - --color-slate-100: #f1f5f9; - --color-slate-200: #e2e8f0; - --color-slate-300: #cbd5e1; - --color-slate-400: #94a3b8; - --color-slate-500: #64748b; - --color-slate-600: #475569; - --color-slate-700: #334155; - --color-slate-800: #1e293b; - --color-slate-900: #0f172a; - --color-slate-950: #020617; - --color-gray-50: #f9fafb; - --color-gray-100: #f3f4f6; - --color-gray-200: #e5e7eb; - --color-gray-300: #d1d5db; - --color-gray-400: #9ca3af; - --color-gray-500: #6b7280; - --color-gray-600: #4b5563; - --color-gray-700: #374151; - --color-gray-800: #1f2937; - --color-gray-900: #111827; - --color-gray-950: #030712; - --color-zinc-50: #fafafa; - --color-zinc-100: #f4f4f5; - --color-zinc-200: #e4e4e7; - --color-zinc-300: #d4d4d8; - --color-zinc-400: #a1a1aa; - --color-zinc-500: #71717a; - --color-zinc-600: #52525b; - --color-zinc-700: #3f3f46; - --color-zinc-800: #27272a; - --color-zinc-900: #18181b; - --color-zinc-950: #09090b; - --color-neutral-50: #fafafa; - --color-neutral-100: #f5f5f5; - --color-neutral-200: #e5e5e5; - --color-neutral-300: #d4d4d4; - --color-neutral-400: #a3a3a3; - --color-neutral-500: #737373; - --color-neutral-600: #525252; - --color-neutral-700: #404040; - --color-neutral-800: #262626; - --color-neutral-900: #171717; - --color-neutral-950: #0a0a0a; - --color-stone-50: #fafaf9; - --color-stone-100: #f5f5f4; - --color-stone-200: #e7e5e4; - --color-stone-300: #d6d3d1; - --color-stone-400: #a8a29e; - --color-stone-500: #78716c; - --color-stone-600: #57534e; - --color-stone-700: #44403c; - --color-stone-800: #292524; - --color-stone-900: #1c1917; - --color-stone-950: #0c0a09; - --color-red-50: #fef2f2; - --color-red-100: #fee2e2; - --color-red-200: #fecaca; - --color-red-300: #fca5a5; - --color-red-400: #f87171; - --color-red-500: #ef4444; - --color-red-600: #dc2626; - --color-red-700: #b91c1c; - --color-red-800: #991b1b; - --color-red-900: #7f1d1d; - --color-red-950: #450a0a; - --color-orange-50: #fff7ed; - --color-orange-100: #ffedd5; - --color-orange-200: #fed7aa; - --color-orange-300: #fdba74; - --color-orange-400: #fb923c; - --color-orange-500: #f97316; - --color-orange-600: #ea580c; - --color-orange-700: #c2410c; - --color-orange-800: #9a3412; - --color-orange-900: #7c2d12; - --color-orange-950: #431407; - --color-amber-50: #fffbeb; - --color-amber-100: #fef3c7; - --color-amber-200: #fde68a; - --color-amber-300: #fcd34d; - --color-amber-400: #fbbf24; - --color-amber-500: #f59e0b; - --color-amber-600: #d97706; - --color-amber-700: #b45309; - --color-amber-800: #92400e; - --color-amber-900: #78350f; - --color-amber-950: #451a03; - --color-yellow-50: #fefce8; - --color-yellow-100: #fef9c3; - --color-yellow-200: #fef08a; - --color-yellow-300: #fde047; - --color-yellow-400: #facc15; - --color-yellow-500: #eab308; - --color-yellow-600: #ca8a04; - --color-yellow-700: #a16207; - --color-yellow-800: #854d0e; - --color-yellow-900: #713f12; - --color-yellow-950: #422006; - --color-lime-50: #f7fee7; - --color-lime-100: #ecfccb; - --color-lime-200: #d9f99d; - --color-lime-300: #bef264; - --color-lime-400: #a3e635; - --color-lime-500: #84cc16; - --color-lime-600: #65a30d; - --color-lime-700: #4d7c0f; - --color-lime-800: #3f6212; - --color-lime-900: #365314; - --color-lime-950: #1a2e05; - --color-green-50: #f0fdf4; - --color-green-100: #dcfce7; - --color-green-200: #bbf7d0; - --color-green-300: #86efac; - --color-green-400: #4ade80; - --color-green-500: #22c55e; - --color-green-600: #16a34a; - --color-green-700: #15803d; - --color-green-800: #166534; - --color-green-900: #14532d; - --color-green-950: #052e16; - --color-emerald-50: #ecfdf5; - --color-emerald-100: #d1fae5; - --color-emerald-200: #a7f3d0; - --color-emerald-300: #6ee7b7; - --color-emerald-400: #34d399; - --color-emerald-500: #10b981; - --color-emerald-600: #059669; - --color-emerald-700: #047857; - --color-emerald-800: #065f46; - --color-emerald-900: #064e3b; - --color-emerald-950: #022c22; - --color-teal-50: #f0fdfa; - --color-teal-100: #ccfbf1; - --color-teal-200: #99f6e4; - --color-teal-300: #5eead4; - --color-teal-400: #2dd4bf; - --color-teal-500: #14b8a6; - --color-teal-600: #0d9488; - --color-teal-700: #0f766e; - --color-teal-800: #115e59; - --color-teal-900: #134e4a; - --color-teal-950: #042f2e; - --color-cyan-50: #ecfeff; - --color-cyan-100: #cffafe; - --color-cyan-200: #a5f3fc; - --color-cyan-300: #67e8f9; - --color-cyan-400: #22d3ee; - --color-cyan-500: #06b6d4; - --color-cyan-600: #0891b2; - --color-cyan-700: #0e7490; - --color-cyan-800: #155e75; - --color-cyan-900: #164e63; - --color-cyan-950: #083344; - --color-sky-50: #f0f9ff; - --color-sky-100: #e0f2fe; - --color-sky-200: #bae6fd; - --color-sky-300: #7dd3fc; - --color-sky-400: #38bdf8; - --color-sky-500: #0ea5e9; - --color-sky-600: #0284c7; - --color-sky-700: #0369a1; - --color-sky-800: #075985; - --color-sky-900: #0c4a6e; - --color-sky-950: #082f49; - --color-blue-50: #eff6ff; - --color-blue-100: #dbeafe; - --color-blue-200: #bfdbfe; - --color-blue-300: #93c5fd; - --color-blue-400: #60a5fa; - --color-blue-500: #3b82f6; - --color-blue-600: #2563eb; - --color-blue-700: #1d4ed8; - --color-blue-800: #1e40af; - --color-blue-900: #1e3a8a; - --color-blue-950: #172554; - --color-indigo-50: #eef2ff; - --color-indigo-100: #e0e7ff; - --color-indigo-200: #c7d2fe; - --color-indigo-300: #a5b4fc; - --color-indigo-400: #818cf8; - --color-indigo-500: #6366f1; - --color-indigo-600: #4f46e5; - --color-indigo-700: #4338ca; - --color-indigo-800: #3730a3; - --color-indigo-900: #312e81; - --color-indigo-950: #1e1b4b; - --color-violet-50: #f5f3ff; - --color-violet-100: #ede9fe; - --color-violet-200: #ddd6fe; - --color-violet-300: #c4b5fd; - --color-violet-400: #a78bfa; - --color-violet-500: #8b5cf6; - --color-violet-600: #7c3aed; - --color-violet-700: #6d28d9; - --color-violet-800: #5b21b6; - --color-violet-900: #4c1d95; - --color-violet-950: #2e1065; - --color-purple-50: #faf5ff; - --color-purple-100: #f3e8ff; - --color-purple-200: #e9d5ff; - --color-purple-300: #d8b4fe; - --color-purple-400: #c084fc; - --color-purple-500: #a855f7; - --color-purple-600: #9333ea; - --color-purple-700: #7e22ce; - --color-purple-800: #6b21a8; - --color-purple-900: #581c87; - --color-purple-950: #3b0764; - --color-fuchsia-50: #fdf4ff; - --color-fuchsia-100: #fae8ff; - --color-fuchsia-200: #f5d0fe; - --color-fuchsia-300: #f0abfc; - --color-fuchsia-400: #e879f9; - --color-fuchsia-500: #d946ef; - --color-fuchsia-600: #c026d3; - --color-fuchsia-700: #a21caf; - --color-fuchsia-800: #86198f; - --color-fuchsia-900: #701a75; - --color-fuchsia-950: #4a044e; - --color-pink-50: #fdf2f8; - --color-pink-100: #fce7f3; - --color-pink-200: #fbcfe8; - --color-pink-300: #f9a8d4; - --color-pink-400: #f472b6; - --color-pink-500: #ec4899; - --color-pink-600: #db2777; - --color-pink-700: #be185d; - --color-pink-800: #9d174d; - --color-pink-900: #831843; - --color-pink-950: #500724; - --color-rose-50: #fff1f2; - --color-rose-100: #ffe4e6; - --color-rose-200: #fecdd3; - --color-rose-300: #fda4af; - --color-rose-400: #fb7185; - --color-rose-500: #f43f5e; - --color-rose-600: #e11d48; - --color-rose-700: #be123c; - --color-rose-800: #9f1239; - --color-rose-900: #881337; - --color-rose-950: #4c0519; - /* End: Colors from Tailwind CSS */ -} \ No newline at end of file diff --git a/elevators.js b/elevators.js index 4908cfb..ea999f4 100644 --- a/elevators.js +++ b/elevators.js @@ -7,7 +7,7 @@ let geolocation = null; const openStations = new Set(); let sortByDistance = false; -const substituteData = [ +const substituteCoordinates = [ { name: 'Borgweg (Stadtpark)', coordinates: [53.5907696, 10.0147719], @@ -24,26 +24,6 @@ const substituteData = [ name: 'Hagenbecks Tierpark', coordinates: [53.5925874, 9.9440359], }, - { - name: 'Hamburg Hbf', - searchTarget: "Hauptbahnhof", - }, - { - name: 'Jungfernstieg', - searchTarget: "Rathaus", - }, - { - name: 'Rathaus', - searchTarget: "Jungfernstieg", - }, - { - name: 'Stephansplatz (Oper/CCH)', - searchTarget: "Dammtor (Messe/CCH)", - }, - { - name: 'Dammtor (Messe/CCH)', - searchTarget: "Stephansplatz (Oper/CCH)", - }, { name: 'Hauptbahnhof Nord', coordinates: [53.5541197, 10.0061270], @@ -82,6 +62,14 @@ const substituteData = [ }, ] + +Object.defineProperty(String.prototype, 'capitalize', { + value: function () { + return this.charAt(0).toUpperCase() + this.toLowerCase().slice(1); + }, + enumerable: false +}); + async function loadElevators() { document.querySelector('#errorMessage').classList.add('hidden'); const res = await fetch('https://www.hvv.de/elevators', { @@ -101,13 +89,6 @@ async function loadElevators() { for (const station of stations) { const stationName = station['mainSubStation']['stationName']; const stationComment = station['mainSubStation']['comment']; - let searchTarget = undefined; - - const substitute = substituteData.filter(subs => subs.name === stationName) - - if (substitute.length && substitute[0].hasOwnProperty('searchTarget')) { - searchTarget = substitute[0].searchTarget; - } const lines = new Set(); const elevators = []; for (const elevatorKey of Object.keys(station.elevators)) { @@ -176,7 +157,6 @@ async function loadElevators() { internalData.stations[stationIndex++] = { name: stationName, comment: stationComment, - searchTarget: searchTarget, state: stationState, lines: stationLines, types: stationTypes, @@ -185,11 +165,17 @@ async function loadElevators() { } localStorage.setItem("internal_data", JSON.stringify({ - api: minorVersion, + api: 'v1', ...internalData })); } +const dateTimeStyle = new Intl.DateTimeFormat('de-DE', { + dateStyle: 'medium', + timeStyle: 'medium', + timeZone: 'Europe/Berlin', +}) + async function loadOsmData() { const nodeIdList = []; for (const station of internalData.stations) { @@ -231,21 +217,20 @@ async function loadOsmData() { } if (!internalData.stations[stationIndex].hasOwnProperty('coordinates')) { - const substitute = substituteData.filter(subs => subs.name === internalData.stations[stationIndex].name) - console.log(substitute) - if (substitute.length && substitute[0].hasOwnProperty('coordinates')) { + const substitute = substituteCoordinates.filter(subs => subs.name === internalData.stations[stationIndex].name) + if (substitute.length) { internalData.stations[stationIndex]['coordinates'] = substitute[0].coordinates; } } } localStorage.setItem("osm_data", JSON.stringify({ - api: minorVersion, + api: 'v1', lastUpdate: new Date(), nodes: osmNodes })); localStorage.setItem("internal_data", JSON.stringify({ - api: minorVersion, + api: 'v1', ...internalData })); } @@ -317,23 +302,9 @@ function sortStations(stationA, stationB) { return 0; } -function sortInt(valueA, valueB) { - const a = parseInt(valueA) - const b = parseInt(valueB) - if (a < b) { - return -1; - } - if (a > b) { - return 1; - } - - // names must be equal - return 0; -} - function sortStationsByDistance(stationA, stationB) { - const distanceA = stationA.distance ?? 0; // ignore upper and lowercase - const distanceB = stationB.distance ?? 0; // ignore upper and lowercase + const distanceA = stationA.distance; // ignore upper and lowercase + const distanceB = stationB.distance; // ignore upper and lowercase if (distanceA < distanceB) { return -1; } @@ -399,17 +370,7 @@ function renderData(location = null) { document.querySelector('#filters').classList.remove('hidden'); document.querySelector('#initialLoad').classList.add('hidden'); const dateContainer = document.querySelector('#lastUpdated'); - const oldDataWarning = document.querySelector('#oldDataWarning'); - - const lastUpdate = new Date(internalData.lastUpdate); - const now = new Date(); - dateContainer.innerHTML = dateTimeStyle.format(lastUpdate); - oldDataWarning.classList.add('hidden'); - if (now - lastUpdate > 86400 * 1000) { - const days = numberFormat.format((now - lastUpdate) / (86400 * 1000)); - oldDataWarning.classList.remove('hidden'); - oldDataWarning.innerHTML = `Daten ${days} Tag${days !== '1' ? 'e' : ''} alt!`; - } + dateContainer.innerHTML = dateTimeStyle.format(new Date(internalData.lastUpdate)); const listContainer = document.querySelector('#stationList'); //clear list before update @@ -430,9 +391,7 @@ function renderData(location = null) { } } - if (sortByDistance) { - stations = stations.sort(sortStationsByDistance); - } + stations = stations.sort(sortStationsByDistance); for (const stationIndex in stations) { const station = stations[stationIndex]; @@ -495,7 +454,7 @@ function renderData(location = null) { osmTemplate += `
Beschreibung
${node.tags['description']}
`; } if (node.tags.hasOwnProperty('level')) { - osmTemplate += `
Ebenen
${node.tags['level'].split(';').sort(sortInt).join(', ')}
`; + osmTemplate += `
Ebenen
${node.tags['level'].split(';').sort().join(', ')}
`; } if (node.tags.hasOwnProperty('wheelchair')) { osmTemplate += `
Rollstühle
${node.tags['wheelchair'] === 'yes' ? 'Ja' : 'Nein'}
`; @@ -568,11 +527,7 @@ function renderData(location = null) {
${station.types.sort().map(t => `${t}`).join('')}
- ${sortByDistance - ? typeof station.distance !== 'undefined' - ? `
${Math.round(station.distance / 100) / 10}
km
` - : '
? km
' - : ''} + ${typeof station.distance !== 'undefined' ? `
${Math.round(station.distance / 100) / 10}
km
` : ''}

${station.name}

@@ -667,13 +622,12 @@ document.querySelector('#stationsNearMe') if (geolocationPermission !== 'granted') { allowGeolocation(); } else { - sortByDistance = e.target.ariaPressed = true; - // If geolocation is already set. // If not the location watcher will re-render our data. if (geolocation !== null) { renderData(geolocation) } + sortByDistance = e.target.ariaPressed = true; } } } else { @@ -692,25 +646,22 @@ function filterData() { const typeA = document.querySelector('button.typeChip[data-type="A"]'); const typeR = document.querySelector('button.typeChip[data-type="R"]'); const activeTypes = []; - if (typeU.dataset.pressed === 'true') activeTypes.push('U'); - if (typeS.dataset.pressed === 'true') activeTypes.push('S'); - if (typeA.dataset.pressed === 'true') activeTypes.push('A'); - if (typeR.dataset.pressed === 'true') activeTypes.push('R'); + if(typeU.dataset.pressed === 'true') activeTypes.push('U'); + if(typeS.dataset.pressed === 'true') activeTypes.push('S'); + if(typeA.dataset.pressed === 'true') activeTypes.push('A'); + if(typeR.dataset.pressed === 'true') activeTypes.push('R'); const stationCount = internalData.stations.length; let filteredStations = 0; if (internalData) { for (const stationIndex in internalData.stations) { - const matchesName = internalData.stations[stationIndex].name.toLowerCase().search(searchString.toLowerCase()) >= 0; - const matchesSearchTarget = internalData.stations[stationIndex].hasOwnProperty('searchTarget') - ? internalData.stations[stationIndex].searchTarget.toLowerCase().search(searchString.toLowerCase()) >= 0 - : false; + const matchesSearch = internalData.stations[stationIndex].name.toLowerCase().search(searchString.toLowerCase()) >= 0; let matchesType = false; internalData.stations[stationIndex].types.forEach(type => { - if (activeTypes.includes(type)) matchesType = true; + if(activeTypes.includes(type)) matchesType = true; }) - const filtered = !((matchesName || matchesSearchTarget) && matchesType); + const filtered = !(matchesSearch && matchesType); document.querySelector(`#station_${stationIndex}`).classList.toggle('hidden', filtered); - if (filtered) filteredStations++; + if(filtered) filteredStations++; } document.querySelector('#stationCount').innerHTML = stationCount; @@ -729,11 +680,23 @@ document.querySelectorAll('button.typeChip').forEach(e => { }) }) +function openDialog(selector) { + document.querySelector('body').classList.add('has-dialog') + document.querySelector('#dialog_layer').classList.add('active') + document.querySelector(selector).classList.remove('hidden') +} + +function closeDialog(selector) { + document.querySelector('body').classList.remove('has-dialog') + document.querySelector('#dialog_layer').classList.remove('active') + document.querySelector(selector).classList.add('hidden') +} + // data api version check const check_internal = JSON.parse(localStorage.getItem("internal_data")); const check_osm = JSON.parse(localStorage.getItem("osm_data")); -if (check_internal === null || check_internal.hasOwnProperty('api') && check_internal.api === minorVersion) { - if (check_osm === null || check_osm.hasOwnProperty('api') && check_osm.api === minorVersion) { +if (check_internal === null || check_internal.hasOwnProperty('api') && check_internal.api === 'v1') { + if (check_osm === null || check_osm.hasOwnProperty('api') && check_osm.api === 'v1') { renderData(); } else { console.log('osm_data: version mismatch') diff --git a/icons/192.png b/icons/192.png deleted file mode 100644 index a329713..0000000 Binary files a/icons/192.png and /dev/null differ diff --git a/icons/512-maskable.png b/icons/512-maskable.png deleted file mode 100644 index 6122f35..0000000 Binary files a/icons/512-maskable.png and /dev/null differ diff --git a/icons/512-transparent.png b/icons/512-transparent.png deleted file mode 100644 index c6eed8c..0000000 Binary files a/icons/512-transparent.png and /dev/null differ diff --git a/icons/512.png b/icons/512.png deleted file mode 100644 index 79acdc4..0000000 Binary files a/icons/512.png and /dev/null differ diff --git a/icons/favicon-maskable.svg b/icons/favicon-maskable.svg deleted file mode 100644 index cb8cda2..0000000 --- a/icons/favicon-maskable.svg +++ /dev/null @@ -1,58 +0,0 @@ - - - - diff --git a/icons/favicon-transparent.svg b/icons/favicon-transparent.svg deleted file mode 100644 index dcea345..0000000 --- a/icons/favicon-transparent.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - diff --git a/icons/favicon.ico b/icons/favicon.ico deleted file mode 100644 index 29e9f5e..0000000 Binary files a/icons/favicon.ico and /dev/null differ diff --git a/icons/favicon.svg b/icons/favicon.svg deleted file mode 100644 index 4222b18..0000000 --- a/icons/favicon.svg +++ /dev/null @@ -1,58 +0,0 @@ - - - - diff --git a/icons/favicon_source.svg b/icons/favicon_source.svg deleted file mode 100644 index 028ef75..0000000 --- a/icons/favicon_source.svg +++ /dev/null @@ -1,85 +0,0 @@ - - - - diff --git a/images/screenshot-desktop.png b/images/screenshot-desktop.png deleted file mode 100644 index 4856c04..0000000 Binary files a/images/screenshot-desktop.png and /dev/null differ diff --git a/images/screenshot-mobile.png b/images/screenshot-mobile.png deleted file mode 100644 index 2856686..0000000 Binary files a/images/screenshot-mobile.png and /dev/null differ diff --git a/index.html b/index.html index 2099374..b676958 100644 --- a/index.html +++ b/index.html @@ -6,12 +6,7 @@ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> - - - - - - hvvstuhl.de + Barrierefreie Aufzugs-Liste

Barrierefreie Aufzugs-Liste

@@ -33,18 +28,18 @@

Liste aller Stationen mit Aufzug im HVV

+