- Add centralized API type definitions (types/api.d.ts) - Interfaces for all API responses matching Go handler JSON - Snake_case field names matching actual API responses - Source file references in comments for verification - Add API client module (api.ts) - Procedural get/post/put/delete functions - Automatic auth header injection - Exported to window for cross-module access - Add DOM utilities (dom.ts) - escapeHtml for safe HTML rendering - querySelector wrappers with null checks - Element creation helpers - Add event delegation helpers (events.ts) - Reusable event delegation pattern - Data attribute selectors for dynamic content - Add localStorage wrapper (storage.ts) - Type-safe token management - Theme persistence helpers
138 lines
3.3 KiB
TypeScript
138 lines
3.3 KiB
TypeScript
function escapeHtml(text: string): string {
|
|
const div = document.createElement('div');
|
|
div.textContent = text;
|
|
return div.innerHTML;
|
|
}
|
|
|
|
function querySelector<T extends Element>(selector: string): T | null {
|
|
return document.querySelector<T>(selector);
|
|
}
|
|
|
|
function querySelectorAll<T extends Element>(selector: string): NodeListOf<T> {
|
|
return document.querySelectorAll<T>(selector);
|
|
}
|
|
|
|
function getElementById<T extends HTMLElement>(id: string): T | null {
|
|
return document.getElementById(id) as T | null;
|
|
}
|
|
|
|
function createElement<K extends keyof HTMLElementTagNameMap>(
|
|
tagName: K,
|
|
attributes?: Record<string, string>,
|
|
children?: (string | Node)[]
|
|
): HTMLElementTagNameMap[K] {
|
|
const element = document.createElement(tagName);
|
|
|
|
if (attributes) {
|
|
Object.entries(attributes).forEach(([key, value]) => {
|
|
if (key === 'className') {
|
|
element.className = value;
|
|
} else if (key === 'dataset') {
|
|
Object.entries(JSON.parse(value)).forEach(([dataKey, dataValue]) => {
|
|
element.dataset[dataKey] = String(dataValue);
|
|
});
|
|
} else {
|
|
element.setAttribute(key, value);
|
|
}
|
|
});
|
|
}
|
|
|
|
if (children) {
|
|
children.forEach(child => {
|
|
if (typeof child === 'string') {
|
|
element.appendChild(document.createTextNode(child));
|
|
} else {
|
|
element.appendChild(child);
|
|
}
|
|
});
|
|
}
|
|
|
|
return element;
|
|
}
|
|
|
|
function showElement(element: HTMLElement | null): void {
|
|
if (element) {
|
|
element.classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
function hideElement(element: HTMLElement | null): void {
|
|
if (element) {
|
|
element.classList.add('hidden');
|
|
}
|
|
}
|
|
|
|
function toggleElement(element: HTMLElement | null): void {
|
|
if (element) {
|
|
element.classList.toggle('hidden');
|
|
}
|
|
}
|
|
|
|
function setTextContent(element: HTMLElement | null, text: string): void {
|
|
if (element) {
|
|
element.textContent = text;
|
|
}
|
|
}
|
|
|
|
function setInnerHTML(element: HTMLElement | null, html: string): void {
|
|
if (element) {
|
|
element.innerHTML = html;
|
|
}
|
|
}
|
|
|
|
function addClass(element: HTMLElement | null, className: string): void {
|
|
if (element) {
|
|
element.classList.add(className);
|
|
}
|
|
}
|
|
|
|
function removeClass(element: HTMLElement | null, className: string): void {
|
|
if (element) {
|
|
element.classList.remove(className);
|
|
}
|
|
}
|
|
|
|
function toggleClass(element: HTMLElement | null, className: string): void {
|
|
if (element) {
|
|
element.classList.toggle(className);
|
|
}
|
|
}
|
|
|
|
function hasClass(element: HTMLElement | null, className: string): boolean {
|
|
return element ? element.classList.contains(className) : false;
|
|
}
|
|
|
|
(window as any).dom = {
|
|
escapeHtml,
|
|
querySelector,
|
|
querySelectorAll,
|
|
getElementById,
|
|
createElement,
|
|
showElement,
|
|
hideElement,
|
|
toggleElement,
|
|
setTextContent,
|
|
setInnerHTML,
|
|
addClass,
|
|
removeClass,
|
|
toggleClass,
|
|
hasClass
|
|
};
|
|
|
|
export {
|
|
escapeHtml,
|
|
querySelector,
|
|
querySelectorAll,
|
|
getElementById,
|
|
createElement,
|
|
showElement,
|
|
hideElement,
|
|
toggleElement,
|
|
setTextContent,
|
|
setInnerHTML,
|
|
addClass,
|
|
removeClass,
|
|
toggleClass,
|
|
hasClass
|
|
};
|