only render Elements in renderData

This commit is contained in:
kritzl 2024-06-04 16:08:44 +02:00
parent dc84436346
commit 7673265167

View file

@ -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", '<dl class="osmTags">loading...</dl>');
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 += `<div><dt><span data-icon="location" class="size-l"></span>Link zur Karte</dt><dd><a href="https://www.openstreetmap.org/node/${nodeId}" target="_blank">
Auf Karte anzeigen
</a></dd></div>`;
if (tags.hasOwnProperty('description')) {
osmTemplate += `<div><dt><span data-icon="info" class="size-l"></span>Beschreibung</dt><dd>${tags['description']}</dd></div>`;
}
if (tags.hasOwnProperty('level')) {
osmTemplate += `<div><dt><span data-icon="up-down" class="size-l"></span>Ebenen</dt><dd>${tags['level'].split(';').sort().join(', ')}</dd></div>`;
}
if (tags.hasOwnProperty('wheelchair')) {
osmTemplate += `<div><dt><span data-icon="wheelchair" class="size-l"></span>Rollstühle</dt><dd>${tags['wheelchair'] === 'yes' ? 'Ja' : 'Nein'}</dd></div>`;
}
if (tags.hasOwnProperty('bicycle')) {
osmTemplate += `<div><dt><span data-icon="bicycle" class="size-l"></span>Fahrräder</dt><dd>${tags['bicycle'] === 'yes' ? 'Ja' : 'Nein'}</dd></div>`;
}
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 = '<div class="lineList">Linien: ';
for (const line of elevator.lines) {
linesTemplate += `<span data-type="${line.type}" data-line="${line.line}" class="lineChip">${line.line}</span>`;
@ -262,16 +257,45 @@ function renderData() {
}
levelsTemplate += '</ol>';
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 = '<dl>';
osmTemplate += `<div><dt><span data-icon="location" class="size-l"></span>Link zur Karte</dt><dd><a href="https://www.openstreetmap.org/node/${elevator.osmNodeId}" target="_blank">
Auf Karte anzeigen
</a></dd></div>`;
if (tags.hasOwnProperty('description')) {
osmTemplate += `<div><dt><span data-icon="info" class="size-l"></span>Beschreibung</dt><dd>${tags['description']}</dd></div>`;
}
if (tags.hasOwnProperty('level')) {
osmTemplate += `<div><dt><span data-icon="up-down" class="size-l"></span>Ebenen</dt><dd>${tags['level'].split(';').sort().join(', ')}</dd></div>`;
}
if (tags.hasOwnProperty('wheelchair')) {
osmTemplate += `<div><dt><span data-icon="wheelchair" class="size-l"></span>Rollstühle</dt><dd>${tags['wheelchair'] === 'yes' ? 'Ja' : 'Nein'}</dd></div>`;
}
if (tags.hasOwnProperty('bicycle')) {
osmTemplate += `<div><dt><span data-icon="bicycle" class="size-l"></span>Fahrräder</dt><dd>${tags['bicycle'] === 'yes' ? 'Ja' : 'Nein'}</dd></div>`;
}
osmTemplate += '<dl>';
}
} else {
osmTemplate = 'keine Daten';
}
} else {
osmTemplate = 'keine Daten';
}
}
previewTemplate += `<span data-icon="${elevator.working || elevator.stateUnavailable ? 'elevator' : 'elevator-slash'}"
class="size-l ${elevator.working ? 'text-green' : elevator.stateUnavailable ? 'text-orange' : 'text-red'}"></span>`
if (elevator.stateUnavailable) {
stationState.unavailable++;
} else if (elevator.working) {
stationState.working++;
} else {
stationState.outOfOrder++;
}
elevatorsTemplate += `<li class="elevator">
<span data-icon="${elevator.working || elevator.stateUnavailable ? 'elevator' : 'elevator-slash'}"
@ -311,6 +335,7 @@ function renderData() {
${elevator.lines.length ? `${linesTemplate}` : ''}
<div class="osm" data-nodeid="${elevator.osmNodeId}">
<h4>Daten von OpenStreetMap</h4>
${osmTemplate}
</div>
</div>
</li>`;
@ -319,14 +344,14 @@ function renderData() {
const template = `<li class="station" id="station_${stationIndex}">
<div class="stationSummary">
<div class="typeList">
${Array.from(stationTypes).sort().map(t => `<span class="typeChip" data-type="${t}">${t}</span>`).join('')}
${station.types.sort().map(t => `<span class="typeChip" data-type="${t}">${t}</span>`).join('')}
</div>
<div class="stationTitle">
<h3>${stationName}</h3>
<h3>${station.name}</h3>
<div class="elevator-preview" role="img"
aria-label="${stationState.working ? `${stationState.working} ${stationState.working > 1 ? 'Aufzüge sind' : 'Aufzug ist'} funktionstüchtig.` : ''}
${stationState.outOfOrder ? `${stationState.outOfOrder} ${stationState.outOfOrder > 1 ? 'Aufzüge sind' : 'Aufzug ist'} außer Betrieb.` : ''}
${stationState.unavailable ? `Bei ${stationState.unavailable} ${stationState.unavailable > 1 ? 'Aufzügen' : 'Aufzug'} ist der Funktionsstatus unbekannt.` : ''}">
aria-label="${station.state.working ? `${station.state.working} ${station.state.working > 1 ? 'Aufzüge sind' : 'Aufzug ist'} funktionstüchtig.` : ''}
${station.state.outOfOrder ? `${station.state.outOfOrder} ${station.state.outOfOrder > 1 ? 'Aufzüge sind' : 'Aufzug ist'} außer Betrieb.` : ''}
${station.state.unavailable ? `Bei ${station.state.unavailable} ${station.state.unavailable > 1 ? 'Aufzügen' : 'Aufzug'} ist der Funktionsstatus unbekannt.` : ''}">
${previewTemplate}
</div>
</div>
@ -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)
filterData()