new feat übersetzer und faq

This commit is contained in:
2026-07-24 15:16:10 +00:00
parent 11b0d20c42
commit 45b37597a9
14 changed files with 1205 additions and 51 deletions

View File

@@ -0,0 +1,117 @@
(() => {
function initTranslator(dialog) {
const openButton = document.querySelector("[data-translator-open]");
const swapButton = dialog.querySelector("[data-translator-swap]");
const submitButton = dialog.querySelector("[data-translator-submit]");
const input = dialog.querySelector("[data-translator-input]");
const sourceLabel = dialog.querySelector("[data-translator-source]");
const targetLabel = dialog.querySelector("[data-translator-target]");
const phraseButtons = dialog.querySelectorAll("[data-translator-phrase]");
if (!openButton || !swapButton || !submitButton || !input || !sourceLabel || !targetLabel) {
return;
}
let sourceLang = dialog.dataset.sourceLang === "en" ? "en" : "de";
const labels = {
de: sourceLang === "de" ? sourceLabel.textContent : targetLabel.textContent,
en: sourceLang === "en" ? sourceLabel.textContent : targetLabel.textContent,
};
const renderDirection = () => {
const targetLang = sourceLang === "de" ? "en" : "de";
sourceLabel.textContent = labels[sourceLang];
targetLabel.textContent = labels[targetLang];
};
const updateSubmit = () => {
submitButton.disabled = input.value.trim().length === 0;
};
let isClosing = false;
const close = () => {
if (!dialog.open || isClosing) {
return;
}
isClosing = true;
dialog.classList.remove("is-opening");
dialog.classList.add("is-closing");
const finishClose = () => {
if (!dialog.open) {
return;
}
dialog.classList.remove("is-closing");
dialog.close();
isClosing = false;
openButton.focus();
};
dialog.addEventListener("animationend", finishClose, { once: true });
window.setTimeout(
finishClose,
window.matchMedia("(prefers-reduced-motion: reduce)").matches ? 0 : 360,
);
};
openButton.addEventListener("click", () => {
dialog.showModal();
dialog.classList.remove("is-closing");
dialog.classList.add("is-opening");
window.requestAnimationFrame(() => input.focus());
});
dialog.addEventListener("click", (event) => {
if (event.target === dialog) {
close();
}
});
dialog.addEventListener("cancel", (event) => {
event.preventDefault();
close();
});
swapButton.addEventListener("click", () => {
sourceLang = sourceLang === "de" ? "en" : "de";
renderDirection();
phraseButtons.forEach((button) => {
input.value = input.value === button.dataset.de || input.value === button.dataset.en
? button.dataset[sourceLang]
: input.value;
});
updateSubmit();
input.focus();
});
phraseButtons.forEach((button) => {
button.addEventListener("click", () => {
input.value = button.dataset[sourceLang] || "";
updateSubmit();
input.focus();
});
});
input.addEventListener("input", updateSubmit);
submitButton.addEventListener("click", () => {
const text = input.value.trim();
if (!text) {
return;
}
const targetLang = sourceLang === "de" ? "en" : "de";
const url = `https://www.deepl.com/translator#${sourceLang}/${targetLang}/${encodeURIComponent(text)}`;
window.open(url, "_blank", "noopener,noreferrer");
close();
});
renderDirection();
updateSubmit();
}
document.addEventListener("DOMContentLoaded", () => {
const dialog = document.querySelector("[data-translator-dialog]");
if (dialog) {
initTranslator(dialog);
}
});
})();