1479 lines
45 KiB
JavaScript
1479 lines
45 KiB
JavaScript
// ==UserScript==
|
||
// @name Runcity
|
||
// @namespace http://tampermonkey.net/
|
||
// @version 2024-11-18
|
||
// @desc try to take over the world!
|
||
// @author You
|
||
// @match https://rst.runcity.org/*
|
||
// @icon https://www.google.com/s2/favicons?sz=64&domain=runcity.org
|
||
// @grant none
|
||
// @require https://code.jquery.com/jquery-3.7.1.min.js
|
||
// @require https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js
|
||
// @require https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js
|
||
// ==/UserScript==
|
||
|
||
(function () {
|
||
'use strict';
|
||
|
||
let fileInputs = {
|
||
"attachment1": "legend_photo",
|
||
"attachment4": "legend_files",
|
||
"attachment2": "admin_photo",
|
||
"attachment3": "admin_files"
|
||
}
|
||
|
||
const localStorageItems = {
|
||
NEED_UPDATE_ID: "needUpdateId",
|
||
JUST_CREATED: "justCreated",
|
||
PREV_CREATED: "prevCreated",
|
||
LATTITUDE: "lattitude",
|
||
LONGITUDE: "longitude",
|
||
ALWAYS_PRETTIFY: "always",
|
||
REDIRECT_EXIT: "redirectExit"
|
||
}
|
||
|
||
const ZOOM = 17
|
||
const METERS = 510
|
||
|
||
let removedFilesLinks = []
|
||
|
||
class Property {
|
||
id;
|
||
name;
|
||
content;
|
||
desc;
|
||
|
||
constructor(id, row) {
|
||
this.id = id
|
||
|
||
let columns = [...row.querySelectorAll('td, th')].map(el => el.cloneNode(true))
|
||
if (columns.length === 1) {
|
||
this.content = columns[0].innerHTML.trim()
|
||
}
|
||
else if (columns.length >= 2) {
|
||
this.name = columns[0].innerHTML.trim()
|
||
let elementsToRemove = columns[1].querySelector("input[name=\"read_gps2\"]")
|
||
if (elementsToRemove) {
|
||
columns[1].removeChild(elementsToRemove)
|
||
}
|
||
|
||
this.content = columns[1].innerHTML
|
||
.replaceAll("<br>", "")
|
||
.replaceAll(/\s*Перейти к легенде.*$/gs, "")
|
||
.replaceAll("для легенды (\"l\")", "")
|
||
.replaceAll("общие (\"c\")", "")
|
||
.replaceAll("для ист. справки (\"h\")", "")
|
||
.replaceAll("Получить координаты КП из картинки", "")
|
||
.trim()
|
||
}
|
||
|
||
if (columns.length === 3) {
|
||
this.desc = columns[2].innerHTML.replaceAll("<br>", "").replaceAll(/(\n)\s*/g, "$1").trim()
|
||
}
|
||
}
|
||
|
||
toDiv(altName = null, altDesc = null) {
|
||
let div = document.createElement('div')
|
||
let desc = altDesc ?? this.desc
|
||
desc = desc ? "<div class='desc-icon-container' title='" + desc + "'>" +
|
||
"<img class='desc-icon' src='data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnIGlkPSJzdmcyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAwIiB3aWR0aD0iMjAwIiB2ZXJzaW9uPSIxLjAiPgogPHBhdGggaWQ9InBhdGgyMzgyIiBkPSJtMTY1LjMzIDExMy40NGExMDMuNjEgMTAzLjYxIDAgMSAxIC0yMDcuMjIgMCAxMDMuNjEgMTAzLjYxIDAgMSAxIDIwNy4yMiAweiIgdHJhbnNmb3JtPSJtYXRyaXgoLjkzNzM5IDAgMCAuOTM3MzkgNDIuMTQzIC02LjMzOTIpIiBzdHJva2Utd2lkdGg9IjAiIGZpbGw9IiNmZmYiLz4KIDxnIGlkPSJsYXllcjEiPgogIDxwYXRoIGlkPSJwYXRoMjQxMyIgZD0ibTEwMCAwYy01NS4yIDAtMTAwIDQ0LjgtMTAwIDEwMC01LjA0OTVlLTE1IDU1LjIgNDQuOCAxMDAgMTAwIDEwMHMxMDAtNDQuOCAxMDAtMTAwLTQ0LjgtMTAwLTEwMC0xMDB6bTAgMTIuODEyYzQ4LjEzIDAgODcuMTkgMzkuMDU4IDg3LjE5IDg3LjE4OHMtMzkuMDYgODcuMTktODcuMTkgODcuMTktODcuMTg4LTM5LjA2LTg3LjE4OC04Ny4xOSAzOS4wNTgtODcuMTg4IDg3LjE4OC04Ny4xODh6bTEuNDcgMjEuMjVjLTUuNDUgMC4wMy0xMC42NTMgMC43MzctMTUuMjgyIDIuMDYzLTQuNjk5IDEuMzQ2LTkuMTI2IDMuNDg0LTEyLjg3NiA2LjIxOS0zLjIzOCAyLjM2Mi02LjMzMyA1LjM5MS04LjY4NyA4LjUzMS00LjE1OSA1LjU0OS02LjQ2MSAxMS42NTEtNy4wNjMgMTguNjg3LTAuMDQgMC40NjgtMC4wNyAwLjg2OC0wLjA2MiAwLjg3NiAwLjAxNiAwLjAxNiAyMS43MDIgMi42ODcgMjEuODEyIDIuNjg3IDAuMDUzIDAgMC4xMTMtMC4yMzQgMC4yODItMC45MzcgMS45NDEtOC4wODUgNS40ODYtMTMuNTIxIDEwLjk2OC0xNi44MTMgNC4zMi0yLjU5NCA5LjgwOC0zLjYxMiAxNS43NzgtMi45NjkgMi43NCAwLjI5NSA1LjIxIDAuOTYgNy4zOCAyIDIuNzEgMS4zMDEgNS4xOCAzLjM2MSA2Ljk0IDUuODEzIDEuNTQgMi4xNTYgMi40NiA0LjU4NCAyLjc1IDcuMzEyIDAuMDggMC43NTkgMC4wNSAyLjQ4LTAuMDMgMy4yMTktMC4yMyAxLjgyNi0wLjcgMy4zNzgtMS41IDQuOTY5LTAuODEgMS41OTctMS40OCAyLjUxNC0yLjc2IDMuODEyLTIuMDMgMi4wNzctNS4xOCA0LjgyOS0xMC43OCA5LjQwNy0zLjYgMi45NDQtNi4wNCA1LjE1Ni04LjEyIDcuMzQzLTQuOTQzIDUuMTc5LTcuMTkxIDkuMDY5LTguNTY0IDE0LjcxOS0wLjkwNSAzLjcyLTEuMjU2IDcuNTUtMS4xNTYgMTMuMTkgMC4wMjUgMS40IDAuMDYyIDIuNzMgMC4wNjIgMi45N3YwLjQzaDIxLjU5OGwwLjAzLTIuNGMwLjAzLTMuMjcgMC4yMS01LjM3IDAuNTYtNy40MSAwLjU3LTMuMjcgMS40My01IDMuOTQtNy44MSAxLjYtMS44IDMuNy0zLjc2IDYuOTMtNi40NyA0Ljc3LTMuOTkxIDguMTEtNi45OSAxMS4yNi0xMC4xMjUgNC45MS00LjkwNyA3LjQ2LTguMjYgOS4yOC0xMi4xODcgMS40My0zLjA5MiAyLjIyLTYuMTY2IDIuNDYtOS41MzIgMC4wNi0wLjgxNiAwLjA3LTMuMDMgMC0zLjk2OC0wLjQ1LTcuMDQzLTMuMS0xMy4yNTMtOC4xNS0xOS4wMzItMC44LTAuOTA5LTIuNzgtMi44ODctMy43Mi0zLjcxOC00Ljk2LTQuMzk0LTEwLjY5LTcuMzUzLTE3LjU2LTkuMDk0LTQuMTktMS4wNjItOC4yMy0xLjYtMTMuMzUtMS43NS0wLjc4LTAuMDIzLTEuNTktMC4wMzYtMi4zNy0wLjAzMnptLTEwLjkwOCAxMDMuNnYyMmgyMS45OTh2LTIyaC0yMS45OTh6Ii8+CiA8L2c+Cjwvc3ZnPgo='/>" +
|
||
"</div>" : ""
|
||
div.innerHTML = "<label for=''>" + (altName ?? this.name ?? "") + "</label>" + "<div>" + this.content + "</div>" +
|
||
desc
|
||
return div
|
||
}
|
||
}
|
||
|
||
function createFrom(rows, classList, data) {
|
||
let container = document.createElement('div')
|
||
container.classList.add(...classList.split(" "))
|
||
for (const options of data) {
|
||
let prop = new Property(options.index, rows[options.index])
|
||
container.appendChild(prop.toDiv(options.name, options.desc))
|
||
}
|
||
|
||
return container
|
||
}
|
||
|
||
function createFromMulti(rows, classList, data) {
|
||
let rowData = []
|
||
let toIndex = data.to ?? rows.length - 1
|
||
for (let i = data.from; i <= toIndex; i++) {
|
||
rowData.push({ index: i })
|
||
}
|
||
|
||
return createFrom(rows, classList, rowData)
|
||
}
|
||
|
||
function addCss(link) {
|
||
let css = document.createElement("link")
|
||
css.href = link
|
||
css.rel = "stylesheet"
|
||
document.head.appendChild(css)
|
||
}
|
||
|
||
function addJs(link) {
|
||
let script = document.createElement("script")
|
||
script.src = link
|
||
document.head.appendChild(script)
|
||
}
|
||
|
||
const sleep = ms => new Promise(res => setTimeout(res, ms));
|
||
|
||
function isEditCpPage() {
|
||
let params = new URLSearchParams(document.location.search)
|
||
return params.get("action") === "edit"
|
||
}
|
||
|
||
function isDeleteCpPage() {
|
||
let params = new URLSearchParams(document.location.search)
|
||
return params.get("action") === "delete"
|
||
}
|
||
|
||
async function updatePoint(formData) {
|
||
return await fetch(`https://runcity.geo.rictum.ru/api/competitions/${window.location.pathname.split('/')[1]}/update`, {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
}
|
||
|
||
async function deletePoint() {
|
||
return await fetch(`https://runcity.geo.rictum.ru/api/points/${new URLSearchParams(location.search).get("cp_id")}`, {
|
||
method: 'DELETE'
|
||
})
|
||
}
|
||
|
||
function copyCoordinates() {
|
||
let copyButton = document.createElement("button")
|
||
copyButton.addEventListener("click", async event => {
|
||
event.preventDefault();
|
||
let lat = document.querySelector(`input[name="cp[lattitude]"]`).value
|
||
let lon = document.querySelector(`input[name="cp[longitude]"]`).value
|
||
|
||
const text = new Blob([`${lat}, ${lon}`], { type: "text/plain" });
|
||
const data = new ClipboardItem({ "text/plain": text });
|
||
await navigator.clipboard.write([data]);
|
||
})
|
||
copyButton.classList.add("copy-button")
|
||
|
||
let copyImage = document.createElement("img")
|
||
copyImage.src = "https://upload.wikimedia.org/wikipedia/commons/a/aa/Bw_copy_icon_320x320.svg"
|
||
copyButton.appendChild(copyImage)
|
||
|
||
return copyButton
|
||
}
|
||
|
||
function yandexMaps(lat, lon, zoom) {
|
||
return `https://yandex.ru/maps/213/moscow/?ll=${lon}%2C${lat}&z=${zoom}`
|
||
}
|
||
|
||
function googleMaps(lat, lon, meters) {
|
||
return `https://www.google.ru/maps/@${lat},${lon},${meters}m`
|
||
}
|
||
|
||
function pastvu(lat, lon, zoom) {
|
||
return `https://pastvu.com/?g=${lat},${lon}&z=${zoom}&s=yandex&t=scheme&type=1`
|
||
}
|
||
|
||
function twoGis(lat, lon, zoom) {
|
||
return `https://2gis.ru/moscow?m=${lon}%2C${lat}%2F${zoom}`
|
||
}
|
||
|
||
function makeRef(linkCallback, iconSrc, zoom) {
|
||
let ref = document.createElement("a")
|
||
ref.href = linkCallback(lat, lon, zoom)
|
||
ref.setAttribute('target', "_blank")
|
||
ref.addEventListener("click", function (e) {
|
||
let lat = document.querySelector(`input[name="cp[lattitude]"]`).value
|
||
let lon = document.querySelector(`input[name="cp[longitude]"]`).value
|
||
this.href = linkCallback(lat, lon, zoom)
|
||
})
|
||
|
||
let icon = document.createElement("img")
|
||
icon.src = iconSrc
|
||
icon.classList.add("map-icon")
|
||
ref.appendChild(icon)
|
||
|
||
return ref
|
||
}
|
||
|
||
let makeCoordinatesLinks = (function() {
|
||
var executed = false
|
||
return function () {
|
||
if (executed) return
|
||
executed = true
|
||
|
||
let linksContainer = document.createElement("div")
|
||
|
||
linksContainer.appendChild(copyCoordinates())
|
||
linksContainer.appendChild(makeRef(yandexMaps, "https://upload.wikimedia.org/wikipedia/commons/7/72/Yandex_Maps_icon.svg", ZOOM))
|
||
linksContainer.appendChild(makeRef(googleMaps, "https://upload.wikimedia.org/wikipedia/commons/a/aa/Google_Maps_icon_%282020%29.svg", METERS))
|
||
linksContainer.appendChild(makeRef(pastvu, "https://pastvu.com/coast-icon.png", ZOOM))
|
||
linksContainer.appendChild(makeRef(twoGis, "https://d-assets.2gis.ru/favicon.png", ZOOM))
|
||
|
||
document.querySelector(`div:has(> div > input[name="cp[longitude]"])`).after(linksContainer)
|
||
}
|
||
})()
|
||
|
||
function makeDownloadLink(name, href = null) {
|
||
let downloadLink = document.createElement("a")
|
||
downloadLink.setAttribute("download", name)
|
||
downloadLink.textContent = "Скачать"
|
||
downloadLink.setAttribute("target", "_blank")
|
||
if (href)
|
||
downloadLink.href = href
|
||
|
||
return downloadLink
|
||
}
|
||
|
||
async function sendFileDeleted(inputName) {
|
||
let formData = new FormData()
|
||
|
||
let normalInputName = 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 addDisplayedFile(inputName, type, file, preview, removeLink) {
|
||
if (!inputName || !file || !removeLink) return
|
||
|
||
let input = document.querySelector(`input[name="${inputName}\[\]"]`)
|
||
let fileListContainer = input.parentElement.parentElement.querySelector(".file-list-container")
|
||
let fileContainer = document.createElement("div")
|
||
fileContainer.classList.add("file-container")
|
||
|
||
const displayedFile = document.createElement(type ?? "a")
|
||
displayedFile.classList.add("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 = document.createElement("div")
|
||
fileButtonsContainer.classList.add("file-buttons-container")
|
||
|
||
fileButtonsContainer.appendChild(makeDownloadLink(/[^/]*$/.exec(new URL(file).pathname)[0], file))
|
||
|
||
let deleteButton = document.createElement("button")
|
||
deleteButton.type = "button"
|
||
deleteButton.classList.add("button-delete")
|
||
deleteButton.textContent = "x"
|
||
deleteButton.addEventListener("click", async e => {
|
||
if (!confirm("Точно?")) return
|
||
|
||
await fetch(removeLink)
|
||
await sendFileDeleted(inputName)
|
||
removedFilesLinks.push(removeLink)
|
||
|
||
fileListContainer.removeChild(fileContainer)
|
||
})
|
||
fileButtonsContainer.appendChild(deleteButton)
|
||
|
||
fileContainer.appendChild(displayedFile)
|
||
fileContainer.appendChild(fileButtonsContainer)
|
||
|
||
fileListContainer.appendChild(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 = document.createElement(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 fileListContainer = this.parentElement.parentElement.querySelector(".file-list-container")
|
||
let fileContainer = document.createElement("div")
|
||
fileContainer.classList.add("file-container")
|
||
|
||
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 = document.createElement("div")
|
||
fileButtonsContainer.classList.add("file-buttons-container")
|
||
|
||
let downloadLink = makeDownloadLink(file.name)
|
||
fileButtonsContainer.appendChild(downloadLink)
|
||
|
||
let deleteButton = document.createElement("button")
|
||
deleteButton.classList.add("button-delete")
|
||
deleteButton.textContent = "x"
|
||
deleteButton.type = "button"
|
||
deleteButton.addEventListener("click", e => {
|
||
let index = [...fileListContainer.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
|
||
|
||
fileListContainer.removeChild(fileContainer)
|
||
})
|
||
fileButtonsContainer.appendChild(deleteButton)
|
||
|
||
fileContainer.appendChild(displayedFile)
|
||
fileContainer.appendChild(fileButtonsContainer)
|
||
|
||
fileListContainer.appendChild(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() {
|
||
var executed = false
|
||
return function(insertedFileRows) {
|
||
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 = document.createElement("label")
|
||
pseudoInput.classList.add("custom-file-upload")
|
||
pseudoInput.setAttribute("for", element.id)
|
||
pseudoInput.textContent = "+"
|
||
element.parentElement.insertBefore(pseudoInput, element)
|
||
|
||
let fileListContainer = document.createElement("div")
|
||
fileListContainer.classList.add("file-list-container")
|
||
element.parentElement.parentElement.appendChild(fileListContainer)
|
||
|
||
element.addEventListener("change", makeHandleFilesFunc(), false)
|
||
})
|
||
|
||
moveFileInputValues(insertedFileRows)
|
||
}
|
||
})()
|
||
|
||
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) {
|
||
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
|
||
}
|
||
|
||
addDisplayedFile(fileInput, type, fileUrl, preview, deleteUrl)
|
||
}
|
||
}
|
||
}
|
||
|
||
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.appendChild(became)
|
||
setInputValues(became, inputValues)
|
||
createSendButtons()
|
||
}
|
||
|
||
function prettify(form, was, became, insertedFileRows) {
|
||
moveInputValues(form, was, became)
|
||
prettifyFiles(insertedFileRows)
|
||
|
||
$("#cps_main").select2()
|
||
makeCoordinatesLinks()
|
||
}
|
||
|
||
function uglify(form, was, became) {
|
||
moveInputValues(form, was, became)
|
||
for (const removedFileLink of removedFilesLinks) {
|
||
removeDeletedFilesFromUglyVersion(removedFileLink)
|
||
}
|
||
removedFilesLinks = []
|
||
}
|
||
|
||
function createAlwaysPrettifyInput(index) {
|
||
let alwaysPrettify = document.createElement("div")
|
||
alwaysPrettify.classList.add("always-prettify-container")
|
||
|
||
let alwaysPrettifyLabel = document.createElement("label")
|
||
alwaysPrettifyLabel.setAttribute("for", "always-prettify-" + index)
|
||
alwaysPrettifyLabel.textContent = "Всегда"
|
||
alwaysPrettify.appendChild(alwaysPrettifyLabel)
|
||
|
||
let alwaysPrettifyCheckbox = document.createElement("input")
|
||
alwaysPrettifyCheckbox.type = "checkbox"
|
||
alwaysPrettifyCheckbox.id = "always-prettify-" + index
|
||
alwaysPrettifyCheckbox.name = "always-prettify-" + index
|
||
alwaysPrettifyCheckbox.addEventListener("change", function() {
|
||
let otherCheckboxes = document.querySelectorAll(`input[name^="always-prettify-"]`)
|
||
for (let checkbox of otherCheckboxes) {
|
||
if (checkbox.id !== this.id) {
|
||
checkbox.checked = this.checked
|
||
}
|
||
}
|
||
if (this.checked)
|
||
localStorage.setItem(localStorageItems.ALWAYS_PRETTIFY, "+")
|
||
else
|
||
localStorage.removeItem(localStorageItems.ALWAYS_PRETTIFY)
|
||
})
|
||
|
||
alwaysPrettify.appendChild(alwaysPrettifyCheckbox)
|
||
|
||
i++
|
||
|
||
return alwaysPrettify
|
||
}
|
||
|
||
function hide(elList) {
|
||
elList.forEach(el => el.classList.add("hidden"))
|
||
}
|
||
|
||
function show(elList) {
|
||
elList.forEach(el => el.classList.remove("hidden"))
|
||
}
|
||
|
||
function makeSwiper(dialog, fileListContainer, src) {
|
||
let files = [...fileListContainer.querySelectorAll(`:is(.preview, .preview-small)`)]
|
||
|
||
let swiperDiv = document.createElement("div")
|
||
swiperDiv.classList.add("swiper")
|
||
|
||
let swiperWrapper = document.createElement("div")
|
||
swiperWrapper.classList.add("swiper-wrapper")
|
||
|
||
for (const file of files) {
|
||
let swiperSlide = document.createElement("div")
|
||
swiperSlide.classList.add("swiper-slide")
|
||
|
||
let downloadLink = document.createElement("a")
|
||
downloadLink.classList.add("swiper-download-link")
|
||
downloadLink.href = file.dataset.origin
|
||
downloadLink.text = "Скачать"
|
||
downloadLink.setAttribute("target", "_blank")
|
||
swiperSlide.appendChild(downloadLink)
|
||
|
||
let swiperFile = file.cloneNode(true)
|
||
if (swiperFile.dataset.origin)
|
||
swiperFile.src = swiperFile.dataset.origin
|
||
|
||
swiperSlide.appendChild(swiperFile)
|
||
swiperWrapper.appendChild(swiperSlide)
|
||
}
|
||
|
||
swiperDiv.appendChild(swiperWrapper)
|
||
|
||
let prevButton = document.createElement("div")
|
||
prevButton.classList.add("swiper-button-prev")
|
||
swiperDiv.appendChild(prevButton)
|
||
|
||
let nextButton = document.createElement("div")
|
||
nextButton.classList.add("swiper-button-next")
|
||
swiperDiv.appendChild(nextButton)
|
||
|
||
dialog.appendChild(swiperDiv)
|
||
|
||
new Swiper('.swiper', {
|
||
initialSlide: files.findIndex(el => el.dataset.origin && el.dataset.origin === src || el.src === src),
|
||
|
||
navigation: {
|
||
nextEl: '.swiper-button-next',
|
||
prevEl: '.swiper-button-prev',
|
||
},
|
||
})
|
||
|
||
bindArrowsForGallery('.swiper-button-prev', '.swiper-button-next')
|
||
}
|
||
|
||
function bindArrowsForGallery(leftButtonQuery, rightButtonQuery) {
|
||
document.addEventListener("keydown", function(e) {
|
||
if (!document.querySelector("dialog").open) return
|
||
switch(e.key) {
|
||
case "ArrowLeft":
|
||
$(leftButtonQuery).click()
|
||
break
|
||
|
||
case "ArrowRight":
|
||
$(rightButtonQuery).click()
|
||
break
|
||
|
||
default: return
|
||
}
|
||
e.preventDefault()
|
||
})
|
||
}
|
||
|
||
async function sendForm(onSend) {
|
||
let formData = new FormData(document.querySelector("form"))
|
||
|
||
let fileContainers = [...document.querySelectorAll(".file-list-container")]
|
||
let fileInputNames = ["legend_photo", "legend_files", "admin_photo", "admin_files"]
|
||
for (let [i, fileContainer] of fileContainers.entries()) {
|
||
formData.set(`cp[${fileInputNames[i]}]`, fileContainer.children.length)
|
||
}
|
||
|
||
if (formData.get("cp[id]") == '') {
|
||
localStorage.setItem(localStorageItems.NEED_UPDATE_ID, true)
|
||
}
|
||
|
||
let props = document.querySelectorAll("input[name^=\"prop_\"]");
|
||
for (let prop of props) {
|
||
let parent = prop.parentElement
|
||
let propName
|
||
|
||
if (parent.tagName === "DIV") {
|
||
propName = parent.parentElement.querySelector("label").textContent
|
||
}
|
||
else if (parent.tagName === "TD") {
|
||
propName = parent.parentElement.querySelector("td:first-child").textContent
|
||
}
|
||
|
||
formData.set(`propname[${prop.name}]`, propName)
|
||
}
|
||
|
||
let result = await updatePoint(formData)
|
||
|
||
try {
|
||
console.log(result.ok)
|
||
}
|
||
catch (e) {
|
||
console.log(e)
|
||
}
|
||
finally {
|
||
onSend()
|
||
}
|
||
}
|
||
|
||
function createSaveAndNewButton() {
|
||
let saveAndNewButton = document.createElement("button")
|
||
saveAndNewButton.textContent = "+"
|
||
saveAndNewButton.type = "button"
|
||
saveAndNewButton.classList.add("safe-action")
|
||
saveAndNewButton.addEventListener("click", () => {
|
||
sendForm(() => {
|
||
let cpNumber = document.querySelector(`input[name="cp[number]"]`).value
|
||
let lattitude = document.querySelector(`input[name="cp[lattitude]"]`).value
|
||
let longitude = document.querySelector(`input[name="cp[longitude]"]`).value
|
||
|
||
localStorage.setItem(localStorageItems.JUST_CREATED, cpNumber)
|
||
localStorage.setItem(localStorageItems.LATTITUDE, lattitude)
|
||
localStorage.setItem(localStorageItems.LONGITUDE, longitude)
|
||
|
||
document.querySelector(`input[name="save_go"]`).click()
|
||
})
|
||
})
|
||
|
||
return saveAndNewButton
|
||
}
|
||
|
||
function createSendButtons() {
|
||
if (document.querySelector(".pseudo-save")) return
|
||
|
||
let saveAndStayButtons = document.querySelectorAll(`input[name="save_go"]`)
|
||
let saveAndExitButtons = document.querySelectorAll(`input[name="save_exit"]`)
|
||
let saveButtons = [...saveAndStayButtons, ...saveAndExitButtons]
|
||
|
||
for (let saveButton of saveButtons) {
|
||
let pseudoSaveButton = document.createElement("button")
|
||
pseudoSaveButton.type = "button"
|
||
pseudoSaveButton.textContent = saveButton.value
|
||
pseudoSaveButton.classList.add("safe-action", "pseudo-save")
|
||
pseudoSaveButton.addEventListener("click", async () => await sendForm(() => {
|
||
if (document.querySelector(`input[name="cp[id]"]`).value != '') {
|
||
saveButton.click()
|
||
return
|
||
}
|
||
|
||
if (saveButton.name == "save_exit") {
|
||
localStorage.setItem(localStorageItems.REDIRECT_EXIT, true)
|
||
}
|
||
|
||
saveAndStayButtons[0].click()
|
||
}))
|
||
|
||
saveButton.style.display = "none"
|
||
saveButton.parentElement.insertBefore(pseudoSaveButton, saveButton)
|
||
}
|
||
|
||
saveAndStayButtons.forEach(el => el.after(createSaveAndNewButton()))
|
||
}
|
||
|
||
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"]`)
|
||
|
||
link.addEventListener("click", async e => {
|
||
e.preventDefault()
|
||
if (!confirm("Точно?")) return
|
||
|
||
await sendFileDeleted(fileInput.name.split("[")[0])
|
||
location.href = link.href
|
||
})
|
||
}
|
||
|
||
}
|
||
|
||
function addFullscreenButton() {
|
||
$(async () => {
|
||
if (document.querySelector("#map") !== null) {
|
||
while (L.Control.Fullscreen === undefined) {
|
||
await sleep(500)
|
||
}
|
||
map.addControl(new L.Control.Fullscreen())
|
||
}
|
||
})
|
||
}
|
||
|
||
let styles = `
|
||
.large-menu {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 10;
|
||
background: white;
|
||
}
|
||
|
||
#content-wrapper {
|
||
display: flex;
|
||
gap: 20px;
|
||
|
||
#props {
|
||
width: unset !important;
|
||
}
|
||
|
||
form {
|
||
width: 50%;
|
||
}
|
||
|
||
#map-wrapper {
|
||
width: 50%;
|
||
}
|
||
|
||
#map {
|
||
width: unset !important;
|
||
}
|
||
|
||
#new {
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
& > :not(:first-child) {
|
||
padding-top: 5px;
|
||
border-top: 1px solid #ddd;
|
||
}
|
||
|
||
& > :not(:last-child) {
|
||
padding-bottom: 5px;
|
||
}
|
||
|
||
.map-icon {
|
||
width: 15px;
|
||
height: 15px;
|
||
}
|
||
|
||
.copy-button {
|
||
all: unset;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.copy-button img {
|
||
width: 15px;
|
||
heigth: 15px;
|
||
}
|
||
|
||
input[type=radio], input[type=checkbox] {
|
||
margin: 0;
|
||
}
|
||
|
||
input[type="file"] {
|
||
display: none;
|
||
}
|
||
|
||
div > input[type="checkbox"] {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
input#cp_number {
|
||
width: 3em;
|
||
}
|
||
|
||
select#cps_main {
|
||
width: 6em;
|
||
}
|
||
|
||
input:is(#lat, #lng) {
|
||
width: 5.5em;
|
||
}
|
||
|
||
input[name="cp[name_int]"] {
|
||
width: 34em;
|
||
}
|
||
}
|
||
|
||
#cps_main {
|
||
width: 150px;
|
||
}
|
||
|
||
input[type=submit] {
|
||
width: fit-content;
|
||
}
|
||
|
||
.desc-icon-container {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.desc-icon {
|
||
width: 15px;
|
||
height: 15px;
|
||
cursor: help;
|
||
}
|
||
|
||
button, input[type=submit] {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.buttons-row__content-wrapper {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 10px;
|
||
font-weight: normal;
|
||
}
|
||
|
||
.custom-file-upload {
|
||
display: block;
|
||
width: fit-content;
|
||
border: 1px solid black;
|
||
padding: 5px 14px;
|
||
border-radius: 5px;
|
||
box-shadow: 0 1px 3px #ddd;
|
||
background: linear-gradient(white, #ddd);
|
||
}
|
||
|
||
.buttons > * > * {
|
||
display: flex;
|
||
gap: 10px;
|
||
}
|
||
|
||
.always-prettify-container {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
}
|
||
|
||
.header > * {
|
||
display: flex;
|
||
gap: 5px;
|
||
}
|
||
|
||
:is(.header, .options) input {
|
||
width: unset;
|
||
}
|
||
|
||
.header {
|
||
display: flex;
|
||
gap: 30px;
|
||
align-items: start;
|
||
}
|
||
|
||
.options {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 10px;
|
||
}
|
||
|
||
.options > * {
|
||
display: flex;
|
||
gap: 5px;
|
||
align-items: center;
|
||
}
|
||
|
||
.legend-container {
|
||
display: flex;
|
||
}
|
||
|
||
.legend-container > :not(:last-child) {
|
||
padding-right: 15px;
|
||
border-right: 1px solid #ddd;
|
||
}
|
||
|
||
.legend-container > :not(:first-child) {
|
||
padding-left: 15px;
|
||
}
|
||
|
||
.legend-container > * {
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex: 0 1 48%;
|
||
gap: 5px;
|
||
}
|
||
|
||
.legend-container__desc-header {
|
||
display: flex;
|
||
gap: 10px;
|
||
align-items: center;
|
||
justify-content: end;
|
||
}
|
||
|
||
.legend-desc {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 5px;
|
||
}
|
||
|
||
.collapsed, .hidden {
|
||
display: none;
|
||
}
|
||
|
||
.collapse-button::after {
|
||
content: "Свернуть"
|
||
}
|
||
|
||
.collapsed + * > .collapse-button::after {
|
||
content: "Развернуть"
|
||
}
|
||
|
||
:is(.comment, .legend-desc) > * {
|
||
display: flex;
|
||
gap: 5px;
|
||
}
|
||
|
||
:is(.comment, .legend-desc) label {
|
||
display: block;
|
||
width: 10em;
|
||
}
|
||
|
||
:is(.comment, .legend-desc) > * > :nth-child(2) {
|
||
flex: 1 1 auto;
|
||
}
|
||
|
||
textarea {
|
||
width: 100%;
|
||
}
|
||
|
||
.files-container input[type=radio] {
|
||
display: none;
|
||
}
|
||
|
||
.file-list-container {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 10px;
|
||
margin-top: 5px;
|
||
}
|
||
|
||
.file-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 5px;
|
||
}
|
||
|
||
.file-container img.preview {
|
||
width: 120px;
|
||
}
|
||
|
||
.file-container img.preview-small {
|
||
width: 60px;
|
||
}
|
||
|
||
.file-container img:is(.preview, .preview-small) {
|
||
cursor: zoom-in;
|
||
}
|
||
|
||
dialog .preview,
|
||
.swiper {
|
||
max-width: 1000px;
|
||
width: 100%;
|
||
max-height: 500px;
|
||
height: 100%;
|
||
}
|
||
|
||
.swiper-button-next,
|
||
.swiper-button-prev {
|
||
user-select: none;
|
||
-webkit-user-select: none;
|
||
}
|
||
|
||
.swiper-wrapper {
|
||
align-items: center;
|
||
}
|
||
|
||
.swiper-wrapper > .swiper-slide {
|
||
width: 100%;
|
||
max-height: 500px;
|
||
height: 100%;
|
||
}
|
||
|
||
.swiper-slide img {
|
||
width: 100%;
|
||
max-height: 500px;
|
||
height: 100%;
|
||
object-fit: contain;
|
||
object-position: center;
|
||
}
|
||
|
||
.swiper-download-link {
|
||
display: block;
|
||
position: absolute;
|
||
top: 0;
|
||
right: 0;
|
||
background: white;
|
||
padding: 5px 10px;
|
||
margin: 5px;
|
||
border: 1px solid #ccc;
|
||
border-radius: 7.5px;
|
||
}
|
||
|
||
button.button-delete {
|
||
padding: 0;
|
||
border: 0;
|
||
margin: 0;
|
||
background: none;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.admin-files-container {
|
||
display: flex;
|
||
}
|
||
|
||
.admin-files-container > :not(:last-child) {
|
||
padding-right: 10px;
|
||
border-right: 1px solid #ddd;
|
||
}
|
||
|
||
.admin-files-container > :not(:first-child) {
|
||
padding-left: 10px;
|
||
}
|
||
|
||
dialog img.preview {
|
||
width: auto;
|
||
}
|
||
|
||
.file-buttons-container {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
}
|
||
}
|
||
`
|
||
|
||
/* REDIRECTS */
|
||
|
||
let justCreated = localStorage.getItem(localStorageItems.JUST_CREATED)
|
||
let prevCreated = localStorage.getItem(localStorageItems.PREV_CREATED)
|
||
let needUpdateId = localStorage.getItem(localStorageItems.NEED_UPDATE_ID)
|
||
let exit = localStorage.getItem(localStorageItems.REDIRECT_EXIT)
|
||
|
||
if (needUpdateId) {
|
||
let formData = new FormData()
|
||
formData.set("cp[id]", new URLSearchParams(document.location.search).get("cp_id"))
|
||
formData.set("cp[number]", document.querySelector(`input[name="cp[number]"]`).value)
|
||
formData.set("update_id", true)
|
||
updatePoint(formData).then(() => localStorage.removeItem(localStorageItems.NEED_UPDATE_ID))
|
||
}
|
||
|
||
if (exit) {
|
||
localStorage.removeItem(localStorageItems.REDIRECT_EXIT)
|
||
|
||
location.href = location.href.replace(location.search, '')
|
||
return
|
||
}
|
||
|
||
if (justCreated !== null) {
|
||
localStorage.setItem(localStorageItems.PREV_CREATED, justCreated)
|
||
localStorage.removeItem(localStorageItems.JUST_CREATED)
|
||
|
||
location.href = location.href.replace(location.search, "?action=edit")
|
||
return
|
||
}
|
||
if (prevCreated !== null) {
|
||
document.querySelector(`input[name="cp[number]"]`).value = parseInt(localStorage.getItem(localStorageItems.PREV_CREATED)) + 1
|
||
document.querySelector(`input[name="cp[lattitude]"]`).value = localStorage.getItem(localStorageItems.LATTITUDE)
|
||
document.querySelector(`input[name="cp[longitude]"]`).value = localStorage.getItem(localStorageItems.LONGITUDE)
|
||
|
||
localStorage.removeItem(localStorageItems.PREV_CREATED)
|
||
localStorage.removeItem(localStorageItems.LATTITUDE)
|
||
localStorage.removeItem(localStorageItems.LONGITUDE)
|
||
}
|
||
|
||
/* HEAD */
|
||
|
||
let styleSheet = document.createElement("style")
|
||
styleSheet.textContent = styles
|
||
document.head.appendChild(styleSheet)
|
||
|
||
/* SWITCH FOR DIFFERENT PAGES */
|
||
|
||
if (isDeleteCpPage()) {
|
||
let deleteButton = document.querySelector(`input[name="delete_go"]`)
|
||
let pseudoDeleteButton = document.createElement("button")
|
||
pseudoDeleteButton.type = "button"
|
||
pseudoDeleteButton.textContent = deleteButton.value
|
||
pseudoDeleteButton.classList.add("unsafe-action", "pseudo-save")
|
||
pseudoDeleteButton.addEventListener("click", async () => {
|
||
await deletePoint()
|
||
deleteButton.click()
|
||
})
|
||
|
||
deleteButton.style.display = "none"
|
||
deleteButton.parentElement.insertBefore(pseudoDeleteButton, deleteButton)
|
||
|
||
return
|
||
}
|
||
|
||
addJs('https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/Leaflet.fullscreen.min.js')
|
||
addCss('https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/leaflet.fullscreen.css')
|
||
|
||
addFullscreenButton()
|
||
|
||
if (!isEditCpPage()) {
|
||
return
|
||
}
|
||
|
||
/* action=edit HEAD */
|
||
|
||
addCss("https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css")
|
||
addCss("https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css")
|
||
|
||
/* NEW DEFALUT VALUES */
|
||
|
||
document.querySelector(`#props input[name="new_file_type1"][value="l"]`).click()
|
||
document.querySelector(`#props input[name="new_file_type4"][value="l"]`).click()
|
||
|
||
/* CONTAINER */
|
||
|
||
let form = document.querySelector('form')
|
||
let rows = [...document.querySelectorAll('#props > tbody > tr')]
|
||
let insertedFileRows = new Map()
|
||
let i = 0
|
||
while (i < rows.length) {
|
||
if ([23, 27, 31, 35].includes(i) && rows[i].querySelector(`input[type="file"]`) == null) {
|
||
if (!insertedFileRows.has(i)) {
|
||
insertedFileRows.set(i, [rows[i]])
|
||
}
|
||
else {
|
||
let savedRows = insertedFileRows.get(i)
|
||
savedRows.push(rows[i])
|
||
insertedFileRows.set(i, savedRows)
|
||
}
|
||
rows.splice(i, 1)
|
||
}
|
||
else {
|
||
i++
|
||
}
|
||
}
|
||
|
||
let container = document.createElement('div')
|
||
container.id = "new"
|
||
let oldTable = document.querySelector("#props")
|
||
|
||
/* HEADER */
|
||
|
||
let headerContainer = createFrom(rows, "header", [
|
||
{ index: 2, name: "№", desc: "" },
|
||
{ index: 8, name: "Название" }
|
||
])
|
||
|
||
let copyLink = document.createElement("div")
|
||
copyLink.innerHTML = new Property(2, rows[2]).desc
|
||
headerContainer.append(copyLink)
|
||
|
||
/* TOP BUTTONS */
|
||
|
||
let topButtonsContainer = createFrom(rows, "buttons", [
|
||
{ index: 0 }
|
||
])
|
||
|
||
let bottomButtonsContainer = topButtonsContainer.cloneNode(true)
|
||
|
||
document.querySelectorAll("#props tr:is(:first-child, :last-child) th").forEach((el, index) => {
|
||
let rowContentWrapper = document.createElement("div")
|
||
rowContentWrapper.classList.add("buttons-row__content-wrapper")
|
||
while ([...el.children].length > 0) {
|
||
let child = el.firstChild
|
||
rowContentWrapper.appendChild(child)
|
||
}
|
||
|
||
let prettifyButton = document.createElement("button")
|
||
prettifyButton.type = "button"
|
||
prettifyButton.textContent = "Сделать красиво"
|
||
prettifyButton.addEventListener("click", () => {
|
||
prettify(form, oldTable, container, insertedFileRows)
|
||
})
|
||
|
||
rowContentWrapper.appendChild(prettifyButton)
|
||
rowContentWrapper.appendChild(createAlwaysPrettifyInput(index))
|
||
|
||
el.appendChild(rowContentWrapper)
|
||
})
|
||
|
||
;[topButtonsContainer, bottomButtonsContainer].forEach((el, index) => {
|
||
let unglifyButton = document.createElement("button")
|
||
unglifyButton.type = "button"
|
||
unglifyButton.textContent = "Сделать некрасиво"
|
||
unglifyButton.addEventListener("click", () => {
|
||
uglify(form, container, oldTable)
|
||
})
|
||
|
||
let topRowContentWrapper = el.querySelector("div > div > div")
|
||
topRowContentWrapper.appendChild(unglifyButton)
|
||
topRowContentWrapper.appendChild(createAlwaysPrettifyInput(index))
|
||
})
|
||
|
||
addUglyDeleteListener()
|
||
createSendButtons()
|
||
|
||
/* OPTIONS */
|
||
|
||
let firstContainer = createFrom(rows, "options", [
|
||
{ index: 3 },
|
||
{ index: 4, name: "КП-загадка" },
|
||
{ index: 16, name: "Этапник" },
|
||
{ index: 7, name: "Пиктограмма" },
|
||
{ index: 12, name: "Нужна ИС" },
|
||
{ index: 17, name: "Спрятать ИС" },
|
||
{ index: 14, name: "Основной КП" },
|
||
{ index: 10, name: "Широта" },
|
||
{ index: 11, name: "Долгота" },
|
||
{ index: 5, name: "Старт" },
|
||
{ index: 6, name: "Финиш" },
|
||
{ index: 15, name: "Знак" }
|
||
])
|
||
|
||
let commentContainer = createFrom(rows, "comment", [
|
||
{ index: 9, desc: "" }
|
||
])
|
||
|
||
/* LEGEND */
|
||
|
||
let legendContainer = document.createElement("div")
|
||
legendContainer.classList.add("legend-container")
|
||
|
||
/* LEGEND DESC */
|
||
|
||
let legendDescContainer = document.createElement("div")
|
||
legendDescContainer.classList.add("legend-container__desc")
|
||
|
||
let legendDescHeader = document.createElement("div")
|
||
legendDescHeader.classList.add("legend-container__desc-header")
|
||
|
||
|
||
const LEGEND_RU_LABEL = "Русский"
|
||
const LEGEND_EN_LABEL = "Английский"
|
||
let legendLang = document.createElement("div")
|
||
legendLang.classList.add("legend-desc__lang")
|
||
legendLang.textContent = LEGEND_RU_LABEL
|
||
legendDescHeader.appendChild(legendLang)
|
||
|
||
let legendEnSwitchContainer = createFrom(rows, "legend-switch-container", [
|
||
{ index: 48 }
|
||
])
|
||
legendEnSwitchContainer.addEventListener("click", event => {
|
||
hide([legendRuDescContainer, legendRuHiddenDescContainer, legendEnSwitchContainer])
|
||
show([legendEnDescContainer, legendEnHiddenDescContainer, legendRuSwitchContainer])
|
||
legendLang.textContent = LEGEND_EN_LABEL
|
||
})
|
||
legendDescHeader.appendChild(legendEnSwitchContainer)
|
||
let copyDescButton = document.createElement("button")
|
||
copyDescButton.type = "button"
|
||
copyDescButton.textContent = "Копировать"
|
||
copyDescButton.addEventListener("click", () => {
|
||
let ruInputs = [...container.querySelectorAll(":is(input, textarea)[name^=\"cp_strings\[ru\]\"]")]
|
||
let enInputs = [...container.querySelectorAll(":is(input, textarea)[name^=\"cp_strings\[en\]\"]")]
|
||
for (const [i, enInput] of enInputs.entries()) {
|
||
enInput.value = ruInputs[i].value
|
||
}
|
||
})
|
||
|
||
let legendRuSwitchContainer = createFrom(rows, "legend-switch-container hidden", [
|
||
{ index: 39 }
|
||
])
|
||
legendRuSwitchContainer.addEventListener("click", event => {
|
||
hide([legendEnDescContainer, legendEnHiddenDescContainer, legendRuSwitchContainer])
|
||
show([legendRuDescContainer, legendRuHiddenDescContainer, legendEnSwitchContainer])
|
||
legendLang.textContent = LEGEND_RU_LABEL
|
||
})
|
||
legendDescHeader.appendChild(legendRuSwitchContainer)
|
||
|
||
legendDescHeader.appendChild(copyDescButton)
|
||
|
||
let legendRuDescContainer = createFrom(rows, "legend-desc", [
|
||
{ index: 40, desc: "" },
|
||
{ index: 41, desc: "" },
|
||
{ index: 42, desc: "" },
|
||
{ index: 43, desc: "" }
|
||
])
|
||
|
||
let legendRuHiddenDescContainer = createFrom(rows, "legend-desc collapsible collapsed", [
|
||
{ index: 44, desc: "" },
|
||
{ index: 45, desc: "" },
|
||
{ index: 46, desc: "" },
|
||
{ index: 47, desc: "" },
|
||
])
|
||
|
||
let legendEnDescContainer = createFrom(rows, "legend-desc hidden", [
|
||
{ index: 49, desc: "" },
|
||
{ index: 50, desc: "" },
|
||
{ index: 51, desc: "" },
|
||
{ index: 52, desc: "" }
|
||
])
|
||
|
||
let legendEnHiddenDescContainer = createFrom(rows, "legend-desc collapsible collapsed hidden", [
|
||
{ index: 53, desc: "" },
|
||
{ index: 54, desc: "" },
|
||
{ index: 55, desc: "" },
|
||
{ index: 56, desc: "" }
|
||
])
|
||
|
||
let hider = document.createElement("div")
|
||
let hiderButton = document.createElement("button")
|
||
hiderButton.classList.add("collapse-button")
|
||
hiderButton.setAttribute("type", "button")
|
||
hiderButton.addEventListener("click", event => {
|
||
container.querySelectorAll(".legend-desc.collapsible").forEach(element => {
|
||
element.classList.toggle("collapsed")
|
||
})
|
||
})
|
||
hider.appendChild(hiderButton)
|
||
|
||
legendDescContainer.appendChild(legendDescHeader)
|
||
legendDescContainer.appendChild(legendRuDescContainer)
|
||
legendDescContainer.appendChild(legendRuHiddenDescContainer)
|
||
legendDescContainer.appendChild(legendEnDescContainer)
|
||
legendDescContainer.appendChild(legendEnHiddenDescContainer)
|
||
legendDescContainer.appendChild(hider)
|
||
legendContainer.appendChild(legendDescContainer)
|
||
|
||
/* LEGEND FILES */
|
||
let legendFilesContainer = document.createElement("div")
|
||
legendFilesContainer.classList.add("legend-container__files")
|
||
|
||
let imagesForLegendContainer = createFrom(rows, "files-container", [
|
||
{ index: 23, name: "Фото в легенде" }
|
||
])
|
||
legendFilesContainer.appendChild(imagesForLegendContainer)
|
||
|
||
let audioForLegendContainer = createFrom(rows, "files-container", [
|
||
{ index: 27, name: "Файлы в легенде" }
|
||
])
|
||
legendFilesContainer.appendChild(audioForLegendContainer)
|
||
|
||
legendContainer.appendChild(legendFilesContainer)
|
||
|
||
let adminFilesContainer = document.createElement('div')
|
||
adminFilesContainer.classList.add('admin-files-container')
|
||
|
||
let imagesForAdminContainer = createFrom(rows, "files-container", [
|
||
{ index: 31, name: "Фото в админке" }
|
||
])
|
||
adminFilesContainer.appendChild(imagesForAdminContainer)
|
||
|
||
let audioForAdminContainer = createFrom(rows, "files-container", [
|
||
{ index: 35, name: "Файлы в админке" }
|
||
])
|
||
adminFilesContainer.appendChild(audioForAdminContainer)
|
||
|
||
/* BOTTOM OPTIONS */
|
||
|
||
let bottomOptionsContainer = createFromMulti(rows, "options bottom-options", {
|
||
from: 59,
|
||
to: rows.length - 3
|
||
})
|
||
|
||
/* APPEND ALL */
|
||
|
||
container.appendChild(topButtonsContainer)
|
||
container.appendChild(headerContainer)
|
||
container.appendChild(firstContainer)
|
||
container.appendChild(commentContainer)
|
||
container.appendChild(legendContainer)
|
||
container.appendChild(adminFilesContainer)
|
||
container.appendChild(bottomOptionsContainer)
|
||
container.appendChild(bottomButtonsContainer)
|
||
|
||
/* MAP */
|
||
if (map !== undefined && L !== undefined) {
|
||
let content = document.querySelector("#content")
|
||
let contentWrapper = document.createElement("div")
|
||
contentWrapper.id = "content-wrapper"
|
||
contentWrapper.appendChild(document.querySelector("form"))
|
||
contentWrapper.appendChild(document.querySelector("#map-wrapper"))
|
||
content.appendChild(contentWrapper)
|
||
|
||
let panToCenter = document.createElement("button")
|
||
panToCenter.type = "button"
|
||
panToCenter.textContent = "В центр"
|
||
panToCenter.addEventListener("click", () => {
|
||
let lat = document.querySelector("input[name=\"cp\[lattitude\]\"").value
|
||
let lon = document.querySelector("input[name=\"cp\[longitude\]\"").value
|
||
map.setView(new L.LatLng(parseFloat(lat), parseFloat(lon)), 16)
|
||
})
|
||
document.querySelector("#map_controls").appendChild(panToCenter)
|
||
}
|
||
|
||
/* DIALOG */
|
||
let dialog = document.createElement("dialog")
|
||
dialog.id = "dialog"
|
||
document.body.appendChild(dialog)
|
||
|
||
dialog.addEventListener("click", e => {
|
||
if (e.target == dialog) {
|
||
e.target.close()
|
||
}
|
||
})
|
||
|
||
dialog.addEventListener("close", e => {
|
||
e.target.innerHTML = ""
|
||
})
|
||
|
||
/* PRETTIFY CHECKBOX */
|
||
|
||
if (localStorage.getItem(localStorageItems.ALWAYS_PRETTIFY)) {
|
||
document.querySelector(`input[name^="always-prettify-0"]`).click()
|
||
prettify(form, oldTable, container, insertedFileRows)
|
||
}
|
||
|
||
})(); |