307 lines
10 KiB
JavaScript
307 lines
10 KiB
JavaScript
// bulma hamburger menu
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
// Get all "navbar-burger" elements
|
|
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 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');
|
|
});
|
|
});
|
|
});
|
|
|
|
// language selector
|
|
document.getElementById("current-language").addEventListener("click", (e) => {
|
|
e.preventDefault();
|
|
document.getElementById("language-dropdown").classList.toggle("is-active");
|
|
});
|
|
|
|
const i18n = JSON.parse(document.getElementById("i18n-data").textContent);
|
|
const i18nSupported = Object.keys(i18n._flags)
|
|
|
|
// build language selector
|
|
const langSelector = document.getElementById("language-selector")
|
|
for (const l of i18nSupported) {
|
|
const a = document.createElement("a");
|
|
a.classList.add("navbar-item");
|
|
a.innerHTML = `${i18n._flags[l]} ${l.toUpperCase()}`;
|
|
a.href = "#";
|
|
a.addEventListener("click", (e) => {
|
|
changeLanguage(e.target.textContent.slice(-2).toLowerCase());
|
|
document.getElementById("language-dropdown").classList.remove("is-active");
|
|
});
|
|
langSelector.appendChild(a);
|
|
}
|
|
|
|
changeLanguage = (l) => {
|
|
const lang = i18nSupported.includes(l) ? l : "en";
|
|
console.log(`Switching language to ${lang}`);
|
|
document.querySelectorAll("[data-i18n]").forEach(el => {
|
|
el.innerHTML = i18n[el.dataset.i18n][lang];
|
|
});
|
|
document.getElementById("current-language").innerHTML = `${i18n._flags[lang]} ${lang.toUpperCase()}`;
|
|
document.documentElement.lang = lang;
|
|
saveFormData();
|
|
};
|
|
|
|
saveFormData = () => {
|
|
localStorage.setItem("bezahlbrudiFormData", JSON.stringify({
|
|
name: document.querySelector("#name input").value,
|
|
iban: document.querySelector("#iban input").value.toUpperCase(),
|
|
bic: document.querySelector("#bic input").value.toUpperCase(),
|
|
amount: parseFloat(document.querySelector("#amount input").value).toFixed(2),
|
|
purpose: document.querySelector("#purpose input").value,
|
|
lang: document.getElementById("current-language").textContent.slice(-2).toLowerCase()
|
|
}));
|
|
}
|
|
|
|
// Field data checks
|
|
|
|
validateName = (target) => {
|
|
if (target.value.length == 0) return
|
|
if (target.value.length > 0 && target.value.length <= 70) {
|
|
target.classList.remove("is-danger")
|
|
document.querySelector("#name div span").innerHTML = "✅";
|
|
if (document.querySelector("#name p")) {
|
|
document.querySelector("#name p").remove();
|
|
}
|
|
} else {
|
|
target.classList.add("is-danger")
|
|
document.querySelector("#name div span").innerHTML = "❌";
|
|
|
|
if (!document.querySelector("#name p")) {
|
|
const help = document.createElement("p");
|
|
help.classList.add("help", "is-danger");
|
|
help.textContent = "Name can only have 70 characters.";
|
|
document.querySelector("#name").appendChild(help);
|
|
}
|
|
}
|
|
}
|
|
|
|
validateBic = (target) => {
|
|
if (target.value.length == 0) return
|
|
const re = /^[a-z]{6}[2-9a-z][0-9a-np-z]([a-z0-9]{3}|x{3})?$/i;
|
|
|
|
if (re.test(target.value)) {
|
|
target.classList.remove("is-danger")
|
|
document.querySelector("#bic div span").innerHTML = "✅";
|
|
if (document.querySelector("#bic p")) {
|
|
document.querySelector("#bic p").remove();
|
|
}
|
|
} else {
|
|
target.classList.add("is-danger")
|
|
document.querySelector("#bic div span").innerHTML = "❌";
|
|
|
|
if (!document.querySelector("#bic p")) {
|
|
const help = document.createElement("p");
|
|
help.classList.add("help", "is-danger");
|
|
help.textContent = "BIC is invalid";
|
|
document.querySelector("#bic").appendChild(help);
|
|
}
|
|
}
|
|
}
|
|
|
|
validateIban = (target) => {
|
|
if (target.value.length == 0) return
|
|
// IBANs are fucking complicated. this is a hugely simplified check
|
|
// If you want to know more look here:
|
|
// https://www.swift.com/standards/data-standards/iban-international-bank-account-number
|
|
const re = /^[a-z]{2}[0-9a-z]+$/i;
|
|
|
|
if (re.test(target.value)) {
|
|
target.classList.remove("is-danger")
|
|
document.querySelector("#iban div span").innerHTML = "✅";
|
|
if (document.querySelector("#iban p")) {
|
|
document.querySelector("#iban p").remove();
|
|
}
|
|
} else {
|
|
target.classList.add("is-danger")
|
|
document.querySelector("#iban div span").innerHTML = "❌";
|
|
|
|
if (!document.querySelector("#iban p")) {
|
|
const help = document.createElement("p");
|
|
help.classList.add("help", "is-danger");
|
|
help.textContent = "IBAN is invalid";
|
|
document.querySelector("#iban").appendChild(help);
|
|
}
|
|
}
|
|
}
|
|
|
|
validateAmount = (target) => {
|
|
if (target.value == 0) return
|
|
if (parseFloat(target.value) > 0 && target.value.toString() === parseFloat(target.value).toFixed(2).toString()) {
|
|
target.value = parseFloat(target.value).toFixed(2);
|
|
target.classList.remove("is-danger")
|
|
document.querySelector("#amount div span.is-right").innerHTML = "✅";
|
|
} else {
|
|
target.classList.add("is-danger")
|
|
document.querySelector("#amount div span.is-right").innerHTML = "❌";
|
|
}
|
|
}
|
|
|
|
validatePurpose = (target) => {
|
|
if (target.value.length == 0) return
|
|
const re = /[a-zA-Z0-9\/?:().,'+\- ]{1,140}/i;
|
|
|
|
if (re.test(target.value)) {
|
|
target.classList.remove("is-danger")
|
|
document.querySelector("#purpose div span").innerHTML = "✅";
|
|
if (document.querySelector("#purpose p")) {
|
|
document.querySelector("#purpose p").remove();
|
|
}
|
|
} else {
|
|
target.classList.add("is-danger")
|
|
document.querySelector("#purpose div span").innerHTML = "❌";
|
|
|
|
if (!document.querySelector("#purpose p")) {
|
|
const help = document.createElement("p");
|
|
help.classList.add("help", "is-danger");
|
|
help.textContent = "Purpose can only have 140 characters and only include A-Z, a-z, 0-9, /?:().,'+- and spaces.";
|
|
document.querySelector("#purpose").appendChild(help);
|
|
}
|
|
}
|
|
}
|
|
|
|
document.querySelector("#name input").addEventListener("input", (event) => {
|
|
validateName(event.target);
|
|
regenerate();
|
|
});
|
|
|
|
document.querySelector("#iban input").addEventListener("input", (event) => {
|
|
validateIban(event.target);
|
|
regenerate();
|
|
});
|
|
|
|
document.querySelector("#bic input").addEventListener("input", (event) => {
|
|
validateBic(event.target);
|
|
regenerate();
|
|
});
|
|
|
|
document.querySelector("#amount input").addEventListener("input", (event) => {
|
|
validateAmount(event.target);
|
|
regenerate();
|
|
});
|
|
|
|
document.querySelector("#purpose input").addEventListener("input", (event) => {
|
|
validatePurpose(event.target);
|
|
regenerate();
|
|
});
|
|
|
|
// Remember inputs
|
|
document.querySelector("#rememberme").addEventListener("change", (event) => {
|
|
if (event.target.checked) {
|
|
saveFormData();
|
|
} else {
|
|
localStorage.clear();
|
|
}
|
|
})
|
|
|
|
// Regenerate on color-scheme change
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
|
|
regenerate()
|
|
});
|
|
|
|
// qr code generator
|
|
regenerate = () => {
|
|
document.querySelector('#qr-code').innerHTML = "";
|
|
if (document.querySelector("#name input").classList.contains("is-danger")) {
|
|
console.error("Error in name");
|
|
}
|
|
else if (document.querySelector("#iban input").classList.contains("is-danger")) {
|
|
console.error("Error in IBAN");
|
|
}
|
|
else if (document.querySelector("#bic input").classList.contains("is-danger")) {
|
|
console.error("Error in BIC");
|
|
}
|
|
else if (document.querySelector("#amount input").classList.contains("is-danger")) {
|
|
console.error("Error in Amount");
|
|
}
|
|
else if (document.querySelector("#purpose input").classList.contains("is-danger")) {
|
|
console.error("Error in Purpose");
|
|
} else {
|
|
console.log("Generating new QR code...");
|
|
const data = `BCD
|
|
002
|
|
1
|
|
SCT
|
|
${document.querySelector("#bic input").value.toUpperCase()}
|
|
${document.querySelector("#name input").value}
|
|
${document.querySelector("#iban input").value.toUpperCase()}
|
|
EUR${document.querySelector("#amount input").value}
|
|
|
|
|
|
${document.querySelector("#purpose input").value}
|
|
`;
|
|
|
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
// dark mode
|
|
QrCreator.render({
|
|
text: data,
|
|
radius: 0.25,
|
|
ecLevel: "H",
|
|
fill: "#fff",
|
|
background: "#000",
|
|
size: 512
|
|
}, document.querySelector('#qr-code'));
|
|
} else {
|
|
// light mode
|
|
QrCreator.render({
|
|
text: data,
|
|
radius: 0.25,
|
|
ecLevel: "H",
|
|
fill: "#000",
|
|
background: "#fff",
|
|
size: 512
|
|
}, document.querySelector('#qr-code'));
|
|
}
|
|
|
|
if (document.querySelector("#rememberme").checked) {
|
|
saveFormData();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fill in form from local storage
|
|
const savedData = localStorage.getItem("bezahlbrudiFormData");
|
|
if (savedData) {
|
|
const formData = JSON.parse(savedData);
|
|
document.querySelector("#name input").value = formData["name"];
|
|
document.querySelector("#iban input").value = formData["iban"];
|
|
document.querySelector("#bic input").value = formData["bic"];
|
|
document.querySelector("#amount input").value = formData["amount"];
|
|
document.querySelector("#purpose input").value = formData["purpose"];
|
|
document.querySelector("#rememberme").checked = true;
|
|
changeLanguage(formData["lang"]);
|
|
} else {
|
|
// get browser language
|
|
let lang = "en"; // default fallback
|
|
for (const l of navigator.languages) {
|
|
const base = l.split("-")[0];
|
|
if (i18nSupported.includes(base)) {
|
|
lang = base;
|
|
break;
|
|
}
|
|
}
|
|
changeLanguage(lang);
|
|
}
|
|
|
|
// Validate all fields to set css properties
|
|
validateName(document.querySelector("#name input"));
|
|
validateIban(document.querySelector("#iban input"));
|
|
validateBic(document.querySelector("#bic input"));
|
|
validateAmount(document.querySelector("#amount input"));
|
|
validatePurpose(document.querySelector("#purpose input"));
|
|
|
|
// generate qr code on first visit
|
|
regenerate();
|
|
|
|
if ('serviceWorker' in navigator) {
|
|
navigator.serviceWorker.register('/js/service-worker.js')
|
|
.catch(err => console.error('Service Worker registration failed:', err));
|
|
}
|
|
|