async function sendFileDeleted(inputName, fileInputVariant = null) { let formData = new FormData() let normalInputName = fileInputVariant !== null ? fileInputs[inputName][fileInputVariant] : fileInputs[inputName] formData.set(`cp[id]`, document.querySelector("input[name='cp[id]']").value) formData.set(`cp[${normalInputName}]`, "-1") let result = await updatePoint(formData) try { console.log(result.ok) } catch (e) { console.log(e) } } function parsePurpose(cell) { return cell?.querySelector("td:nth-child(2)")?.innerHTML.match(/для[^\|]+/g)?.[0].trim() } function parsefileInputVariant(cell) { return Object.keys(fileInpitVariants).find(key => fileInpitVariants[key] === parsePurpose(cell)) } function addDisplayedFile(inputName, type, file, preview, removeLink, removedFilesLinks, variant = null) { if (!inputName || !file || !removeLink) return let fileListContainer if (variant !== null) { if (inputName == "attachment1" || inputName == "attachment4") { if (variant == "l") { fileListContainer = document.querySelector(`[data-container="${fileInputs[inputName][variant]}"] .file-list-container`) } else if (variant == "h") { let filesContainer = document.querySelector(`[data-container="${fileInputs[inputName].h}"]`) fileListContainer = getFileListContainer(filesContainer) } } } let input = document.querySelector(`input[name="${inputName}\[\]"]`) fileListContainer ??= input.parentElement.parentElement.querySelector(".file-list-container") let fileContainer = Tag.div({ classes: "file-container" }) const displayedFile = Tag.make(type ?? "a", { classes: "preview-small" }) if (type == "img") { displayedFile.src = preview displayedFile.dataset.origin = file displayedFile.addEventListener("click", () => { let dialog = document.querySelector("dialog") makeSwiper(dialog, fileListContainer, file) dialog.showModal() }) } else if (type == "audio") { displayedFile.src = file displayedFile.setAttribute("controls", "") } else { displayedFile.href = file displayedFile.textContent = "Файл" } let fileButtonsContainer = Tag.div({ classes: "file-buttons-container" }) fileButtonsContainer.append(makeDownloadLink(/[^/]*$/.exec(new URL(file).pathname)[0], file)) let deleteButton = Tag.button({ type: "button", classes: "button-delete", textContent: "x", on: { click: async e => { if (!confirm("Точно?")) return await fetch(removeLink) await sendFileDeleted(inputName, variant) removedFilesLinks.push(removeLink) fileListContainer.removeChild(fileContainer) } } }) fileButtonsContainer.append(deleteButton) fileContainer.append(displayedFile) fileContainer.append(fileButtonsContainer) fileListContainer.append(fileContainer) } function dataURLtoFile(dataurl, filename) { let arr = dataurl.split(',') let mime = arr[0].match(/:(.*?);/)[1] let bstr = atob(arr[arr.length - 1]) let n = bstr.length let u8arr = new Uint8Array(n) while (n--) { u8arr[n] = bstr.charCodeAt(n) } return new File([u8arr], filename, { type: mime }) } function getHtmlElementByFileType(file) { const htmlElementsForTypes = { "image/": "img", "audio/": "audio" } let res = "div" for (const [type, el] of Object.entries(htmlElementsForTypes)) { if (file.type.startsWith(type)) { res = el break } } let el = Tag.make(res) if (res == "audio") { el.setAttribute("controls", "") } return el } function makeHandleFilesFunc() { let storedFiles = [] return function () { let dt = new DataTransfer() if (storedFiles.length) { for (const oldFile of storedFiles) { let oldFileObj = dataURLtoFile(oldFile.data, oldFile.name) dt.items.add(oldFileObj) } } for (let i = 0; i < this.files.length; i++) { const file = this.files[i] dt.items.add(file) let variant = this.parentElement.querySelector('input[type="radio"]:checked')?.value let fileListContainer if (variant) { let [_, filesContainer] = getContainersByVariant(variant, getAttachmentIndex(this)) fileListContainer = getFileListContainer(filesContainer) } else { fileListContainer = this.parentElement.parentElement.querySelector(".file-list-container") } let fileContainer = Tag.div({ classes: "file-container file-container-new" }) const displayedFile = getHtmlElementByFileType(file) displayedFile.classList.add("preview") displayedFile.file = file displayedFile.addEventListener("click", () => { let dialog = document.querySelector("dialog") makeSwiper(dialog, fileListContainer, displayedFile.src) dialog.showModal() }) let fileButtonsContainer = Tag.div({ classes: "file-buttons-container" }) let downloadLink = makeDownloadLink(file.name) fileButtonsContainer.append(downloadLink) let deleteButton = Tag.button({ classes: "button-delete", textContent: "x", type: "button", on: { click: e => { let index = [...fileContainer.parentElement.children].indexOf(fileContainer) if (!confirm("Точно?")) return storedFiles.splice(storedFiles.length - this.files.length + index, 1) let rdt = new DataTransfer() for (const file of this.files) { rdt.items.add(file) } rdt.items.remove(index) this.files = rdt.files fileContainer.parentElement.removeChild(fileContainer) } } }) fileButtonsContainer.append(deleteButton) fileContainer.append(displayedFile) fileContainer.append(fileButtonsContainer) fileListContainer.append(fileContainer) const reader = new FileReader() reader.onload = (e) => { displayedFile.src = e.target.result downloadLink.setAttribute("href", displayedFile.src) storedFiles.push({ data: displayedFile.src, name: file.name }) } reader.readAsDataURL(file) } this.files = dt.files } } let prettifyFiles = (function () { let executed = false return function (insertedFileRows, removedFilesLinks) { if (executed) return executed = true document.querySelector("#new").querySelectorAll("input[type=file]").forEach((element, index) => { element.id = `input-file-${index}` element.setAttribute("multiple", "multiple") element.dataset.index = index let pseudoInput = Tag.make("label", { classes: "custom-file-upload", _for: element.id, textContent: "+" }) element.parentElement.insertBefore(pseudoInput, element) element.parentElement.parentElement.append(makeFileListContainer()) element.addEventListener("change", makeHandleFilesFunc(), false) }) moveFileInputValues(insertedFileRows, removedFilesLinks) } })() function saveInputValues(from) { let fromInputs = [...from.querySelectorAll("input, textarea")] let result = new Map() for (const fromEl of fromInputs) { result.set(fromEl, fromEl.type == "radio" ? fromEl.checked : fromEl.value) } return result } function setInputValues(to, values) { let toInputs = [...to.querySelectorAll("input, textarea")] for (const [fromEl, value] of values) { let currentToInput = toInputs.find(toEl => toEl.type !== 'file' && toEl.type === fromEl.type && toEl.name === fromEl.name && toEl.id === fromEl.id && (toEl.type !== "radio" || toEl.value === fromEl.value) ) if (currentToInput) { currentToInput.checked = fromEl.checked currentToInput.value = fromEl.value } } } function moveFileInputValues(insertedFileRows, removedFilesLinks) { for (const [inputRowIndex, rows] of insertedFileRows) { for (const row of rows) { let fileInput = null, type = null, fileUrl = null, deleteUrl = null, preview = null if (row.querySelector("img")) { type = "img" fileUrl = row.querySelector("td:first-child a").href preview = row.querySelector("img").src } else if (row.querySelector("audio")) { type = "audio" fileUrl = row.querySelector("audio").src } else { fileUrl = row.querySelector("td:first-child a").href } deleteUrl = row.querySelector("td:nth-child(2) a").href if (inputRowIndex == 23) { fileInput = "attachment1" } else if (inputRowIndex == 27) { fileInput = "attachment4" } else if (inputRowIndex == 31) { fileInput = "attachment2" } else if (inputRowIndex == 35) { fileInput = "attachment3" } else { console.log(inputRowIndex) return } let variant = parsefileInputVariant(row) addDisplayedFile(fileInput, type, fileUrl, preview, deleteUrl, removedFilesLinks, variant) } } } function moveNewFilesOnVariantChange() { document.querySelectorAll(`input[name^="new_file_type"]`).forEach(el => el.addEventListener("change", function () { let attachmentIndex = getAttachmentIndex(this) let [from, to] = getContainersByVariant(this.value, attachmentIndex) let newFiles = [...from.querySelectorAll(`.file-container-new`)] for (const newFile of newFiles) { getFileListContainer(to).append(newFile) } })) } function removeDeletedFilesFromUglyVersion(removeLink) { let shortHref = removeLink.split("/").at(-1) document.querySelector(`tr:has(a[href="${shortHref}"])`).remove() } function moveInputValues(form, was, became) { let inputValues = saveInputValues(was) form.removeChild(was) form.append(became) setInputValues(became, inputValues) createSendButtons() } function prettifyEditCpForm(form, was, became, insertedFileRows, removedFilesLinks) { moveInputValues(form, was, became) prettifyFiles(insertedFileRows, removedFilesLinks) moveNewFilesOnVariantChange() $("#cps_main").select2() makeCoordinatesLinks() } function uglifyEditCpForm(form, was, became, removedFilesLinks) { moveInputValues(form, was, became) for (const removedFileLink of removedFilesLinks) { removeDeletedFilesFromUglyVersion(removedFileLink) } } function addUglyDeleteListener() { let links = [...document.querySelectorAll("a[href*='del_stored']")] for (const link of links) { let shortHref = link.href.split("/").at(-1) let fileInput = document.querySelector(`tr:has(a[href$="${shortHref}"]) ~ tr:has(input[type="file"]) input[type="file"]`) let fileInputVariant = parsefileInputVariant(document.querySelector(`tr:has(a[href$="${shortHref}"])`)) link.addEventListener("click", async e => { e.preventDefault() if (!confirm("Точно?")) return await sendFileDeleted(fileInput.name.split("[")[0], fileInputVariant) location.href = link.href }) } }