mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-23 20:18:00 +01:00
103 lines
3.3 KiB
TypeScript
103 lines
3.3 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 (typeof newValue !== 'undefined') {
|
|
el[prop] = newValue as Exclude<typeof newValue, undefined>;
|
|
}
|
|
}
|
|
}
|
|
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];
|
|
}
|