// DOM Utils
type PhilomenaInputElements = HTMLTextAreaElement | HTMLInputElement | HTMLButtonElement;
/**
* Get the first matching element
*/
export function $(selector: string, context: Pick = document): E | null {
return context.querySelector(selector);
}
/**
* Get every matching element as an array
*/
export function $$(selector: string, context: Pick = document): E[] {
const elements = context.querySelectorAll(selector);
return [...elements];
}
export function showEl(...elements: E[] | ConcatArray[]) {
([] as E[]).concat(...elements).forEach(el => el.classList.remove('hidden'));
}
export function hideEl(...elements: E[] | ConcatArray[]) {
([] as E[]).concat(...elements).forEach(el => el.classList.add('hidden'));
}
export function toggleEl(...elements: E[] | ConcatArray[]) {
([] as E[]).concat(...elements).forEach(el => el.classList.toggle('hidden'));
}
export function clearEl(...elements: E[] | ConcatArray[]) {
([] as E[]).concat(...elements).forEach(el => {
while (el.firstChild) el.removeChild(el.firstChild);
});
}
export function disableEl(...elements: E[] | ConcatArray[]) {
([] as E[]).concat(...elements).forEach(el => {
el.disabled = true;
});
}
export function enableEl(...elements: E[] | ConcatArray[]) {
([] as E[]).concat(...elements).forEach(el => {
el.disabled = false;
});
}
export function removeEl(...elements: E[] | ConcatArray[]) {
([] as E[]).concat(...elements).forEach(el => el.parentNode?.removeChild(el));
}
export function makeEl(tag: Tag, attr?: Partial): 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;
}
}
}
return el;
}
export function onLeftClick(callback: (e: MouseEvent) => boolean | void, context: Pick = 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(/(of: Node): N {
return Array.prototype.filter.call(of.childNodes, el => el.nodeType === Node.TEXT_NODE)[0];
}