add js to quote part of a post

This commit is contained in:
2025-07-06 22:31:54 +03:00
parent e60c74a90f
commit d006862422
4 changed files with 170 additions and 2 deletions

View File

@ -8,6 +8,125 @@
ta.focus();
})
}
function supportsPopover() {
return Object.hasOwn(HTMLElement.prototype, "popover");
}
if (supportsPopover()){
let quotedPostContainer = null;
function isQuoteSelectionValid() {
const selection = document.getSelection();
if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {
return false;
}
const range = selection.getRangeAt(0);
const commonAncestor = range.commonAncestorContainer;
const ancestorElement = commonAncestor.nodeType === Node.TEXT_NODE
? commonAncestor.parentNode
: commonAncestor;
const container = ancestorElement.closest(".post-inner");
if (!container) {
return false;
}
const success = container.contains(ancestorElement);
if (success) {
quotedPostContainer = container;
}
return success;
}
let quotePopover = null;
let isSelecting = false;
document.addEventListener("mousedown", () => {
isSelecting = true;
})
document.addEventListener("mouseup", () => {
isSelecting = false;
handlePossibleSelection();
})
document.addEventListener("keyup", (e) => {
if (e.shiftKey && (e.key.startsWith('Arrow') || e.key === 'Home' || e.key === 'End')) {
handlePossibleSelection();
}
})
function handlePossibleSelection() {
setTimeout(() => {
const valid = isQuoteSelectionValid();
if (isSelecting || !valid) {
removePopover();
return;
}
const selection = document.getSelection();
const selectionStr = selection.toString().trim();
if (selection.isCollapsed || selectionStr === "") {
removePopover();
return;
}
showPopover();
}, 50)
}
function removePopover() {
quotePopover?.hidePopover();
}
function createPopover() {
quotePopover = document.createElement("div");
quotePopover.popover = "auto";
quotePopover.className = "quote-popover";
const quoteButton = document.createElement("button");
quoteButton.textContent = "Quote fragment"
quoteButton.className = "reduced"
quotePopover.appendChild(quoteButton);
document.body.appendChild(quotePopover);
return quoteButton;
}
function showPopover() {
if (!quotePopover) {
const quoteButton = createPopover();
quoteButton.addEventListener("click", () => {
console.log("Quoting:", document.getSelection().toString());
const postPermalink = quotedPostContainer.dataset.postPermalink;
const authorUsername = quotedPostContainer.dataset.authorUsername;
console.log(postPermalink, authorUsername);
if (ta.value.trim() !== "") {
ta.value += "\n"
}
ta.value += `[url=${postPermalink}]${authorUsername} said:[/url]\n[quote]${document.getSelection().toString()}[/quote]\n`;
ta.scrollIntoView()
ta.focus();
document.getSelection().empty();
removePopover();
})
}
const range = document.getSelection().getRangeAt(0);
const rect = range.getBoundingClientRect();
const scrollY = window.scrollY || window.pageYOffset;
quotePopover.style.setProperty("top", `${rect.top + scrollY - 55}px`)
quotePopover.style.setProperty("left", `${rect.left + rect.width/2}px`)
if (!quotePopover.matches(':popover-open')) {
quotePopover.showPopover();
}
}
}
const deleteDialog = document.getElementById("delete-dialog");
const deleteDialogCloseButton = document.getElementById("post-delete-dialog-close");

View File

@ -310,6 +310,10 @@ button:active, input[type=submit]:active, .linkbutton:active {
button:disabled, input[type=submit]:disabled, .linkbutton:disabled {
background-color: rgb(209.535, 211.565, 211.46);
}
button.reduced, input[type=submit].reduced, .linkbutton.reduced {
margin: 0;
padding: 5px;
}
button.critical, input[type=submit].critical, .linkbutton.critical {
color: white;
background-color: red;
@ -323,6 +327,10 @@ button.critical:active, input[type=submit].critical:active, .linkbutton.critical
button.critical:disabled, input[type=submit].critical:disabled, .linkbutton.critical:disabled {
background-color: rgb(174.675, 156.825, 156.825);
}
button.critical.reduced, input[type=submit].critical.reduced, .linkbutton.critical.reduced {
margin: 0;
padding: 5px;
}
button.warn, input[type=submit].warn, .linkbutton.warn {
background-color: #fbfb8d;
}
@ -335,6 +343,10 @@ button.warn:active, input[type=submit].warn:active, .linkbutton.warn:active {
button.warn:disabled, input[type=submit].warn:disabled, .linkbutton.warn:disabled {
background-color: rgb(217.55, 217.55, 209.85);
}
button.warn.reduced, input[type=submit].warn.reduced, .linkbutton.warn.reduced {
margin: 0;
padding: 5px;
}
input[type=file]::file-selector-button {
background-color: rgb(177, 206, 204.5);
@ -349,6 +361,10 @@ input[type=file]::file-selector-button:active {
input[type=file]::file-selector-button:disabled {
background-color: rgb(209.535, 211.565, 211.46);
}
input[type=file]::file-selector-button.reduced {
margin: 0;
padding: 5px;
}
p {
margin: 15px 0;
@ -371,6 +387,10 @@ p {
.pagebutton:disabled {
background-color: rgb(209.535, 211.565, 211.46);
}
.pagebutton.reduced {
margin: 0;
padding: 5px;
}
.currentpage {
border: none;
@ -632,6 +652,10 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus, select:focus
.tab-button:disabled {
background-color: rgb(209.535, 211.565, 211.46);
}
.tab-button.reduced {
margin: 0;
padding: 5px;
}
.tab-button.active {
background-color: #beb1ce;
padding-top: 8px;
@ -737,3 +761,13 @@ ul, ol {
.babycode-button > * {
font-size: 1rem;
}
.quote-popover {
position: absolute;
transform: translateX(-50%);
margin: 0;
border: none;
border-radius: 4px;
background-color: rgba(0, 0, 0, 0.5019607843);
padding: 5px 10px;
}