diff --git a/data/static/js/babycode-editor.js b/data/static/js/babycode-editor.js
index 09681ac..5258ff7 100644
--- a/data/static/js/babycode-editor.js
+++ b/data/static/js/babycode-editor.js
@@ -3,7 +3,6 @@
ta.addEventListener("keydown", (e) => {
if(e.key === "Enter" && e.ctrlKey) {
- // console.log(e.target.form)
if (inThread()) {
localStorage.removeItem(window.location.pathname);
}
@@ -38,152 +37,4 @@
if (!prevContent) return;
ta.value = prevContent;
})
-
- const buttonBold = document.getElementById("post-editor-bold");
- const buttonItalics = document.getElementById("post-editor-italics");
- const buttonStrike = document.getElementById("post-editor-strike");
- const buttonUnderline = document.getElementById("post-editor-underline");
- const buttonUrl = document.getElementById("post-editor-url");
- const buttonCode = document.getElementById("post-editor-code");
- const buttonImg = document.getElementById("post-editor-img");
- const buttonOl = document.getElementById("post-editor-ol");
- const buttonUl = document.getElementById("post-editor-ul");
- const buttonSpoiler = document.getElementById("post-editor-spoiler");
-
- function insertTag(tagStart, newline = false, prefill = "") {
- const hasAttr = tagStart[tagStart.length - 1] === "=";
- let tagEnd = tagStart;
- let tagInsertStart = `[${tagStart}]${newline ? "\n" : ""}`;
- if (hasAttr) {
- tagEnd = tagEnd.slice(0, -1);
- }
- const tagInsertEnd = `${newline ? "\n" : ""}[/${tagEnd}]`;
- const hasSelection = ta.selectionStart !== ta.selectionEnd;
- const text = ta.value;
- if (hasSelection) {
- const realStart = Math.min(ta.selectionStart, ta.selectionEnd);
- const realEnd = Math.max(ta.selectionStart, ta.selectionEnd);
- const selectionLength = realEnd - realStart;
-
- const strStart = text.slice(0, realStart);
- const strEnd = text.substring(realEnd);
- const frag = `${tagInsertStart}${text.slice(realStart, realEnd)}${tagInsertEnd}`;
- const reconst = `${strStart}${frag}${strEnd}`;
- ta.value = reconst;
- if (!hasAttr){
- ta.setSelectionRange(realStart + tagInsertStart.length, realStart + tagInsertStart.length + selectionLength);
- } else {
- ta.setSelectionRange(realStart + tagInsertEnd.length - 1, realStart + tagInsertEnd.length - 1); // cursor on attr
- }
- ta.focus()
- } else {
- if (hasAttr) {
- tagInsertStart += prefill;
- }
- const cursor = ta.selectionStart;
- const strStart = text.slice(0, cursor);
- const strEnd = text.substr(cursor);
-
- let newCursor = strStart.length + tagInsertStart.length;
- if (hasAttr) {
- newCursor = cursor + tagInsertStart.length - prefill.length - 1;
- }
- const reconst = `${strStart}${tagInsertStart}${tagInsertEnd}${strEnd}`;
- ta.value = reconst;
- ta.setSelectionRange(newCursor, newCursor);
- ta.focus()
- }
- }
-
- buttonBold.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("b")
- })
- buttonItalics.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("i")
- })
- buttonStrike.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("s")
- })
- buttonUnderline.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("u")
- })
- buttonUrl.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("url=", false, "link label");
- })
- buttonCode.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("code", true)
- })
- buttonImg.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("img=", false, "alt text");
- })
- buttonOl.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("ol", true);
- })
- buttonUl.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("ul", true);
- })
- buttonSpoiler.addEventListener("click", (e) => {
- e.preventDefault();
- insertTag("spoiler=", true, "hidden content");
- })
-
- const previewEndpoint = "/api/babycode-preview";
- let previousMarkup = "";
- const previewTab = document.getElementById("tab-preview");
- previewTab.addEventListener("tab-activated", async () => {
- const previewContainer = document.getElementById("babycode-preview-container");
- const previewErrorsContainer = document.getElementById("babycode-preview-errors-container");
- // previewErrorsContainer.textContent = "";
- const markup = ta.value.trim();
- if (markup === "" || markup === previousMarkup) {
- return;
- }
- const bannedTags = JSON.parse(document.getElementById('babycode-banned-tags').value);
- previousMarkup = markup;
- const req = await fetch(previewEndpoint, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- markup: markup,
- banned_tags: bannedTags,
- })
- })
- if (!req.ok) {
- switch (req.status) {
- case 429:
- previewErrorsContainer.textContent = "(Old preview, try again in a few seconds.)"
- previousMarkup = "";
- break;
- case 400:
- previewErrorsContainer.textContent = "(Request got malformed.)"
- break;
- case 401:
- previewErrorsContainer.textContent = "(You are not logged in.)"
- break;
- default:
- previewErrorsContainer.textContent = "(Error. Check console.)"
- console.error(req.error);
- break;
- }
- return;
- }
-
- const json_resp = await req.json();
- previewContainer.innerHTML = json_resp.html;
- previewErrorsContainer.textContent = "";
-
- const accordionRefreshEvt = new CustomEvent("refresh_accordions");
- document.body.dispatchEvent(accordionRefreshEvt);
- });
}
diff --git a/data/static/js/bitties/pyrom-bitty.js b/data/static/js/bitties/pyrom-bitty.js
index 8f560bc..bd9cd05 100644
--- a/data/static/js/bitties/pyrom-bitty.js
+++ b/data/static/js/bitties/pyrom-bitty.js
@@ -1,4 +1,7 @@
-const bookmarkMenuHrefTemplate = '/hyperapi/bookmarks-dropdown'
+const bookmarkMenuHrefTemplate = '/hyperapi/bookmarks-dropdown';
+const previewEndpoint = '/api/babycode-preview';
+
+const delay = ms => {return new Promise(resolve => setTimeout(resolve, ms))}
export default class {
async showBookmarkMenu(ev, el) {
@@ -85,4 +88,160 @@ export default class {
window.location.reload();
}
}
+
+ async copyCode(ev, el) {
+ if (!el.isSender) {
+ return;
+ }
+ await navigator.clipboard.writeText(el.value);
+ el.textContent = 'Copied!'
+ await delay(1000);
+ el.textContent = 'Copy';
+ }
+
+ toggleAccordion(ev, el) {
+ const accordion = el;
+ const header = accordion.querySelector('.accordion-header');
+ if (!header.contains(ev.sender)){
+ return;
+ }
+ const btn = ev.sender;
+ const content = el.querySelector('.accordion-content');
+ // these are all meant to be in sync
+ accordion.classList.toggle('hidden');
+ content.classList.toggle('hidden');
+ btn.textContent = accordion.classList.contains('hidden') ? '+' : '-';
+ }
+
+ toggleTab(ev, el) {
+ const tabButtonsContainer = el.querySelector('.tab-buttons');
+ if (!el.contains(ev.sender)) {
+ return;
+ }
+
+ if (ev.sender.classList.contains('active')) {
+ return;
+ }
+
+ const targetId = ev.sender.getString('targetId');
+ const contents = el.querySelectorAll('.tab-content');
+ for (let content of contents) {
+ if (content.id === targetId) {
+ content.classList.add('active');
+ } else {
+ content.classList.remove('active');
+ }
+ }
+ for (let button of tabButtonsContainer.children) {
+ if (button.dataset.targetId === targetId) {
+ button.classList.add('active');
+ } else {
+ button.classList.remove('active');
+ }
+ }
+ }
+
+ #previousMarkup = '';
+ async babycodePreview(ev, el) {
+ if (ev.sender.classList.contains('active')) {
+ return;
+ }
+
+ const previewErrorsContainer = el.querySelector('#babycode-preview-errors-container');
+ const previewContainer = el.querySelector('#babycode-preview-container');
+ const ta = document.getElementById('babycode-content');
+ const markup = ta.value.trim();
+ if (markup === '' || markup === this.#previousMarkup) {
+ return;
+ }
+ const bannedTags = JSON.parse(document.getElementById('babycode-banned-tags').value);
+ this.#previousMarkup = markup;
+
+ const res = await this.api.getJSON(previewEndpoint, [], {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ markup: markup,
+ banned_tags: bannedTags,
+ }),
+ });
+ if (res.error) {
+ switch (res.error.status) {
+ case 429:
+ previewErrorsContainer.textContent = '(Old preview, try again in a few seconds.)'
+ this.#previousMarkup = '';
+ break;
+ case 400:
+ previewErrorsContainer.textContent = '(Request got malformed.)'
+ break;
+ case 401:
+ previewErrorsContainer.textContent = '(You are not logged in.)'
+ break;
+ default:
+ previewErrorsContainer.textContent = '(Error. Check console.)'
+ break;
+ }
+ } else {
+ previewErrorsContainer.textContent = '';
+ previewContainer.innerHTML = res.value.html;
+ }
+ }
+
+ insertBabycodeTag(ev, el) {
+ const tagStart = ev.sender.getString('tag');
+ const breakLine = 'breakLine' in ev.sender.dataset;
+ const prefill = 'prefill' in ev.sender.dataset ? ev.sender.dataset.prefill : '';
+
+ const hasAttr = tagStart[tagStart.length - 1] === '=';
+ let tagEnd = tagStart;
+ let tagInsertStart = `[${tagStart}]${breakLine ? '\n' : ''}`;
+ if (hasAttr) {
+ tagEnd = tagEnd.slice(0, -1);
+ }
+ const tagInsertEnd = `${breakLine ? '\n' : ''}[/${tagEnd}]`;
+ const hasSelection = el.selectionStart !== el.selectionEnd;
+ const text = el.value;
+
+ if (hasSelection) {
+ const realStart = Math.min(el.selectionStart, el.selectionEnd);
+ const realEnd = Math.max(el.selectionStart, el.selectionEnd);
+ const selectionLength = realEnd - realStart;
+
+ const strStart = text.slice(0, realStart);
+ const strEnd = text.substring(realEnd);
+ const frag = `${tagInsertStart}${text.slice(realStart, realEnd)}${tagInsertEnd}`;
+ const reconst = `${strStart}${frag}${strEnd}`;
+ el.value = reconst;
+ if (!hasAttr) {
+ el.setSelectionRange(realStart + tagInsertStart.length, realStart + tagInsertEnd.length + selectionLength - 1);
+ } else {
+ const attrCursor = realStart + tagInsertEnd.length - (1 + (breakLine ? 1 : 0))
+ el.setSelectionRange(attrCursor, attrCursor); // cursor on attr
+ }
+ } else {
+ if (hasAttr) {
+ tagInsertStart += prefill;
+ }
+ const cursor = el.selectionStart;
+ const strStart = text.slice(0, cursor);
+ const strEnd = text.substr(cursor);
+
+ let newCursor = strStart.length + tagInsertStart.length;
+ if (hasAttr) {
+ newCursor = cursor + tagInsertStart.length - prefill.length - (1 + (breakLine ? 1 : 0)) //cursor on attr
+ }
+ const reconst = `${strStart}${tagInsertStart}${tagInsertEnd}${strEnd}`;
+ el.value = reconst;
+ el.setSelectionRange(newCursor, newCursor);
+ }
+ el.focus();
+ }
+
+ addQuote(ev, el) {
+ el.value += ev.sender.value;
+ el.scrollIntoView();
+ el.focus();
+ }
}
diff --git a/data/static/js/thread.js b/data/static/js/thread.js
index 3e226d3..4570235 100644
--- a/data/static/js/thread.js
+++ b/data/static/js/thread.js
@@ -1,13 +1,5 @@
{
const ta = document.getElementById("babycode-content");
-
- for (let button of document.querySelectorAll(".reply-button")) {
- button.addEventListener("click", (e) => {
- ta.value += button.value;
- ta.scrollIntoView()
- ta.focus();
- })
- }
function supportsPopover() {
return Object.hasOwn(HTMLElement.prototype, "popover");
diff --git a/data/static/js/ui.js b/data/static/js/ui.js
index c2128aa..bb5537b 100644
--- a/data/static/js/ui.js
+++ b/data/static/js/ui.js
@@ -1,26 +1,3 @@
-function activateSelfDeactivateSibs(button) {
- if (button.classList.contains("active")) return;
-
- Array.from(button.parentNode.children).forEach(s => {
- if (s === button){
- button.classList.add('active');
- } else {
- s.classList.remove('active');
- }
- const targetId = s.dataset.targetId;
- const target = document.getElementById(targetId);
-
- if (!target) return;
-
- if (s.classList.contains('active')) {
- target.classList.add('active');
- target.dispatchEvent(new CustomEvent("tab-activated", {bubbles: false}))
- } else {
- target.classList.remove('active');
- }
- });
-}
-
function openLightbox(post, idx) {
lightboxCurrentPost = post;
lightboxCurrentIdx = idx;
@@ -102,43 +79,6 @@ let lightboxCurrentPost = null;
let lightboxCurrentIdx = -1;
document.addEventListener("DOMContentLoaded", () => {
- // tabs
- document.querySelectorAll(".tab-button").forEach(button => {
- button.addEventListener("click", () => {
- activateSelfDeactivateSibs(button);
- });
- });
-
- // accordions
- const handledAccordions = new Set();
- function attachAccordionHandlers(accordion){
- if(handledAccordions.has(accordion)) {
- return;
- }
-
- handledAccordions.add(accordion)
- const header = accordion.querySelector(".accordion-header");
- const toggleButton = header.querySelector(".accordion-toggle");
- const content = accordion.querySelector(".accordion-content");
-
- const toggle = (e) => {
- e.stopPropagation();
- accordion.classList.toggle("hidden");
- content.classList.toggle("hidden");
- toggleButton.textContent = content.classList.contains("hidden") ? "+" : "-"
- }
-
- toggleButton.addEventListener("click", toggle);
- }
-
- function refreshAccordions(){
- const accordions = document.querySelectorAll(".accordion");
- accordions.forEach(attachAccordionHandlers);
- }
- refreshAccordions()
-
- document.body.addEventListener('refresh_accordions', refreshAccordions)
-
//lightboxes
lightboxObj = constructLightbox();
document.body.appendChild(lightboxObj.dialog);
@@ -192,13 +132,4 @@ document.addEventListener("DOMContentLoaded", () => {
image.addEventListener("load", () => setImageMaxSize(image));
}
})
-
- // copy code blocks
- for (let button of document.querySelectorAll(".copy-code")) {
- button.addEventListener("click", async () => {
- await navigator.clipboard.writeText(button.value)
- button.textContent = "Copied!"
- setTimeout(() => {button.textContent = "Copy"}, 1000.0)
- })
- };
});