diff --git a/elevators.js b/elevators.js index 34b9713..912f1ea 100644 --- a/elevators.js +++ b/elevators.js @@ -1,3 +1,11 @@ +const internalData = { + lastUpdate: 0, + stations: [], +}; +let geolocationPermission = false; +let geolocation = [null, null]; + + Object.defineProperty(String.prototype, 'capitalize', { value: function () { return this.charAt(0).toUpperCase() + this.toLowerCase().slice(1); @@ -9,7 +17,90 @@ async function loadElevators() { const res = await fetch('https://www.hvv.de/elevators', {referrer: ""}); const data = await res.json(); - localStorage.setItem("elevator_data", JSON.stringify(data)); + + const stations = data['stations']; + stations.sort(sortStations) + internalData.lastUpdate = new Date(data['lastUpdate']); + + let stationIndex = 0; + + for (const station of stations) { + const stationName = station['mainSubStation']['stationName']; + const lines = new Set(); + const elevators = []; + for (const elevatorKey of Object.keys(station.elevators)) { + const elevatorApi = station.elevators[elevatorKey]; + const elevatorLines = []; + for (let line of elevatorApi.lines) { + line = line.replace(/[()]/g, ""); + lines.add(line); + elevatorLines.push({ + line: line, + type: getType(line), + }); + } + + // try to detect levels from description + let levels = []; + if (elevatorApi.description.search('<->') >= 0) { + levels = elevatorApi.description.split('<->').map(level => level.trim()); + } else if (elevatorApi.description.search('<>') >= 0) { + levels = elevatorApi.description.split('<>').map(level => level.trim()); + } else if (elevatorApi.description.search('/ ') >= 0) { + levels = elevatorApi.description.split('/ ').map(level => level.trim()); + } + + const elevator = { + working: elevatorApi['state'] === 1, + stateUnavailable: elevatorApi['state'] === -1, + dimensions: { + width: elevatorApi['cabinWidth'], + length: elevatorApi['cabinLength'], + door: elevatorApi['doorWidth'], + }, + description: elevatorApi['description'], + label: elevatorApi['label'], + type: elevatorApi['type'].replace('_', ' ').capitalize(), + braille: elevatorApi['tasterType'] === 'UNBEKANNT' ? -1 : elevatorApi['tasterType'] === 'KOMBI' || elevatorApi['tasterType'] === 'BRAILLE', + speaker: elevatorApi['tasterType'] === 'UNBEKANNT' ? -1 : elevatorApi['tasterType'] === 'KOMBI', + lines: elevatorLines, + levels: levels, + instCause: elevatorApi['instCause'], + osmNodeId: elevatorApi['osmId'], + } + + elevators.push(elevator); + } + + let stationState = { + unavailable: 0, + working: 0, + outOfOrder: 0, + } + + for (const elevator of elevators) { + if (elevator.stateUnavailable) { + stationState.unavailable++; + } else if (elevator.working) { + stationState.working++; + } else { + stationState.outOfOrder++; + } + } + + const stationLines = Array.from(lines); + const stationTypes = Array.from(getTypes(stationLines)); + + internalData.stations[stationIndex++] = { + name: stationName, + state: stationState, + lines: stationLines, + types: stationTypes, + elevators: elevators, + } + } + + localStorage.setItem("internal_data", JSON.stringify(internalData)); } const dateTimeStyle = new Intl.DateTimeFormat('de-DE', { @@ -18,19 +109,11 @@ const dateTimeStyle = new Intl.DateTimeFormat('de-DE', { timeZone: 'Europe/Berlin', }) -const internalData = [] -let geolocationPermission = false; -let geolocation = [null, null]; - async function loadOsmData() { - const elevatorNodes = document.querySelectorAll('.elevator'); const nodeIdList = []; - for (const elevator of elevatorNodes) { - const osmContainer = elevator.querySelector('.osm'); - const nodeId = osmContainer.dataset.nodeid; - if (nodeId > 0) { - elevator.querySelector('.osm').insertAdjacentHTML("beforeend", '
loading...
'); - nodeIdList.push(nodeId) + for (const station of internalData.stations) { + for (const elevator of station.elevators) { + nodeIdList.push(elevator.osmNodeId) } } @@ -39,44 +122,7 @@ async function loadOsmData() { if (!osmJson.hasOwnProperty('elements')) return; - for (const elevator of elevatorNodes) { - const tagContainer = elevator.querySelector('.osmTags'); - const nodeId = elevator.querySelector('.osm').dataset.nodeid; - - const nodes = osmJson.elements.filter(node => node.id === parseInt(nodeId)) - if (!nodes.length) { - tagContainer.innerHTML = 'keine Daten'; - continue; - } - const nodeInfo = nodes[0]; - - if (!nodeInfo.hasOwnProperty('tags')) { - tagContainer.innerHTML = 'keine Daten'; - continue; - } - const tags = nodeInfo['tags']; - - if (tags['highway'] === 'elevator') { - let osmTemplate = ''; - osmTemplate += `
Link zur Karte
-Auf Karte anzeigen -
`; - if (tags.hasOwnProperty('description')) { - osmTemplate += `
Beschreibung
${tags['description']}
`; - } - if (tags.hasOwnProperty('level')) { - osmTemplate += `
Ebenen
${tags['level'].split(';').sort().join(', ')}
`; - } - if (tags.hasOwnProperty('wheelchair')) { - osmTemplate += `
Rollstühle
${tags['wheelchair'] === 'yes' ? 'Ja' : 'Nein'}
`; - } - if (tags.hasOwnProperty('bicycle')) { - osmTemplate += `
Fahrräder
${tags['bicycle'] === 'yes' ? 'Ja' : 'Nein'}
`; - } - tagContainer.innerHTML = ''; // clear loading state - tagContainer.insertAdjacentHTML('beforeend', osmTemplate); - } - } + localStorage.setItem("osm_data", JSON.stringify(osmJson)); } function distance([lat1, lon1], [lat2, lon2]) { @@ -171,85 +217,34 @@ function getTypes(lines) { } function renderData() { - const data = JSON.parse(localStorage.getItem("elevator_data")); + const ls = JSON.parse(localStorage.getItem("internal_data")); + if (!ls) return; + internalData.lastUpdate = ls['lastUpdate']; + internalData.stations = ls['stations']; + const osmData = JSON.parse(localStorage.getItem("osm_data")); - if (!data) { + if (!internalData || !internalData.stations.length) { console.error('No Data available!') return; } - let stations = data.stations; - stations.sort(sortStations) - const date = new Date(data.lastUpdate); - document.querySelector('#loadElevators').innerHTML = 'Daten aktualisieren'; - const listContainer = document.querySelector('#stationList'); const dateContainer = document.querySelector('#lastUpdated'); + dateContainer.innerHTML = dateTimeStyle.format(new Date(internalData.lastUpdate)); - dateContainer.innerHTML = dateTimeStyle.format(date); - - let stationIndex = 0; - + const listContainer = document.querySelector('#stationList'); //clear list before update listContainer.innerHTML = ''; - for (const station of stations) { - const stationName = station.mainSubStation.stationName; - const lines = new Set(); - const elevators = []; - for (const elevatorKey of Object.keys(station.elevators)) { - const elevatorApi = station.elevators[elevatorKey]; - const elevatorLines = []; - for (let line of elevatorApi.lines) { - line = line.replace(/[\(\)]/g, ""); - lines.add(line); - elevatorLines.push({ - line: line, - type: getType(line), - }); - } - // try to detect levels from description - let levels = []; - if (elevatorApi.description.search('<->') >= 0) { - levels = elevatorApi.description.split('<->').map(level => level.trim()); - } else if (elevatorApi.description.search('<>') >= 0) { - levels = elevatorApi.description.split('<>').map(level => level.trim()); - } else if (elevatorApi.description.search('/ ') >= 0) { - levels = elevatorApi.description.split('/ ').map(level => level.trim()); - } + const stations = internalData['stations']; - const elevator = { - working: elevatorApi['state'] === 1, - stateUnavailable: elevatorApi['state'] === -1, - dimensions: { - width: elevatorApi['cabinWidth'], - length: elevatorApi['cabinLength'], - door: elevatorApi['doorWidth'], - }, - description: elevatorApi['description'], - label: elevatorApi['label'], - type: elevatorApi['type'].replace('_', ' ').capitalize(), - braille: elevatorApi['tasterType'] === 'UNBEKANNT' ? -1 : elevatorApi['tasterType'] === 'KOMBI' || elevatorApi['tasterType'] === 'BRAILLE', - speaker: elevatorApi['tasterType'] === 'UNBEKANNT' ? -1 : elevatorApi['tasterType'] === 'KOMBI', - lines: elevatorLines, - levels: levels, - instCause: elevatorApi['instCause'], - osmNodeId: elevatorApi['osmId'], - } - - elevators.push(elevator); - } - - const stationTypes = getTypes(Array.from(lines)); + for (const stationIndex in stations) { + const station = stations[stationIndex]; let elevatorsTemplate = ''; let previewTemplate = ''; - let stationState = { - unavailable: 0, - working: 0, - outOfOrder: 0, - } - for (const elevator of elevators) { + + for (const elevator of station.elevators) { let linesTemplate = '
Linien: '; for (const line of elevator.lines) { linesTemplate += `${line.line}`; @@ -262,16 +257,45 @@ function renderData() { } levelsTemplate += ''; + let osmTemplate = ''; + if (osmData) { + const nodes = osmData.elements.filter(node => node.id === elevator.osmNodeId) + if (nodes.length) { + const nodeInfo = nodes[0]; + if (nodeInfo.hasOwnProperty('tags')) { + const tags = nodeInfo['tags']; + if (tags['highway'] === 'elevator') { + osmTemplate = '
'; + osmTemplate += `
Link zur Karte
+Auf Karte anzeigen +
`; + if (tags.hasOwnProperty('description')) { + osmTemplate += `
Beschreibung
${tags['description']}
`; + } + if (tags.hasOwnProperty('level')) { + osmTemplate += `
Ebenen
${tags['level'].split(';').sort().join(', ')}
`; + } + if (tags.hasOwnProperty('wheelchair')) { + osmTemplate += `
Rollstühle
${tags['wheelchair'] === 'yes' ? 'Ja' : 'Nein'}
`; + } + if (tags.hasOwnProperty('bicycle')) { + osmTemplate += `
Fahrräder
${tags['bicycle'] === 'yes' ? 'Ja' : 'Nein'}
`; + } + + osmTemplate += '
'; + } + } else { + osmTemplate = 'keine Daten'; + } + } else { + osmTemplate = 'keine Daten'; + } + } + + previewTemplate += `` - if (elevator.stateUnavailable) { - stationState.unavailable++; - } else if (elevator.working) { - stationState.working++; - } else { - stationState.outOfOrder++; - } elevatorsTemplate += `
  • Daten von OpenStreetMap

    + ${osmTemplate}
  • `; @@ -319,14 +344,14 @@ function renderData() { const template = `
  • - ${Array.from(stationTypes).sort().map(t => `${t}`).join('')} + ${station.types.sort().map(t => `${t}`).join('')}
    -

    ${stationName}

    +

    ${station.name}

    @@ -349,38 +374,39 @@ ${stationState.unavailable ? `Bei ${stationState.unavailable} ${stationState.una // .addEventListener('click', () => toggleElevatorList(stationId)) // }()); - - internalData[stationIndex++] = { - name: stationName, - state: stationState, - elevators: elevators, - } } } document.querySelector('#loadElevators') .addEventListener('click', (e) => { - loadElevators().then(() => renderData()); + loadElevators().then(() => { + renderData(); + filterData(); + }); }) document.querySelector('#loadOSM') .addEventListener('click', (e) => { - loadOsmData(); + loadOsmData().then(() => { + renderData(); + }); }) renderData(); -function filterData(searchString) { - for (const stationIndex in internalData) { - const matches = internalData[stationIndex].name.toLowerCase().search(searchString.toLowerCase()) >= 0; - document.querySelector(`#station_${stationIndex}`).classList.toggle('hidden', !matches); - +function filterData() { + const searchString = document.querySelector('#searchStation').value; + if (internalData) { + for (const stationIndex in internalData.stations) { + const matches = internalData.stations[stationIndex].name.toLowerCase().search(searchString.toLowerCase()) >= 0; + document.querySelector(`#station_${stationIndex}`).classList.toggle('hidden', !matches); + } } } document.querySelector('#searchStation').addEventListener('input', (e) => { - filterData(e.target.value); + filterData(); }) -filterData(document.querySelector('#searchStation').value) \ No newline at end of file +filterData() \ No newline at end of file