Support Image-Upload and Paste-from-Clipboard
This commit is contained in:
322
js/wishlist.js
322
js/wishlist.js
@@ -2,16 +2,24 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
// Sort direkt submitten
|
||||
const sortSel = document.getElementById("sortby");
|
||||
// ===== Helper =====
|
||||
function $(sel, root) {
|
||||
return (root || document).querySelector(sel);
|
||||
}
|
||||
function $all(sel, root) {
|
||||
return Array.from((root || document).querySelectorAll(sel));
|
||||
}
|
||||
|
||||
// ===== Sort direkt submitten =====
|
||||
const sortSel = $("#sortby");
|
||||
if (sortSel && sortSel.form) {
|
||||
sortSel.addEventListener("change", function () {
|
||||
this.form.submit();
|
||||
});
|
||||
}
|
||||
|
||||
// Reservation Modal
|
||||
const reservationModal = document.getElementById("reservationModal");
|
||||
// ===== Reservation Modal =====
|
||||
const reservationModal = $("#reservationModal");
|
||||
if (reservationModal) {
|
||||
reservationModal.addEventListener("show.bs.modal", function (ev) {
|
||||
const btn = ev.relatedTarget;
|
||||
@@ -19,13 +27,12 @@
|
||||
const wishid = btn.getAttribute("data-wishid");
|
||||
const reserved = btn.getAttribute("data-reserved");
|
||||
|
||||
reservationModal.querySelector("#modal-wishid").value = wishid || "";
|
||||
reservationModal.querySelector("#modal-reservedstat").value =
|
||||
reserved || "";
|
||||
$("#modal-wishid", reservationModal).value = wishid || "";
|
||||
$("#modal-reservedstat", reservationModal).value = reserved || "";
|
||||
|
||||
const submitBtn = reservationModal.querySelector("#reservation-submit");
|
||||
const titleEl = reservationModal.querySelector("#reservationModalLabel");
|
||||
const infoEl = reservationModal.querySelector("#ReservationInfoText");
|
||||
const submitBtn = $("#reservation-submit", reservationModal);
|
||||
const titleEl = $("#reservationModalLabel", reservationModal);
|
||||
const infoEl = $("#ReservationInfoText", reservationModal);
|
||||
|
||||
if (reserved === "1") {
|
||||
submitBtn.textContent = "Reservierung aufheben";
|
||||
@@ -39,8 +46,8 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Delete Modal
|
||||
const deleteModal = document.getElementById("deleteModal");
|
||||
// ===== Delete Modal =====
|
||||
const deleteModal = $("#deleteModal");
|
||||
if (deleteModal) {
|
||||
deleteModal.addEventListener("show.bs.modal", function (ev) {
|
||||
const btn = ev.relatedTarget;
|
||||
@@ -51,7 +58,6 @@
|
||||
: "";
|
||||
const wishid = btn.getAttribute("data-wishid") || "";
|
||||
|
||||
// robust: suche entweder #DelWhishID ODER #WhishID
|
||||
const idInput = deleteModal.querySelector(
|
||||
'#DelWhishID, #WhishID, input[name="WhishID"]'
|
||||
);
|
||||
@@ -64,8 +70,8 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Push Prio Modal
|
||||
const prioModal = document.getElementById("pushprioModal");
|
||||
// ===== Push Prio Modal =====
|
||||
const prioModal = $("#pushprioModal");
|
||||
if (prioModal) {
|
||||
prioModal.addEventListener("show.bs.modal", function (ev) {
|
||||
const btn = ev.relatedTarget;
|
||||
@@ -88,28 +94,118 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Add/Edit Item Modal
|
||||
const itemModal = document.getElementById("itemModal");
|
||||
// ===== Add/Edit Item Modal =====
|
||||
const itemModal = $("#itemModal");
|
||||
let _currentPreviewObjectUrl = null;
|
||||
|
||||
function revokePreviewUrl() {
|
||||
if (_currentPreviewObjectUrl) {
|
||||
try {
|
||||
URL.revokeObjectURL(_currentPreviewObjectUrl);
|
||||
} catch (e) {}
|
||||
_currentPreviewObjectUrl = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (itemModal) {
|
||||
itemModal.addEventListener("show.bs.modal", function (ev) {
|
||||
const btn = ev.relatedTarget;
|
||||
if (!btn) return;
|
||||
const mode = btn.getAttribute("data-mode") || "add";
|
||||
|
||||
const titleEl = itemModal.querySelector("#itemModalTitle");
|
||||
const actionEl = itemModal.querySelector("#ItemAction");
|
||||
const submitEl = itemModal.querySelector("#ItemSubmitBtn");
|
||||
const removeWrap = itemModal.querySelector("#RemoveImageWrap");
|
||||
const removeChk = itemModal.querySelector("#RemoveImage");
|
||||
const titleEl = $("#itemModalTitle", itemModal);
|
||||
const actionEl = $("#ItemAction", itemModal);
|
||||
const submitEl = $("#ItemSubmitBtn", itemModal);
|
||||
const removeWrap = $("#RemoveImageWrap", itemModal);
|
||||
const removeChk = $("#RemoveImage", itemModal);
|
||||
|
||||
// Felder
|
||||
const fTitle = itemModal.querySelector("#ItemTitle");
|
||||
const fDesc = itemModal.querySelector("#ItemDescription");
|
||||
const fPrice = itemModal.querySelector("#ItemPrice");
|
||||
const fLink = itemModal.querySelector("#ItemLink");
|
||||
const fImg = itemModal.querySelector("#ItemImage");
|
||||
const fId = itemModal.querySelector("#WhishID");
|
||||
const fQty = itemModal.querySelector("#ItemQty"); // <-- NEU
|
||||
const fTitle = $("#ItemTitle", itemModal);
|
||||
const fDesc = $("#ItemDescription", itemModal);
|
||||
const fPrice = $("#ItemPrice", itemModal);
|
||||
const fLink = $("#ItemLink", itemModal);
|
||||
const fId = $("#WhishID", itemModal);
|
||||
const fQty = $("#ItemQty", itemModal);
|
||||
|
||||
// Bild-Felder
|
||||
const fImgUrl = $("#ItemImageUrl", itemModal);
|
||||
const fImgFile = $("#ItemImageFile", itemModal);
|
||||
const pasteZone = $("#PasteZone", itemModal);
|
||||
const pasteVal = $("#ItemImagePaste", itemModal);
|
||||
const pasteName = $("#ItemImagePasteName", itemModal);
|
||||
const prevWrap = $("#ImgPreviewWrap", itemModal);
|
||||
const prevImg = $("#ImgPreview", itemModal);
|
||||
const pasteActivator = $("#PasteActivator", itemModal);
|
||||
|
||||
// Preview-Styling erzwingen (falls keine CSS-Regel vorhanden)
|
||||
if (prevWrap) {
|
||||
prevWrap.style.maxHeight = "240px";
|
||||
prevWrap.style.overflow = "hidden";
|
||||
prevWrap.style.border = "1px solid rgba(0,0,0,.1)";
|
||||
prevWrap.style.borderRadius = ".5rem";
|
||||
prevWrap.style.padding = ".5rem";
|
||||
prevWrap.style.background = "#fff";
|
||||
}
|
||||
if (prevImg) {
|
||||
prevImg.style.maxWidth = "100%";
|
||||
prevImg.style.maxHeight = "220px";
|
||||
prevImg.style.objectFit = "contain";
|
||||
prevImg.classList.add("img-fluid", "border", "rounded", "w-100");
|
||||
}
|
||||
|
||||
function showPreview(src) {
|
||||
revokePreviewUrl();
|
||||
if (!prevWrap || !prevImg) return;
|
||||
if (!src) {
|
||||
prevWrap.style.display = "none";
|
||||
prevImg.removeAttribute("src");
|
||||
return;
|
||||
}
|
||||
prevImg.src = src;
|
||||
prevWrap.style.display = "block";
|
||||
if (src.startsWith("blob:")) _currentPreviewObjectUrl = src;
|
||||
}
|
||||
function clearUrl() {
|
||||
if (fImgUrl) fImgUrl.value = "";
|
||||
}
|
||||
function clearFile() {
|
||||
if (fImgFile) fImgFile.value = "";
|
||||
}
|
||||
function clearPaste() {
|
||||
if (pasteVal) pasteVal.value = "";
|
||||
if (pasteName) pasteName.value = "clipboard.png";
|
||||
if (pasteZone) {
|
||||
pasteZone.innerHTML = "";
|
||||
pasteZone.setAttribute("data-ph-active", "1");
|
||||
}
|
||||
}
|
||||
function clearPreviewAndInputs() {
|
||||
showPreview("");
|
||||
clearUrl();
|
||||
clearFile();
|
||||
clearPaste();
|
||||
}
|
||||
|
||||
function focusPasteCatcher() {
|
||||
if (!pasteZone) return;
|
||||
// kurz sichtbar machen, fokus holen, dann wieder verstecken
|
||||
pasteZone.classList.remove("visually-hidden");
|
||||
pasteZone.focus();
|
||||
// cursor ans ende
|
||||
const sel = window.getSelection();
|
||||
if (sel && sel.rangeCount === 0) {
|
||||
const r = document.createRange();
|
||||
r.selectNodeContents(pasteZone);
|
||||
r.collapse(false);
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(r);
|
||||
}
|
||||
// wieder verstecken – Fokus bleibt (Browser lässt Paste trotzdem zu)
|
||||
setTimeout(() => pasteZone.classList.add("visually-hidden"), 10);
|
||||
}
|
||||
|
||||
// —— Modal immer CLEAN beim Öffnen ——
|
||||
clearPreviewAndInputs();
|
||||
|
||||
if (mode === "edit") {
|
||||
titleEl.textContent = "Wunsch bearbeiten";
|
||||
@@ -123,15 +219,14 @@
|
||||
const dDesc = btn.getAttribute("data-description") || "";
|
||||
const dPrice = btn.getAttribute("data-price") || "";
|
||||
const dLink = btn.getAttribute("data-link") || "";
|
||||
const dQty = btn.getAttribute("data-qty") || "1"; // <-- NEU
|
||||
const dQty = btn.getAttribute("data-qty") || "1";
|
||||
|
||||
if (fId) fId.value = wishid;
|
||||
if (fTitle) fTitle.value = dTitle;
|
||||
if (fDesc) fDesc.value = dDesc;
|
||||
if (fPrice) fPrice.value = dPrice;
|
||||
if (fLink) fLink.value = dLink;
|
||||
if (fImg) fImg.value = "";
|
||||
if (fQty) fQty.value = dQty; // <-- NEU
|
||||
if (fQty) fQty.value = dQty;
|
||||
} else {
|
||||
titleEl.textContent = "Wunsch hinzufügen";
|
||||
actionEl.value = "add";
|
||||
@@ -141,11 +236,170 @@
|
||||
if (fDesc) fDesc.value = "";
|
||||
if (fPrice) fPrice.value = "";
|
||||
if (fLink) fLink.value = "";
|
||||
if (fImg) fImg.value = "";
|
||||
if (fQty) fQty.value = "1"; // <-- NEU
|
||||
if (fQty) fQty.value = "1";
|
||||
if (removeWrap) removeWrap.style.display = "none";
|
||||
if (removeChk) removeChk.checked = false;
|
||||
}
|
||||
|
||||
// --- Bild-URL
|
||||
if (fImgUrl) {
|
||||
fImgUrl.addEventListener(
|
||||
"input",
|
||||
() => {
|
||||
const val = fImgUrl.value.trim();
|
||||
if (val !== "") {
|
||||
clearFile();
|
||||
clearPaste();
|
||||
showPreview(val);
|
||||
} else showPreview("");
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
|
||||
// --- Datei-Upload
|
||||
if (fImgFile) {
|
||||
fImgFile.addEventListener(
|
||||
"change",
|
||||
() => {
|
||||
if (fImgFile.files && fImgFile.files[0]) {
|
||||
const f = fImgFile.files[0];
|
||||
if (f.size > 8 * 1024 * 1024) {
|
||||
alert("Datei ist größer als 8 MB.");
|
||||
fImgFile.value = "";
|
||||
showPreview("");
|
||||
return;
|
||||
}
|
||||
clearUrl();
|
||||
clearPaste();
|
||||
const blobUrl = URL.createObjectURL(f);
|
||||
showPreview(blobUrl);
|
||||
} else {
|
||||
showPreview("");
|
||||
}
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
|
||||
// --- Paste aus Zwischenablage
|
||||
if (pasteZone) {
|
||||
pasteZone.setAttribute(
|
||||
"data-placeholder",
|
||||
pasteZone.getAttribute("data-placeholder") ||
|
||||
"Hier klicken und dann Strg+V / Cmd+V"
|
||||
);
|
||||
pasteZone.setAttribute("data-ph-active", "1");
|
||||
pasteZone.addEventListener(
|
||||
"focus",
|
||||
() => {
|
||||
if (pasteZone.getAttribute("data-ph-active") === "1") {
|
||||
pasteZone.innerHTML = "";
|
||||
pasteZone.removeAttribute("data-ph-active");
|
||||
}
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
pasteZone.addEventListener("blur", () => {
|
||||
if (pasteZone.innerText.trim() === "") {
|
||||
pasteZone.innerHTML = "";
|
||||
pasteZone.setAttribute("data-ph-active", "1");
|
||||
}
|
||||
});
|
||||
// verhindert, dass Text-Schnipsel sichtbar werden
|
||||
pasteZone.addEventListener("input", () => {
|
||||
pasteZone.textContent = "";
|
||||
});
|
||||
|
||||
// keine Drops zulassen
|
||||
["dragover", "drop"].forEach((evName) => {
|
||||
pasteZone.addEventListener(evName, (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
|
||||
pasteZone.addEventListener(
|
||||
"paste",
|
||||
(ev) => {
|
||||
const items =
|
||||
ev.clipboardData && ev.clipboardData.items
|
||||
? ev.clipboardData.items
|
||||
: [];
|
||||
let imgItem = null;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const t = items[i].type || "";
|
||||
if (t.startsWith("image/")) {
|
||||
imgItem = items[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// nur Bilder erlaubt
|
||||
if (!imgItem) {
|
||||
ev.preventDefault();
|
||||
// optional Hinweis
|
||||
alert("Bitte nur Bilder einfügen (z. B. über „Bild kopieren“).");
|
||||
return;
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
const blob = imgItem.getAsFile();
|
||||
if (!blob) return;
|
||||
|
||||
if (blob.size > 8 * 1024 * 1024) {
|
||||
alert("Paste-Bild ist größer als 8 MB.");
|
||||
return;
|
||||
}
|
||||
|
||||
const ext =
|
||||
blob.type && blob.type.split("/")[1]
|
||||
? blob.type.split("/")[1]
|
||||
: "png";
|
||||
if (pasteName) pasteName.value = "clipboard." + ext;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = function () {
|
||||
const dataUrl = reader.result; // data:image/*;base64,...
|
||||
if (pasteVal) pasteVal.value = dataUrl;
|
||||
clearUrl();
|
||||
clearFile();
|
||||
showPreview(dataUrl);
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
|
||||
if (pasteActivator) {
|
||||
pasteActivator.addEventListener(
|
||||
"click",
|
||||
() => {
|
||||
// andere Inputs leeren, Preview resetten
|
||||
clearUrl();
|
||||
clearFile();
|
||||
// Fokus in den versteckten Paste-Catcher
|
||||
focusPasteCatcher();
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
|
||||
// Beim Schließen: wirklich ALLES wieder clean + Blob-URL freigeben
|
||||
itemModal.addEventListener(
|
||||
"hidden.bs.modal",
|
||||
() => {
|
||||
revokePreviewUrl();
|
||||
if (prevWrap) prevWrap.style.display = "none";
|
||||
if (prevImg) prevImg.removeAttribute("src");
|
||||
clearUrl();
|
||||
clearFile();
|
||||
clearPaste();
|
||||
if (removeChk) removeChk.checked = false;
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user