232 lines
7.1 KiB
JavaScript
232 lines
7.1 KiB
JavaScript
/**
|
|
* SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
function ready(fn) {
|
|
if (document.readyState !== 'loading') {
|
|
fn();
|
|
} else {
|
|
document.addEventListener('DOMContentLoaded', fn);
|
|
}
|
|
}
|
|
|
|
ready(function () {
|
|
const snackBar = Object.assign(document.body.appendChild(document.createElement('section')), {
|
|
id: 'snackbar',
|
|
});
|
|
|
|
const errorMessage = snackBar.appendChild(document.createElement('div'));
|
|
errorMessage.setAttribute('role', 'alert');
|
|
|
|
const openClass = 'open';
|
|
const toasts = [];
|
|
let timeoutId = null;
|
|
|
|
function showError(message) {
|
|
toasts.push(message);
|
|
popUp();
|
|
}
|
|
|
|
function popUp() {
|
|
if (toasts.length === 0) {
|
|
return;
|
|
}
|
|
if (errorMessage.classList.contains(openClass)) {
|
|
dismiss();
|
|
return;
|
|
}
|
|
if (errorMessage.innerText !== "") {
|
|
// it will show after remove calls popUp again.
|
|
return;
|
|
}
|
|
errorMessage.innerText = toasts[0];
|
|
errorMessage.classList.add(openClass);
|
|
timeoutId = setTimeout(dismiss, 4000);
|
|
}
|
|
|
|
function dismiss() {
|
|
if (!errorMessage.classList.contains(openClass)) {
|
|
// already dismissed
|
|
return;
|
|
}
|
|
errorMessage.classList.remove(openClass);
|
|
clearTimeout(timeoutId);
|
|
timeoutId = setTimeout(remove, 350);
|
|
}
|
|
|
|
function remove() {
|
|
clearTimeout(timeoutId);
|
|
toasts.splice(0, 1);
|
|
errorMessage.innerText = "";
|
|
popUp();
|
|
}
|
|
|
|
document.body.addEventListener('htmx:error', function (evt) {
|
|
const errorInfo = evt.detail.errorInfo;
|
|
const error = errorInfo.xhr && errorInfo.xhr.responseText || errorInfo.error;
|
|
showError(error);
|
|
});
|
|
})
|
|
|
|
ready(function () {
|
|
const textareas = document.querySelectorAll('textarea.html');
|
|
if (textareas.length > 0) {
|
|
const language = document.documentElement.getAttribute('lang');
|
|
const script = document.head.appendChild(Object.assign(document.createElement('script'), {
|
|
src: '/static/ckeditor5@40.0.0/ckeditor.js',
|
|
}));
|
|
if (language !== 'en') {
|
|
document.head.appendChild(Object.assign(document.createElement('script'), {
|
|
src: '/static/ckeditor5@39.0.1/translations/' + language + '.js',
|
|
}));
|
|
}
|
|
script.addEventListener('load', function () {
|
|
for (const textarea of textareas) {
|
|
const canvas = document.createElement('div');
|
|
textarea.parentNode.insertBefore(canvas, textarea.nextSibling);
|
|
textarea.style.display = 'none';
|
|
|
|
ClassicEditor
|
|
.create(canvas, {
|
|
language,
|
|
})
|
|
.then(editor => {
|
|
const xml = document.createElement('div');
|
|
const serializer = new XMLSerializer();
|
|
editor.setData(textarea.value);
|
|
editor.ui.focusTracker.on('change:isFocused', (event, name, focused) => {
|
|
if (!focused) {
|
|
xml.innerHTML = editor.getData();
|
|
textarea.value = serializer.serializeToString(xml).replace(' ', ' ');
|
|
}
|
|
});
|
|
})
|
|
.catch(error => {
|
|
console.error(error);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
})
|
|
|
|
export function camperUploadForm(el) {
|
|
const progress = el.querySelector('progress');
|
|
htmx.on(el, 'drop', function (evt) {
|
|
evt.preventDefault();
|
|
[...evt.dataTransfer.items].forEach(function (i) {
|
|
console.log(i);
|
|
i.getAsString(console.log)
|
|
});
|
|
});
|
|
htmx.on(el, 'dragover', function (evt) {
|
|
evt.preventDefault();
|
|
});
|
|
htmx.on(el, 'dragleave', function (evt) {
|
|
evt.preventDefault();
|
|
});
|
|
htmx.on(el, 'htmx:xhr:progress', function (evt) {
|
|
if (progress && evt.detail.lengthComputable) {
|
|
progress.setAttribute('value', evt.detail.loaded / evt.detail.total * 100);
|
|
}
|
|
});
|
|
}
|
|
|
|
export function setupCampgroundMap(map) {
|
|
if (!map) {
|
|
return;
|
|
}
|
|
const prefix = "cp_";
|
|
for (const campsite of Array.from(map.querySelectorAll(`[id^="${prefix}"]`))) {
|
|
const label = campsite.id.substring(prefix.length);
|
|
if (!label) {
|
|
continue;
|
|
}
|
|
const link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
|
|
link.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '/admin/campsites/' + label);
|
|
link.append(...campsite.childNodes);
|
|
campsite.appendChild(link);
|
|
}
|
|
}
|
|
|
|
export function setupIconInput(icon) {
|
|
if (!icon) {
|
|
return;
|
|
}
|
|
const input = icon.querySelector('input[type="hidden"]')
|
|
if (!input) {
|
|
return;
|
|
}
|
|
const buttons = Array.from(icon.querySelectorAll('button[data-icon-name]'));
|
|
const updateValue = function (iconName) {
|
|
input.value = iconName;
|
|
for (const button of buttons) {
|
|
button.setAttribute('aria-pressed', button.dataset.iconName === iconName);
|
|
}
|
|
}
|
|
for (const button of buttons) {
|
|
button.addEventListener('click', function (e) {
|
|
updateValue(e.target.dataset.iconName);
|
|
})
|
|
}
|
|
updateValue(input.value);
|
|
}
|
|
|
|
export function setupCalendar(calendar) {
|
|
const startDate = calendar.querySelector('input[name="start_date"]');
|
|
const endDate = calendar.querySelector('input[name="end_date"]');
|
|
const days = Array.from(calendar.querySelectorAll('time'));
|
|
const dialog = calendar.querySelector('dialog');
|
|
|
|
const clear = function () {
|
|
console.log('yolo');
|
|
startDate.value = endDate.value = "";
|
|
days.forEach((e) => e.removeAttribute('aria-checked'));
|
|
}
|
|
|
|
dialog.addEventListener('close', clear);
|
|
dialog.querySelector('button').addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
dialog.close();
|
|
});
|
|
|
|
const selectDate = function (e) {
|
|
e.preventDefault();
|
|
const date = e.currentTarget.dateTime;
|
|
if (!date) {
|
|
return;
|
|
}
|
|
if (!startDate.value) {
|
|
startDate.value = date;
|
|
e.currentTarget.setAttribute('aria-checked', true);
|
|
return;
|
|
} else if (startDate.value > date) {
|
|
endDate.value = startDate.value;
|
|
startDate.value = date;
|
|
} else {
|
|
endDate.value = date;
|
|
}
|
|
for (const day of days) {
|
|
if (day.dateTime >= startDate.value && day.dateTime <= endDate.value) {
|
|
day.setAttribute('aria-checked', true);
|
|
} else {
|
|
day.removeAttribute('aria-checked');
|
|
}
|
|
}
|
|
dialog.showModal();
|
|
}
|
|
|
|
for (const day of days) {
|
|
day.addEventListener('click', selectDate);
|
|
}
|
|
|
|
clear();
|
|
}
|
|
|
|
htmx.onLoad((target) => {
|
|
if (target.tagName === 'DIALOG') {
|
|
target.showModal();
|
|
}
|
|
})
|
|
|