/*! * The 2022 r/place Atlas * Copyright (c) 2017 Roland Rytz * Copyright (c) 2022 Place Atlas contributors * Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt) */ const baseLinkElement = document.createElement("a") baseLinkElement.className = "btn btn-primary text-truncate" baseLinkElement.target = "_blank" baseLinkElement.rel = "noopener noreferrer" const baseGroupElement = document.createElement("div") baseGroupElement.className = "btn-group-vertical" function createLabel(name, value, parent) { const nameElement = document.createElement("span") nameElement.className = "fw-bold" nameElement.textContent = name const valueElement = document.createElement("span") valueElement.textContent = value parent.appendChild(nameElement) parent.appendChild(valueElement) return parent } function createInfoListItem(name, value) { const entryInfoListElement = document.createElement("li") entryInfoListElement.className = "list-group-item" createLabel(name, value, entryInfoListElement) return entryInfoListElement } function createInfoBlock(entry, isPreview) { const element = document.createElement("div") element.className = "card mb-2 overflow-hidden shadow" const headerElement = document.createElement("h4") headerElement.className = "card-header" const linkElement = document.createElement("a") linkElement.className = "text-decoration-none d-flex justify-content-between text-body" if (isPreview) linkElement.href = "#" else { linkElement.href = formatHash(entry.id) linkElement.addEventListener('click', e => { e.preventDefault() location.hash = formatHash(entry.id) window.dispatchEvent(new HashChangeEvent("hashchange")) }) } const linkNameElement = document.createElement("span") linkNameElement.className = "flex-grow-1 text-break" linkNameElement.textContent = entry.name headerElement.appendChild(linkElement) linkElement.appendChild(linkNameElement) linkElement.insertAdjacentHTML("beforeend", '') element.appendChild(headerElement) const bodyElement = document.createElement("div") bodyElement.className = "card-body d-flex flex-column gap-3" element.appendChild(bodyElement) if (entry.description) { const descElement = document.createElement("div") descElement.id = "objectDescription" // Formats single line break as br and two line breaks as a new paragraph let formattedDesc = entry.description.replace(/\n{2}/g, '

') formattedDesc = formattedDesc.replace(/\n/g, '
') descElement.innerHTML = '

' + formattedDesc + '

' bodyElement.appendChild(descElement) } const linkListElement = document.createElement("div") linkListElement.className = "d-flex flex-column gap-2" bodyElement.appendChild(linkListElement) const listElement = document.createElement("ul") listElement.className = "list-group list-group-flush" element.appendChild(listElement) if (entry.diff) { const diffElement = createInfoListItem("Diff: ", entry.diff) if (entry.diff === "add") { diffElement.className = "list-group-item list-group-item-success" } else if (entry.diff === "edit") { diffElement.className = "list-group-item list-group-item-warning" } else if (entry.diff === "delete") { diffElement.className = "list-group-item list-group-item-danger" } listElement.appendChild(diffElement) } // Entry data submitted to preview does not include center or path if (!isPreview) { const [x, y] = entry?.center listElement.appendChild(createInfoListItem("Position: ", `${Math.floor(x)}, ${Math.floor(y)}`)) if (entry.path) { const area = calcPolygonArea(entry.path) listElement.appendChild(createInfoListItem("Area: ", `${area} pixels`)) } } if (entry.links.subreddit?.length) { const subredditGroupElement = baseGroupElement.cloneNode() linkListElement.appendChild(subredditGroupElement) entry.links.subreddit.forEach(subreddit => { if (!subreddit) return subreddit = "r/" + subreddit const subredditLinkElement = baseLinkElement.cloneNode() subredditLinkElement.href = "https://reddit.com/" + subreddit subredditLinkElement.innerHTML = ` ${subreddit}` subredditGroupElement.appendChild(subredditLinkElement) }) } if (entry.links.website?.length) { const websiteGroupElement = baseGroupElement.cloneNode() linkListElement.appendChild(websiteGroupElement) entry.links.website.forEach(link => { if (!link) return const websiteLinkElement = baseLinkElement.cloneNode() websiteLinkElement.href = link try { const urlObject = new URL(link) websiteLinkElement.innerHTML = ` ${urlObject.hostname.replace(/^www./, "")}` } catch (e) { websiteLinkElement.innerHTML = ` Website` } websiteGroupElement.appendChild(websiteLinkElement) }) } if (entry.links.discord?.length) { const discordGroupElement = baseGroupElement.cloneNode() linkListElement.appendChild(discordGroupElement) entry.links.discord.forEach(link => { if (!link) return const discordLinkElement = baseLinkElement.cloneNode() discordLinkElement.href = "https://discord.gg/" + link discordLinkElement.innerHTML = ` ${link}` discordGroupElement.appendChild(discordLinkElement) }) } if (entry.links.wiki?.length) { const wikiGroupElement = baseGroupElement.cloneNode() linkListElement.appendChild(wikiGroupElement) entry.links.wiki.forEach(link => { if (!link) return const wikiLinkElement = baseLinkElement.cloneNode() wikiLinkElement.href = "https://place-wiki.stefanocoding.me/wiki/" + link.replace(/ /g, '_') wikiLinkElement.innerHTML = ` Wiki Article` wikiGroupElement.appendChild(wikiLinkElement) }) } // Adds id footer const idElement = document.createElement("div") idElement.className = "py-1" createLabel("ID: ", entry.id, idElement) const idElementContainer = document.createElement("div") idElementContainer.className = "card-footer d-flex justify-content-between align-items-center" idElementContainer.appendChild(idElement) element.appendChild(idElementContainer) // Adds edit button only if element is not deleted if (!isPreview && (!entry.diff || entry.diff !== "delete")) { const editElement = document.createElement("a") editElement.textContent = "Edit" editElement.className = "btn btn-sm btn-outline-primary" editElement.href = "./?mode=draw&id=" + entry.id + formatHash(undefined) editElement.title = "Edit " + entry.name idElementContainer.appendChild(editElement) } // Removes empty elements if (!bodyElement.hasChildNodes()) bodyElement.remove() if (!linkListElement.hasChildNodes()) linkListElement.remove() if (!listElement.hasChildNodes()) listElement.remove() return element }