blob: dd433bf2f13d31a6fb0692c04d2d4df49d88c1b3 [file] [log] [blame]
/* (license-header)
* hores
* Copyright (c) 2023 Adrià Vilanova Martínez
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program.
* If not, see http://www.gnu.org/licenses/.
*/
/**
* Functions hasClass(), addClass() and removeClass() developed by Jake Trent (http://jaketrent.com/post/addremove-classes-raw-javascript/)
*/
function hasClass(el, className) {
if (el.classList)
return el.classList.contains(className)
else
return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
}
function addClass(el, className) {
if (el.classList)
el.classList.add(className)
else if (!hasClass(el, className)) el.className += " " + className
}
function removeClass(el, className) {
if (el.classList)
el.classList.remove(className)
else if (hasClass(el, className)) {
var reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
el.className=el.className.replace(reg, ' ')
}
}
// MultiSelect implementation:
var MultiSelect = function MultiSelect(element) {
this.element_ = element;
this.selected_ = [];
var forElId = this.element_.getAttribute("for") || this.element_.getAttribute("data-for");
if (forElId) {
this.forEl_ = (forElId ? document.getElementById(this.element_.getAttribute("for")) : null);
}
this.init();
};
MultiSelect.prototype.renderSummary = function() {
if (this.forEl_) {
this.forEl_.innerText = this.selected_.join(", ") || "-";
}
};
MultiSelect.prototype.init = function() {
if (this.element_) {
this.element_.addEventListener("click", e => {
e.stopImmediatePropagation();
}, true);
this.element_.querySelectorAll(".mdl-custom-multiselect__item").forEach(item => {
var checkbox = item.querySelector("input[type=\"checkbox\"]");
var label = item.querySelector(".mdl-checkbox__label").innerText;
checkbox.addEventListener("change", e => {
if(checkbox.checked) {
this.selected_.push(label);
} else {
this.selected_ = this.selected_.filter(item => item !== label);
}
this.renderSummary();
var customEvent = new Event('custom-multiselect-change');
this.element_.dispatchEvent(customEvent);
});
});
}
};
var dynDialog = {
didItInit: false,
dialog: null,
url: null,
load: function(url, reload) {
if (this.didItInit === false) {
this.init();
}
if (this.url == url && reload !== true) {
this.show();
return;
}
this.url = url;
fetch(url).then(response => response.text()).then(response => {
if (this.dialog.open) {
this.close();
}
this.dialog.innerHTML = response;
componentHandler.upgradeElements(this.dialog);
this.dialog.querySelectorAll("[data-required]").forEach(input => {
input.setAttribute("required", "true");
});
var script = this.dialog.querySelectorAll("dynscript");
if (script.length > 0) {
for (var i = 0; i < script.length; i++) {
eval(script[i].innerText);
}
}
this.dialog.querySelectorAll("[data-dyndialog-close]").forEach(btn => {
btn.addEventListener("click", e => {
e.preventDefault();
this.close();
});
});
this.dialog.showModal();
});
},
reload: function() {
this.load(this.url, true);
},
show: function() {
this.dialog.showModal();
},
close: function() {
this.dialog.close();
},
init: function() {
this.dialog = document.createElement("dialog");
this.dialog.setAttribute("id", "dynDialog");
this.dialog.setAttribute("class", "mdl-dialog");
dialogPolyfill.registerDialog(this.dialog);
document.body.appendChild(this.dialog);
this.didItInit = true;
}
};
// From nodep-date-input-polyfill
function isDateInputSupported() {
const input = document.createElement("input");
input.setAttribute("type", "date");
const notADateValue = "not-a-date";
input.setAttribute("value", notADateValue);
return (input.value !== notADateValue);
}
document.addEventListener("DOMContentLoaded", function() {
var dialogs = document.querySelectorAll("dialog");
for (var i = 0; i < dialogs.length; i++) {
dialogPolyfill.registerDialog(dialogs[i]);
}
document.querySelectorAll("[data-dyndialog-href]").forEach(link => {
link.addEventListener("click", e => {
e.preventDefault();
dynDialog.load(link.getAttribute("data-dyndialog-href"));
});
});
document.querySelectorAll(".mdl-custom-multiselect-js").forEach(menu => {
new MultiSelect(menu);
});
});
function importCSS(url) {
var link = document.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("href", url);
document.head.appendChild(link);
}
var loadScriptAsync = function(uri) {
return new Promise((resolve, reject) => {
var script = document.createElement('script');
script.src = uri;
script.async = true;
script.onload = () => {
resolve();
};
document.head.appendChild(script);
});
}
function hasParentDialog(el) {
while (el != document.documentElement) {
if (el.tagName == "DIALOG") {
return el;
}
el = el.parentNode;
}
return undefined;
}
function polyfillDateSupport(container) {
container.querySelectorAll("input[type=\"date\"]").forEach(el => {
el.setAttribute("type", "text");
dialogParent = hasParentDialog(el);
var options = {
format: "yyyy-mm-dd",
todayHighlight: true,
weekStart: 1,
zIndexOffset: 100,
container: dialogParent || container
};
if (el.hasAttribute("max")) {
options.endDate = el.getAttribute("max");
}
$(el).datepicker(options);
});
container.querySelectorAll("input[type=\"time\"]").forEach(el => {
el.setAttribute("placeholder", "hh:mm");
});
}
function initPolyfillDateSupport() {
console.info("Polyfilling date support");
importCSS("https://unpkg.com/bootstrap-datepicker@1.9.0/dist/css/bootstrap-datepicker3.standalone.min.css", "css");
loadScriptAsync("https://unpkg.com/jquery@3.4.1/dist/jquery.min.js", "js").then(_ => {
return loadScriptAsync("https://unpkg.com/bootstrap-datepicker@1.9.0/dist/js/bootstrap-datepicker.min.js");
}).then(_ => {
return loadScriptAsync("https://unpkg.com/bootstrap-datepicker@1.9.0/dist/locales/bootstrap-datepicker.es.min.js");
}).then(_ => {
console.log("[Date polyfill] Scripts loaded.");
polyfillDateSupport(document.documentElement);
});
}
window.addEventListener("load", function() {
document.querySelectorAll("[data-required]").forEach(input => {
input.setAttribute("required", "true");
});
if (!isDateInputSupported()) {
initPolyfillDateSupport();
}
});