mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-12-18 23:17:59 +01:00
110 lines
3.2 KiB
TypeScript
110 lines
3.2 KiB
TypeScript
// DOM Utils
|
|
|
|
type PhilomenaInputElements = HTMLTextAreaElement | HTMLInputElement | HTMLButtonElement;
|
|
|
|
/**
|
|
* Get the first matching element
|
|
*/
|
|
export function $<E extends Element = Element>(
|
|
selector: string,
|
|
context: Pick<Document, 'querySelector'> = document,
|
|
): E | null {
|
|
return context.querySelector<E>(selector);
|
|
}
|
|
|
|
/**
|
|
* Get every matching element as an array
|
|
*/
|
|
export function $$<E extends Element = Element>(
|
|
selector: string,
|
|
context: Pick<Document, 'querySelectorAll'> = document,
|
|
): E[] {
|
|
const elements = context.querySelectorAll<E>(selector);
|
|
|
|
return [...elements];
|
|
}
|
|
|
|
export function showEl<E extends HTMLElement>(...elements: E[] | ConcatArray<E>[]) {
|
|
([] as E[]).concat(...elements).forEach(el => el.classList.remove('hidden'));
|
|
}
|
|
|
|
export function hideEl<E extends HTMLElement>(...elements: E[] | ConcatArray<E>[]) {
|
|
([] as E[]).concat(...elements).forEach(el => el.classList.add('hidden'));
|
|
}
|
|
|
|
export function toggleEl<E extends HTMLElement>(...elements: E[] | ConcatArray<E>[]) {
|
|
([] as E[]).concat(...elements).forEach(el => el.classList.toggle('hidden'));
|
|
}
|
|
|
|
export function clearEl<E extends HTMLElement>(...elements: E[] | ConcatArray<E>[]) {
|
|
([] as E[]).concat(...elements).forEach(el => {
|
|
while (el.firstChild) el.removeChild(el.firstChild);
|
|
});
|
|
}
|
|
|
|
export function disableEl<E extends PhilomenaInputElements>(...elements: E[] | ConcatArray<E>[]) {
|
|
([] as E[]).concat(...elements).forEach(el => {
|
|
el.disabled = true;
|
|
});
|
|
}
|
|
|
|
export function enableEl<E extends PhilomenaInputElements>(...elements: E[] | ConcatArray<E>[]) {
|
|
([] as E[]).concat(...elements).forEach(el => {
|
|
el.disabled = false;
|
|
});
|
|
}
|
|
|
|
export function removeEl<E extends HTMLElement>(...elements: E[] | ConcatArray<E>[]) {
|
|
([] as E[]).concat(...elements).forEach(el => el.parentNode?.removeChild(el));
|
|
}
|
|
|
|
export function makeEl<Tag extends keyof HTMLElementTagNameMap>(
|
|
tag: Tag,
|
|
attr?: Partial<HTMLElementTagNameMap[Tag]>,
|
|
): HTMLElementTagNameMap[Tag] {
|
|
const el = document.createElement(tag);
|
|
if (attr) {
|
|
for (const prop in attr) {
|
|
const newValue = attr[prop];
|
|
if (newValue) {
|
|
el[prop] = newValue;
|
|
}
|
|
}
|
|
}
|
|
return el;
|
|
}
|
|
|
|
export function onLeftClick(
|
|
callback: (e: MouseEvent) => boolean | void,
|
|
context: Pick<GlobalEventHandlers, 'addEventListener' | 'removeEventListener'> = document,
|
|
): VoidFunction {
|
|
const handler: typeof callback = event => {
|
|
if (event.button === 0) callback(event);
|
|
};
|
|
context.addEventListener('click', handler);
|
|
|
|
return () => context.removeEventListener('click', handler);
|
|
}
|
|
|
|
/**
|
|
* Execute a function when the DOM is ready
|
|
*/
|
|
export function whenReady(callback: VoidFunction): void {
|
|
if (document.readyState !== 'loading') {
|
|
callback();
|
|
} else {
|
|
document.addEventListener('DOMContentLoaded', callback);
|
|
}
|
|
}
|
|
|
|
export function escapeHtml(html: string): string {
|
|
return html.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"');
|
|
}
|
|
|
|
export function escapeCss(css: string): string {
|
|
return css.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
}
|
|
|
|
export function findFirstTextNode<N extends Node>(of: Node): N {
|
|
return Array.prototype.filter.call(of.childNodes, el => el.nodeType === Node.TEXT_NODE)[0];
|
|
}
|