aed-mapa/web/js/other-ui-stuff.js

470 wiersze
18 KiB
JavaScript

const sidebarDivId = 'sidebar-div';
const sidebar2DivId = 'sidebar2-div';
const sidebarHeaderId = 'sidebar-header';
const sidebarCaptionId = 'sidebar-caption';
const sidebarContentDivId = 'sidebar-content-div';
const sidebarFooterButtonLeftId = 'sidebar-footer-button-left';
const sidebarButtonCloseIds = ['sidebar-button-close-touch', 'sidebar-button-close-desktop'];
const sidebar2ButtonCloseIds = ['sidebar2-button-close-touch', 'sidebar2-button-close-desktop'];
const formPhoneFieldId = 'form-phone';
const formLocationFieldId = 'form-location';
const formLocationEnFieldId = 'form-location-en';
const formIndoorFieldId = 'form-indoor';
const formEmergencyPhoneFieldId = 'form-emergency-phone';
let sidebarHeader = document.getElementById(sidebarHeaderId);
let sidebarCaption = document.getElementById(sidebarCaptionId);
let sidebarContent = document.getElementById(sidebarContentDivId);
let sidebarLink = document.getElementById(sidebarFooterButtonLeftId);
const accessToColourMapping = {
'yes': 'has-background-green',
'no': 'has-background-grey',
'private': 'has-background-grey',
'permissive': 'has-background-link-dark',
'default': 'has-background-grey',
};
const accessToDescriptionMapping = {
'yes': 'ogólnodostępny',
'no': 'prywatny',
'private': 'prywatny',
'permissive': 'o ograniczonym dostępie',
'default': '',
};
const indoorMapping = {
'yes': 'tak',
'no': 'nie',
'default': '',
};
const locationMapping = {
'indoor': 'tak',
'outdoor': 'nie',
'default': '',
};
// --------------------------------------------------------------------------------------
function defineColor(access) {
return accessToColourMapping[access] || accessToColourMapping['default'];
}
function defineAccessDescription(access) {
return accessToDescriptionMapping[access] || accessToDescriptionMapping['default'];
}
function defineIndoor(indoor) {
return indoorMapping[indoor] || indoorMapping['default'];
}
function defineLocationIndoor(location) {
return locationMapping[location] || locationMapping['default'];
}
function getOsmEditLink(id) {
return `https://www.openstreetmap.org/edit?editor=id&node=${id}`;
}
function getOsmPreviewLink(id) {
return `https://www.openstreetmap.org/node/${id}`;
}
function parseOpeningHours(openingHours) {
if (openingHours) {
if (openingHours.includes('24/7')) {
return 'całodobowo';
} else {
let hoursPrettified;
try {
let hours = openingHours.toString();
let oh = new opening_hours(hours, undefined, 2);
isOpen = oh.getState();
hoursPrettified = oh.prettifyValue({
conf: {
locale: 'pl'
},
});
} catch (error) {
console.log('Error when parsing opening hours');
return undefined;
}
return hoursPrettified;
}
} else {
return undefined;
}
}
function isCurrentlyOpen(openingHours) {
if (openingHours) {
if (openingHours.includes('24/7')) {
return true;
} else {
let hours = openingHours.toString();
let oh = new opening_hours(hours, undefined, 2);
isOpen = oh.getState();
return isOpen;
}
}
}
function renderCurrentlyOpenStatus(openingHours) {
if (isCurrentlyOpen(openingHours)) {
return '<sup class="pl-1"><span class="tag is-success is-light">Dostępny</span></sup>';
} else {
return '<sup class="pl-1"><span class="tag is-danger is-light">Niedostępny</span></sup>';
}
}
function renderIfIndoor(indoor, location) {
let beginning = '<p class="has-text-weight-light">Wewnątrz budynku?: <span class="add-new has-text-weight-medium">';
let middle = defineLocationIndoor(location) || defineIndoor(indoor) || '<span class="has-text-grey-light is-italic has-text-weight-light">brak informacji</span>';
let end = '</span></p>';
return beginning + middle + end;
}
function renderLocation(properties) {
let beginning = '<p class="has-text-weight-light">Dokładna lokalizacja: <span class="add-new has-text-weight-medium">';
let middle = properties['defibrillator_location_pl'] || properties['defibrillator_location'] || '<span class="has-text-grey-light is-italic has-text-weight-light">brak informacji</span>';
let end = '</span></p>';
return beginning + middle + end;
}
function renderDescription(properties) {
let beginning = '<p class="has-text-weight-light">Opis: <span class="add-new has-text-weight-medium">';
let middle = properties['description_pl'] || properties.description || '<span class="has-text-grey-light is-italic has-text-weight-light">brak informacji</span>';
let end = '</span></p>';
return beginning + middle + end;
}
function renderContactNumber(phone) {
let beginning = '<p class="has-text-weight-light">Numer kontaktowy: <span class="add-new has-text-weight-medium">';
let middle = phone || '<span class="has-text-grey-light is-italic has-text-weight-light">brak informacji</span>';
let end = '</span></p>';
return beginning + middle + end;
}
function renderAccessibleTime(openingHours) {
if (openingHours) {
let beginning = '<p class="has-text-weight-light">Dostępny w godzinach: <span class="add-new has-text-weight-medium">';
let middle = parseOpeningHours(openingHours) || '<span class="has-text-grey-light is-italic has-text-weight-light">brak informacji </span>';
let end = (renderCurrentlyOpenStatus(openingHours) || '') + '</span></p>';
return beginning + middle + end;
} else {
return '';
}
}
function renderNotes(properties) {
if (properties.note || properties['note_pl']) {
let beginning = '<p class="has-text-weight-light">Uwagi: <span class="add-new has-text-weight-medium">';
let middle = properties['note_pl'] || properties.note || 'brak uwag';
let end = '</span></p>';
return beginning + middle + end;
} else {
return '';
}
}
function renderOperator(operator)
{
let beginning = '<p class="has-text-weight-light">Zarządzający urządzeniem: <span class="add-new has-text-weight-medium">';
let middle = operator || '<span class="has-text-grey-light is-italic has-text-weight-light">brak informacji</span>';
let end = '</span></p>';
return beginning + middle + end;
}
function renderSidebarContent(properties) {
let content = '';
content += renderIfIndoor(properties.indoor, properties.location);
content += renderLocation(properties);
content += renderAccessibleTime(properties.opening_hours);
content += renderDescription(properties);
content += renderContactNumber(properties.phone);
content += renderOperator(properties.operator);
content += renderNotes(properties);
return content;
}
function renderSidebarForm() {
let content = `
<form>
<label class="label has-text-weight-semibold">Rodzaj dostępności:</label>
<div class="field">
<input class="is-checkradio is-success" id="accessRadio1" type="radio" name="aedAccess" value="yes" tag="access">
<label for="accessRadio1">Publicznie dostępny</label>
</div>
<div class="field">
<input class="is-checkradio is-success" id="accessRadio2" type="radio" name="aedAccess" value="private" tag="access">
<label for="accessRadio2">Dostępny za zgodą właściciela</label>
</div>
<div class="field">
<input class="is-checkradio is-success" id="accessRadio3" type="radio" name="aedAccess" value="customers" tag="access">
<label for="accessRadio3">Dostępny tylko w godzinach pracy</label>
</div>
<label class="label has-text-weight-semibold pt-2">Czy wewnątrz budynku?</label>
<div class="field">
<input class="is-checkradio is-success" id="indoorRadio1" type="radio" name="aedIndoor" value="no" tag="indoor">
<label for="indoorRadio1">Na zewnątrz</label>
<input class="is-checkradio is-success" id="indoorRadio2" type="radio" name="aedIndoor" value="yes" tag="indoor">
<label for="indoorRadio2">W budynku</label>
</div>
<div class="field pt-2">
<label class="label has-text-weight-semibold">Szczegółowy opis lokalizacji defibrylatora</label>
<div class="control">
<textarea id="${formLocationFieldId}" tag="defibrillator:location" class="textarea is-success" rows="1"
placeholder="Na przykład: Na ścianie przy wejściu"></textarea>
</div>
</div>
<div class="field">
<label class="label has-text-weight-semibold">Opis lokalizacji defibrylatora po angielsku</label>
<div class="control">
<textarea id="${formLocationEnFieldId}" tag="defibrillator:location:en" class="textarea is-success" rows="1"
placeholder="For example: On the wall near entrance"></textarea>
</div>
<p class="help has-text-weight-light">Pole opcjonalne</p>
</div>
<div class="field-body">
<div class="field">
<label class="label has-text-weight-semibold">Telefon kontaktowy operatora</label>
<div class="control">
<input id="${formPhoneFieldId}" tag="phone" class="input is-success" type="text" placeholder="+48 123 456 789"
pattern="^[+][0-9]{2}[ ]?((?:[0-9]{9})|(?:[0-9]{3} [0-9]{3} [0-9]{3})|(?:[0-9]{2} [0-9]{3} [0-9]{2} [0-9]{2}))$">
</div>
<p class="help has-text-weight-light">Pole opcjonalne</p>
</div>
<div class="field">
<label class="label has-text-weight-semibold">Numer ratunkowy danego obszaru</label>
<div class="control">
<input id="${formEmergencyPhoneFieldId}" tag="emergency:phone" class="input is-success" type="text" placeholder="+48 123 456 789"
pattern="^[+][0-9]{2}[ ]?((?:[0-9]{9})|(?:[0-9]{3} [0-9]{3} [0-9]{3})|(?:[0-9]{2} [0-9]{3} [0-9]{2} [0-9]{2}))$">
</div>
<p class="help has-text-weight-light">Pole opcjonalne. Wypełnij tylko, jeżeli jest inny niż 112/999.</p>
</div>
</div>
<form>
`;
return content;
}
function renderEditButton(osm_id) {
return `
<a href="${getOsmEditLink(osm_id)}" target="_blank" rel="noopener" id="edit-poi" class="button is-small is-pulled-right is-success">
<svg class="icon" viewBox="0 0 24 24">
<path fill="currentColor" d="M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z" />
</svg>
Uzupełnij dane&nbsp;<sup class="has-text-weight-light">(iD)</sup>
</button>`;
}
function renderPreviewButton(osm_id) {
return `
<a href="${getOsmPreviewLink(osm_id)}" target="_blank" rel="noopener" id="preview-poi" class="button is-small mr-1 is-pulled-right is-success">
<svg class="icon mr-1" viewBox="0 0 24 24">
<path fill="currentColor" d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
</svg>
Podgląd w OSM
</button>`;
}
function renderSaveButton() {
return `
<button id="sidebar-save-button" class="button is-success is-fullwidth" onclick="saveNode(prepareNodeData())">
Dodaj AED
</button>
<div class="is-hidden-desktop">
<span class="has-text-weight-light has-text-grey-light is-size-7 pt-1 is-pulled-right">ver. 0.1</span>
</div>`;
}
// --------------------------------------------------------------
function prepareNodeData() {
let data = {};
// get coordinates
let markerPosition = marker.getLngLat();
data.lng = markerPosition.lng;
data.lat = markerPosition.lat;
// get additional tags
data.tags = {};
let formPhoneField = document.getElementById(formPhoneFieldId);
let formLocationField = document.getElementById(formLocationFieldId);
let formEmergencyPhoneField = document.getElementById(formEmergencyPhoneFieldId);
let formLocationEnField = document.getElementById(formLocationEnFieldId);
let formAccessField = document.querySelector('input[name="aedAccess"]:checked');
let formIndoorField = document.querySelector('input[name="aedIndoor"]:checked');
if (formIndoorField && formIndoorField.getAttribute('value'))
data.tags[formIndoorField.getAttribute('tag')] = formIndoorField.getAttribute('value');
if (formPhoneField && formPhoneField.value.trim()) data.tags[formPhoneField.getAttribute('tag')] = formPhoneField.value.trim();
if (formLocationField && formLocationField.value.trim()) data.tags[formLocationField.getAttribute('tag')] = formLocationField.value.trim();
if (formEmergencyPhoneField && formEmergencyPhoneField.value.trim()) data.tags[formEmergencyPhoneField.getAttribute('tag')] = formEmergencyPhoneField.value.trim();
if (formLocationEnField && formLocationEnField.value.trim()) data.tags[formLocationEnField.getAttribute('tag')] = formLocationEnField.value.trim();
if (formAccessField && formAccessField.getAttribute('value'))
data.tags[formAccessField.getAttribute('tag')] = formAccessField.getAttribute('value');
return data;
}
function removeMarkerIfExists() {
if (marker !== null) {
marker.remove();
marker = null;
}
}
function closeNavBurger() {
document.getElementById('navMenu').classList.remove('is-active');
document.getElementsByClassName('navbar-burger')[0].classList.remove('is-active');
}
function showSidebar(properties) {
let sidebar = document.getElementById(sidebarDivId);
if (sidebar) {
sidebar.classList.remove('is-invisible');
if (properties.action === "showDetails") {
prepareSidebarShowingObjectInfo(properties.data);
removeMarkerIfExists();
} else if (properties.action === "addNode") {
prepareSidebarAddingNode(properties.data);
} else {
console.log(`Unknown action: ${properties.action}.`);
}
hideSidebar2();
closeNavBurger();
} else
console.log('Sidebar not found.');
}
function toggleSidebar2() {
let sidebar = document.getElementById(sidebar2DivId);
if (sidebar.classList.contains('is-invisible')) {
showSidebar2();
} else {
sidebar.classList.add('is-invisible');
}
}
function showSidebar2() {
let sidebar = document.getElementById(sidebar2DivId);
if (sidebar) {
sidebar.classList.remove('is-invisible');
hideSidebar();
closeNavBurger();
} else
console.log('Sidebar not found.');
}
function hideSidebar() {
let sidebar = document.getElementById(sidebarDivId);
if (sidebar) {
sidebar.classList.add('is-invisible');
removeMarkerIfExists();
// restore buttons
let mobileButton1 = document.getElementById('addNode-mobile-1');
let mobileButton2 = document.getElementById('addNode-mobile-2');
let mobileButton3 = document.getElementById('addNode-mobile-3');
mobileButton1.classList.remove('is-hidden');
mobileButton2.classList.add('is-hidden');
mobileButton3.classList.add('is-hidden');
} else {
console.log('Sidebar not found.');
}
}
function hideSidebar2() {
let sidebar = document.getElementById(sidebar2DivId);
if (sidebar) {
sidebar.classList.add('is-invisible');
} else {
console.log('Sidebar not found.');
}
}
function prepareSidebarShowingObjectInfo(properties) {
sidebarHeader.classList = ['p-2'];
sidebarHeader.classList.add(defineColor(properties.access));
sidebarCaption.innerHTML = `defibrylator AED ${defineAccessDescription(properties.access)}`;
sidebarContent.innerHTML = renderSidebarContent(properties);
sidebarLink.innerHTML = renderEditButton(properties.osm_id);
sidebarLink.innerHTML += renderPreviewButton(properties.osm_id);
}
function prepareSidebarAddingNode(properties) {
sidebarHeader.classList = ['p-2'];
sidebarHeader.classList.add(defineColor('default'));
sidebarCaption.innerHTML = 'Dodaj defibrylator';
sidebarContent.innerHTML = renderSidebarForm();
sidebarLink.innerHTML = renderSaveButton();
}
// --------------------------------------------------------------------------------------
// Bulma controls
document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Check if there are any navbar burgers
if ($navbarBurgers.length > 0) {
// Add a click event on each of them
$navbarBurgers.forEach(el => {
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
});
}
// add listeners to buttons opening modals
// Add a click event on buttons to open a specific modal
(document.querySelectorAll('.js-modal-trigger') || []).forEach(($trigger) => {
const modal = $trigger.dataset.target;
const $target = document.getElementById(modal);
$trigger.addEventListener('click', () => {
$target.classList.add('is-active');
});
});
// Add a click event on various child elements to close the parent modal
(document.querySelectorAll('.modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .button') || []).forEach(($close) => {
const $target = $close.closest('.modal');
$close.addEventListener('click', () => {
$target.classList.remove('is-active');
});
});
if (window.innerWidth > 1024) {
showSidebar2();
}
});
// button listeners
sidebarButtonCloseIds.forEach(id => {
document.getElementById(id).addEventListener('click', hideSidebar);
});
sidebar2ButtonCloseIds.forEach(id => {
document.getElementById(id).addEventListener('click', hideSidebar2);
});