Files
pyrom/data/static/js/bits/bookmark-menu.js
2026-06-02 17:58:06 +03:00

128 lines
3.3 KiB
JavaScript

async function getHTML(endpoint, options = {}) {
let query = {};
if (options._query !== undefined) {
query = options._query;
delete options._query;
}
const params = new URLSearchParams(query);
const res = await fetch(`${endpoint}?${params}`, options);
// if (!res.ok) {
// console.error(res);
// }
return { body: await res.text(), status: res.status };
}
export const b = {
bookmarksCollectionEndpoint: '/hyperapi/bookmarks/dropdown/',
bookmarkMenuState: {},
}
export async function showBookmarkMenu(ev, sender, el) {
if (b.bookmarkMenuState.state === undefined) {
el.addEventListener('toggle', e => {
if (e.newState === 'closed') {
b.bookmarkMenuState.state = 'closed';
}
});
}
// dismiss if open and last invoker is the same button that opened it
if (b.bookmarkMenuState.state === 'open' && b.bookmarkMenuState.invoker === sender) {
el.hidePopover();
return;
}
b.bookmarkMenuState.invoker = sender;
b.bookmarkMenuState.state = 'open';
b.send({ 'plain': 'Loading…' }, 'fillBookmarkMenu');
el.showPopover();
const bRect = sender.getBoundingClientRect();
const menuRect = el.getBoundingClientRect();
const preferredLeft = bRect.right - menuRect.width;
const enoughSpace = preferredLeft >= 0;
const scrollY = window.scrollY;
if (enoughSpace) {
el.style.left = `${preferredLeft}px`;
} else {
el.style.left = `${bRect.left}px`;
}
el.style.top = `${bRect.bottom + scrollY}px`;
b.bookmarkMenuState.kind = sender.dataset.conceptKind;
b.bookmarkMenuState.id = sender.dataset.conceptId;
const bookmarkCollections = await getHTML(b.bookmarksCollectionEndpoint, {
_query: {
concept_kind: b.bookmarkMenuState.kind,
concept_id: b.bookmarkMenuState.id,
}
});
b.send({ 'html': bookmarkCollections.body }, 'fillBookmarkMenu');
}
export function fillBookmarkMenu(payload, __, el) {
if (payload.plain) {
el.innerText = payload.plain;
return;
}
el.innerHTML = payload.html;
}
export async function bookmarkMenuSubmit(ev, _, el) {
ev.preventDefault();
const url = el.action;
const body = new URLSearchParams(new FormData(el));
const options = { body: body, method: 'POST' };
const status = (await getHTML(url, options)).status;
if (status !== 204) {
b.send({ status: status }, 'bookmarkMenuShowError');
return;
}
const newCollections = await getHTML(b.bookmarksCollectionEndpoint, {
_query: {
concept_kind: b.bookmarkMenuState.kind,
concept_id: b.bookmarkMenuState.id,
saved: true,
}
});
b.send({ 'html': newCollections.body }, 'fillBookmarkMenu');
}
export function bookmarkMenuResetSavedButton(_, __, el) {
el.value = 'Save';
}
export function bookmarkMenuShowError(payload, _, el) {
if (el === undefined) {
return;
}
if (payload.status === 404) {
el.innerText = 'This thread or post no longer exists. Please refresh the page.';
} else {
el.innerText = 'Something went wrong. Try again later.';
}
if (el.classList.contains('hidden')) {
el.classList.remove('hidden');
setTimeout(() => { b.trigger('bookmarkMenuHideError') }, 4000);
}
}
export function bookmarkMenuHideError(_, __, el) {
if (el === undefined) {
return;
}
if (!el.classList.contains('hidden')) {
el.classList.add('hidden');
}
}