(function () { var MIN_WIDTH = 80; var MAX_WIDTH = 560; function csrfToken() { var meta = document.querySelector("meta[name='csrf-token']"); return meta ? meta.getAttribute("content") : ""; } function initEditor(root) { if (root.dataset.ready === "1") return; root.dataset.ready = "1"; var surface = root.querySelector(".invite-editor__surface"); var handle = root.querySelector(".invite-editor__handle"); var fileInput = root.querySelector("[data-invite-file]"); var htmlField = root.closest("form").querySelector("[data-invite-html]"); var noteInput = root.closest("form").querySelector("[data-invite-note]"); var status = root.querySelector("[data-invite-status]"); var selectedImg = null; var drag = null; function showStatus(message, isError) { if (!status) return; if (!message) { status.hidden = true; status.textContent = ""; return; } status.hidden = false; status.textContent = message; status.classList.toggle("invite-editor__status--error", !!isError); } function syncHtml() { if (htmlField) htmlField.value = surface.innerHTML; } function syncNote() { var note = (noteInput && noteInput.value || "").trim(); var el = surface.querySelector("[data-invite-note]"); if (!note) { if (el) el.remove(); syncHtml(); return; } if (!el) { el = document.createElement("p"); el.setAttribute("data-invite-note", ""); var first = surface.querySelector("p"); if (first && first.nextSibling) surface.insertBefore(el, first.nextSibling); else if (first) first.after(el); else surface.appendChild(el); } el.textContent = note; syncHtml(); } function prepareImage(img) { img.draggable = false; img.style.maxWidth = "100%"; img.style.height = "auto"; if (!img.getAttribute("width") && img.naturalWidth) { img.setAttribute("width", Math.min(img.naturalWidth, MAX_WIDTH)); } } function updateHandle() { if (!selectedImg || !handle) return; var frame = handle.parentElement.getBoundingClientRect(); var rect = selectedImg.getBoundingClientRect(); handle.hidden = false; handle.style.left = rect.right - frame.left - 8 + "px"; handle.style.top = rect.bottom - frame.top - 8 + "px"; } function clearSelection() { selectedImg = null; if (handle) handle.hidden = true; surface.querySelectorAll("img.invite-editor__img--selected").forEach(function (img) { img.classList.remove("invite-editor__img--selected"); }); } function selectImage(img) { clearSelection(); selectedImg = img; img.classList.add("invite-editor__img--selected"); updateHandle(); } function insertImage(url) { surface.focus(); document.execCommand("insertHTML", false, ''); var images = surface.querySelectorAll("img"); var img = images[images.length - 1]; if (img) { prepareImage(img); selectImage(img); } syncHtml(); } function uploadFile(file) { if (!file || !file.type.match(/^image\/(png|jpeg|webp|gif)$/)) { showStatus(root.getAttribute("data-msg-type"), true); return; } if (file.size > 2 * 1024 * 1024) { showStatus(root.getAttribute("data-msg-size"), true); return; } var data = new FormData(); data.append("file", file); showStatus(root.getAttribute("data-msg-uploading"), false); fetch(root.getAttribute("data-upload-url"), { method: "POST", headers: { "X-CSRF-Token": csrfToken(), Accept: "application/json" }, body: data, credentials: "same-origin" }).then(function (res) { return res.json().then(function (json) { if (!res.ok) throw new Error(json.error || root.getAttribute("data-msg-failed")); return json; }); }).then(function (json) { showStatus("", false); insertImage(json.url); }).catch(function (err) { showStatus(err.message || root.getAttribute("data-msg-failed"), true); }); } root.querySelectorAll("[data-invite-cmd]").forEach(function (btn) { btn.addEventListener("mousedown", function (e) { e.preventDefault(); }); btn.addEventListener("click", function (e) { e.preventDefault(); var cmd = btn.getAttribute("data-invite-cmd"); surface.focus(); if (cmd === "createLink") { var url = window.prompt(root.getAttribute("data-msg-link") || "URL", "https://"); if (url) document.execCommand("createLink", false, url); } else if (cmd === "image") { fileInput.click(); } else { document.execCommand(cmd, false, null); } syncHtml(); }); }); fileInput.addEventListener("change", function () { var file = fileInput.files && fileInput.files[0]; fileInput.value = ""; if (file) uploadFile(file); }); surface.addEventListener("click", function (e) { if (e.target.tagName === "IMG") { e.preventDefault(); selectImage(e.target); } else { clearSelection(); } }); surface.addEventListener("input", syncHtml); surface.addEventListener("blur", syncHtml); if (noteInput) noteInput.addEventListener("input", syncNote); surface.addEventListener("paste", function (e) { var items = e.clipboardData && e.clipboardData.files; if (items && items.length && items[0].type.indexOf("image/") === 0) { e.preventDefault(); uploadFile(items[0]); } }); ["dragenter", "dragover"].forEach(function (type) { surface.addEventListener(type, function (e) { e.preventDefault(); surface.classList.add("invite-editor__surface--drop"); }); }); ["dragleave", "drop"].forEach(function (type) { surface.addEventListener(type, function () { surface.classList.remove("invite-editor__surface--drop"); }); }); surface.addEventListener("drop", function (e) { e.preventDefault(); var file = e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files[0]; if (file) uploadFile(file); }); handle.addEventListener("mousedown", function (e) { if (!selectedImg) return; e.preventDefault(); e.stopPropagation(); drag = { startX: e.clientX, startWidth: selectedImg.getBoundingClientRect().width }; document.body.classList.add("invite-editor--resizing"); }); document.addEventListener("mousemove", function (e) { if (!drag || !selectedImg) return; var width = Math.round(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, drag.startWidth + (e.clientX - drag.startX)))); selectedImg.style.width = width + "px"; selectedImg.style.height = "auto"; selectedImg.setAttribute("width", String(width)); selectedImg.removeAttribute("height"); updateHandle(); }); document.addEventListener("mouseup", function () { if (!drag) return; drag = null; document.body.classList.remove("invite-editor--resizing"); syncHtml(); }); window.addEventListener("resize", updateHandle); surface.querySelectorAll("img").forEach(prepareImage); var form = root.closest("form"); form.addEventListener("submit", function () { syncNote(); syncHtml(); }); form.addEventListener("turbo:submit-start", function () { syncNote(); syncHtml(); }); syncNote(); syncHtml(); } function bindSelectUncovered() { document.querySelectorAll("[data-select-uncovered]").forEach(function (btn) { if (btn.dataset.boundSelect === "1") return; btn.dataset.boundSelect = "1"; btn.addEventListener("click", function (e) { e.preventDefault(); var formId = btn.getAttribute("data-select-uncovered"); document.querySelectorAll('input[data-uncovered-match][form="' + formId + '"]').forEach(function (cb) { cb.checked = true; }); }); }); } function boot() { document.querySelectorAll("[data-invite-editor]").forEach(initEditor); bindSelectUncovered(); } document.addEventListener("DOMContentLoaded", boot); document.addEventListener("turbo:load", boot); })();