UNPKG

@uswds/uswds

Version:

Open source UI components and visual style guide for U.S. government websites

59 lines (49 loc) 1.81 kB
const toggleFieldMask = require("./toggle-field-mask"); const CONTROLS = "aria-controls"; const PRESSED = "aria-pressed"; const SHOW_ATTR = "data-show-text"; const HIDE_ATTR = "data-hide-text"; /** * Replace the word "Show" (or "show") with "Hide" (or "hide") in a string. * @param {string} showText * @return {strong} hideText */ const getHideText = (showText) => showText.replace(/\bShow\b/i, (show) => `${show[0] === "S" ? "H" : "h"}ide`); const resolveIdRefs = (id) => { const ids = id.trim().split(/\s+/); return ids.map((i) => { const el = document.getElementById(i); if (!el) { const err = `no element with id: ${i}`; throw new Error(err); } return el; }); }; /** * Component that decorates an HTML element with the ability to toggle the * masked state of an input field (like a password) when clicked. * The ids of the fields to be masked will be pulled directly from the button's * `aria-controls` attribute. * * @param {HTMLElement} el Parent element containing the fields to be masked * @return {boolean} */ module.exports = (el) => { // this is the *target* state: // * if the element has the attr and it's !== "true", pressed is true // * otherwise, pressed is false const pressed = el.hasAttribute(PRESSED) && el.getAttribute(PRESSED) !== "true"; const fields = resolveIdRefs(el.getAttribute(CONTROLS)); fields.forEach((field) => toggleFieldMask(field, pressed)); if (!el.hasAttribute(SHOW_ATTR)) { el.setAttribute(SHOW_ATTR, el.textContent); } const showText = el.getAttribute(SHOW_ATTR); const hideText = el.getAttribute(HIDE_ATTR) || getHideText(showText); el.textContent = pressed ? showText : hideText; // eslint-disable-line no-param-reassign el.setAttribute(PRESSED, pressed); return pressed; };