feat: initial commit

This commit is contained in:
Cory Dransfeldt 2025-03-27 16:46:02 -07:00
commit e214116e40
No known key found for this signature in database
253 changed files with 17406 additions and 0 deletions

View file

@ -0,0 +1,41 @@
class NowPlaying extends HTMLElement {
static tagName = "now-playing";
static register(tagName = this.tagName, registry = globalThis.customElements) {
registry.define(tagName, this);
}
async connectedCallback() {
this.contentElement = this.querySelector(".content");
if (!this.contentElement) return;
const cache = localStorage.getItem("now-playing-cache");
if (cache) this.updateHTML(JSON.parse(cache));
await this.fetchAndUpdate();
}
async fetchAndUpdate() {
try {
const data = await this.fetchData();
const newHTML = data?.content;
if (newHTML && newHTML !== this.contentElement.innerHTML) {
this.updateHTML(newHTML);
localStorage.setItem("now-playing-cache", JSON.stringify(newHTML));
}
} catch {}
}
updateHTML(value) {
this.contentElement.innerHTML = value;
}
async fetchData() {
return fetch(`/api/playing.php?nocache=${Date.now()}`)
.then(response => response.json())
.catch(() => ({}));
}
}
NowPlaying.register();

View file

@ -0,0 +1,48 @@
class SelectPagination extends HTMLElement {
static register(tagName = 'select-pagination') {
if ("customElements" in window) customElements.define(tagName, this)
}
static get observedAttributes() {
return ['data-base-index']
}
get baseIndex() {
return this.getAttribute('data-base-index') || 0
}
connectedCallback() {
if (this.shadowRoot) return
this.attachShadow({ mode: 'open' }).appendChild(document.createElement('slot'))
const uriSegments = window.location.pathname.split('/').filter(Boolean)
let pageNumber = this.extractPageNumber(uriSegments) || 0
this.control = this.querySelector('select')
this.control.value = pageNumber
this.control.addEventListener('change', (event) => {
pageNumber = parseInt(event.target.value)
const updatedUrlSegments = this.updateUrlSegments(uriSegments, pageNumber)
window.location.href = `${window.location.origin}/${updatedUrlSegments.join('/')}`
})
}
extractPageNumber(segments) {
const lastSegment = segments[segments.length - 1]
return !isNaN(lastSegment) ? parseInt(lastSegment) : null
}
updateUrlSegments(segments, pageNumber) {
if (!isNaN(segments[segments.length - 1])) {
segments[segments.length - 1] = pageNumber.toString()
} else {
segments.push(pageNumber.toString())
}
if (pageNumber === parseInt(this.baseIndex)) segments.pop()
return segments
}
}
SelectPagination.register()

View file

@ -0,0 +1,72 @@
window.addEventListener("load", () => {
// dialog controls
(() => {
if (document.querySelectorAll(".modal-open").length) {
document.querySelectorAll(".modal-open").forEach((button) => {
const modalId = button.getAttribute("data-modal-trigger");
const dialog = document.getElementById(`dialog-${modalId}`);
if (!dialog) return;
const closeButton = dialog.querySelector(".modal-close");
button.addEventListener("click", () => {
dialog.showModal();
dialog.classList.remove("closing");
});
if (closeButton)
closeButton.addEventListener("click", () => {
dialog.classList.add("closing");
setTimeout(() => dialog.close(), 200);
});
dialog.addEventListener("click", (event) => {
const rect = dialog.getBoundingClientRect();
if (
event.clientX < rect.left ||
event.clientX > rect.right ||
event.clientY < rect.top ||
event.clientY > rect.bottom
) {
dialog.classList.add("closing");
setTimeout(() => dialog.close(), 200);
}
});
dialog.addEventListener("cancel", (event) => {
event.preventDefault();
dialog.classList.add("closing");
setTimeout(() => dialog.close(), 200);
});
});
}
})();
// text toggle for media pages
(() => {
const button = document.querySelector("[data-toggle-button]");
const content = document.querySelector("[data-toggle-content]");
const text = document.querySelectorAll("[data-toggle-content] p");
const minHeight = 500; // this needs to match the height set on [data-toggle-content].text-toggle-hidden in text-toggle.css
const interiorHeight = Array.from(text).reduce(
(acc, node) => acc + node.scrollHeight,
0,
);
if (!button || !content || !text) return;
if (interiorHeight < minHeight) {
content.classList.remove("text-toggle-hidden");
button.style.display = "none";
return;
}
button.addEventListener("click", () => {
const isHidden = content.classList.toggle("text-toggle-hidden");
button.textContent = isHidden ? "Show more" : "Show less";
});
})();
});