iemjs
Version:
Iowa Environmental Mesonet JavaScript utilities for weather data applications
208 lines (187 loc) • 6.13 kB
JavaScript
// DOM utility functions to reduce boilerplate
/**
* Escape HTML special characters to prevent XSS attacks
* @param {string} val - String to escape
* @returns {string} HTML-escaped string
*/
export function escapeHTML(val) {
return val
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
/**
* Safely get an element by ID with type checking
* @param {string} id - Element ID
* @param {Function} [ElementType] - Expected element constructor (e.g., HTMLInputElement)
* @returns {HTMLElement | null} The element or null if not found/wrong type
*/
export function getElement(id, ElementType) {
const element = document.getElementById(id);
if (!element) {
return null;
}
// If no ElementType provided, return as HTMLElement
if (!ElementType) {
return element;
}
if (!(element instanceof ElementType)) {
return null;
}
return element;
}
/**
* Get an element and throw if not found (for required elements)
* @param {string} id - Element ID
* @param {Function} [ElementType] - Expected element constructor
* @returns {HTMLElement} The element (guaranteed to exist)
* @throws {Error} If element not found or wrong type
*/
export function requireElement(id, ElementType) {
const element = getElement(id, ElementType);
if (!element) {
throw new Error(`Required element '${id}' not found or wrong type`);
}
return element;
}
// Specialized helper functions for common element types
/**
* Get an input element by ID
* @param {string} id - Element ID
* @returns {HTMLInputElement | null}
*/
export function getInputElement(id) {
return /** @type {HTMLInputElement | null} */ (getElement(id, HTMLInputElement));
}
/**
* Get a required input element by ID
* @param {string} id - Element ID
* @returns {HTMLInputElement}
* @throws {Error} If element not found or wrong type
*/
export function requireInputElement(id) {
return /** @type {HTMLInputElement} */ (requireElement(id, HTMLInputElement));
}
/**
* Get a select element by ID
* @param {string} id - Element ID
* @returns {HTMLSelectElement | null}
*/
export function getSelectElement(id) {
return /** @type {HTMLSelectElement | null} */ (getElement(id, HTMLSelectElement));
}
/**
* Get a required select element by ID
* @param {string} id - Element ID
* @returns {HTMLSelectElement}
* @throws {Error} If element not found or wrong type
*/
export function requireSelectElement(id) {
return /** @type {HTMLSelectElement} */ (requireElement(id, HTMLSelectElement));
}
/**
* Get a button element by ID
* @param {string} id - Element ID
* @returns {HTMLButtonElement | null}
*/
export function getButtonElement(id) {
return /** @type {HTMLButtonElement | null} */ (getElement(id, HTMLButtonElement));
}
/**
* Get a required button element by ID
* @param {string} id - Element ID
* @returns {HTMLButtonElement}
* @throws {Error} If element not found or wrong type
*/
export function requireButtonElement(id) {
return /** @type {HTMLButtonElement} */ (requireElement(id, HTMLButtonElement));
}
/**
* Get multiple elements by ID with type checking
* @param {string[]} ids - Array of element IDs
* @param {Function} [ElementType] - Expected element constructor
* @returns {(HTMLElement | null)[]} Array of elements (null for missing/wrong type)
*/
export function getElements(ids, ElementType) {
return ids.map(id => getElement(id, ElementType));
}
/**
* Get multiple required elements by ID
* @param {string[]} ids - Array of element IDs
* @param {Function} [ElementType] - Expected element constructor
* @returns {HTMLElement[]} Array of elements (guaranteed to exist)
* @throws {Error} If any element not found or wrong type
*/
export function requireElements(ids, ElementType) {
return ids.map(id => requireElement(id, ElementType));
}
/**
* Add event listeners to multiple elements by ID
* @param {string[]} ids - Array of element IDs
* @param {string} event - Event type
* @param {EventListener} handler - Event handler
* @param {Function} [ElementType] - Expected element constructor
*/
export function addEventListeners(ids, event, handler, ElementType) {
ids.forEach(id => {
const element = getElement(id, ElementType);
if (element) {
element.addEventListener(event, handler);
}
});
}
/**
* Get value from a form element safely
* @param {string} id - Element ID
* @param {string} [defaultValue=''] - Default value if element not found
* @returns {string} Element value or default
*/
export function getElementValue(id, defaultValue = '') {
const element = getInputElement(id);
return element ? element.value : defaultValue;
}
/**
* Set value on a form element safely
* @param {string} id - Element ID
* @param {string} value - Value to set
* @returns {boolean} True if successful
*/
export function setElementValue(id, value) {
const element = getInputElement(id);
if (element) {
element.value = value;
return true;
}
return false;
}
/**
* Interface for elements that have been enhanced with TomSelect
* @typedef {HTMLElement & { tomselect: import('tom-select').default }} TomSelectElement
*/
/**
* Get an element that has been enhanced with TomSelect
* @param {string} id - Element ID
* @returns {TomSelectElement | null}
*/
export function getTomSelectElement(id) {
const element = getElement(id);
if (element && 'tomselect' in element) {
return /** @type {TomSelectElement} */ (element);
}
return null;
}
/**
* Get a required element that has been enhanced with TomSelect
* @param {string} id - Element ID
* @returns {TomSelectElement}
* @throws {Error} If element not found or doesn't have tomselect property
*/
export function requireTomSelectElement(id) {
const element = getTomSelectElement(id);
if (!element) {
throw new Error(`Required TomSelect element '${id}' not found or not initialized`);
}
return element;
}