easy-aria
Version:
The easiest (and safest) way to manipulate ARIA attributes in HTML.
967 lines (966 loc) • 27.5 kB
JavaScript
var x = Object.defineProperty;
var E = (i, e, s) => e in i ? x(i, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : i[e] = s;
var b = (i, e, s) => (E(i, typeof e != "symbol" ? e + "" : e, s), s), g = (i, e, s) => {
if (!e.has(i))
throw TypeError("Cannot " + s);
};
var T = (i, e, s) => (g(i, e, "read from private field"), s ? s.call(i) : e.get(i)), d = (i, e, s) => {
if (e.has(i))
throw TypeError("Cannot add the same private member more than once");
e instanceof WeakSet ? e.add(i) : e.set(i, s);
}, q = (i, e, s, c) => (g(i, e, "write to private field"), c ? c.call(i, s) : e.set(i, s), s);
var m = (i, e, s, c) => ({
set _(h) {
q(i, e, h, s);
},
get _() {
return T(i, e, c);
}
}), r = (i, e, s) => (g(i, e, "access private method"), s);
var f, w, k, l, u, a, t;
const n = class n {
constructor(e) {
/**
* Sets the given `aria-*` attribute on the wrapped Element
* from the un-prefixed version.
*/
d(this, a);
/** HTML Element wrapped by `EasyAria` object. */
b(this, "el");
this.el = e;
}
/**
* @returns The *explicit* role defined on the wrapped Element.
*/
getRole() {
return this.el.getAttribute("role");
}
/**
* Sets the `role` attribute on the wrapped Element to the given value.
*
* @param role The value to be assigned to the `role` attribute.
*/
setRole(e) {
if (!arguments.length)
throw new TypeError(
"EasyAria.setRole() requires 1 argument, but received 0."
);
if (typeof e != "string")
throw new TypeError('Please specify an ARIA role (e.g., "group").');
return this.el.setAttribute("role", e), this;
}
/**
* Takes a callback function which runs immediately, and is passed the
* wrapped Element. The callback's return value is discarded, and the `EasyAria`
* instance is returned.
*
* @param callback The callback function which is passed the wrapped Element.
*/
call(e) {
if (!arguments.length)
throw new TypeError(
"EasyAria.call() requires 1 argument, but received 0."
);
if (typeof e != "function")
throw new TypeError("EasyAria.call() requires a function.");
return e.call(this, this.el), this;
}
// Implementation for `set()`
set(e, s) {
var c, h;
if (!arguments.length)
throw new TypeError(
"EasyAria.set() requires at least 1 argument, but received 0."
);
if (typeof e != "string")
throw new TypeError(
'Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").'
);
switch (e = e.toLowerCase(), e) {
case "keyshortcuts":
case "label":
case "placeholder":
case "roledescription":
case "valuetext":
if (typeof s != "string")
throw new TypeError(`"aria-${e}" requires a string.`);
r(this, a, t).call(this, e, String(s));
break;
case "activedescendant":
case "details":
case "errormessage":
if (s instanceof Element)
r(this, a, t).call(this, e, r(c = n, l, u).call(c, s));
else if (typeof s == "string")
r(this, a, t).call(this, e, s);
else
throw new TypeError(
`"aria-${e}" requires a string, or pass an Element to use its ID.`
);
break;
case "controls":
case "describedby":
case "flowto":
case "labelledby":
case "owns":
if (s instanceof Element)
r(this, a, t).call(this, e, r(h = n, l, u).call(h, s));
else if (Array.isArray(s) || s instanceof NodeList)
r(this, a, t).call(this, e, Array.prototype.map.call(s, (o) => {
var y;
return r(y = n, l, u).call(y, o);
}).filter(Boolean).join(" "));
else if (typeof s == "string")
r(this, a, t).call(this, e, s);
else
throw new TypeError(
`"aria-${e}" requires a string, or pass an Element or Array/NodeList of Elements to use their IDs.`
);
break;
case "atomic":
case "busy":
case "disabled":
case "modal":
case "multiline":
case "multiselectable":
case "readonly":
case "required":
if (typeof s > "u")
r(this, a, t).call(this, e, String(!0));
else
switch (s) {
case !0:
case !1:
r(this, a, t).call(this, e, String(s));
break;
default:
throw new TypeError(
`"aria-${e}" requires a boolean value.`
);
}
break;
case "expanded":
case "grabbed":
case "hidden":
case "selected":
if (typeof s > "u")
r(this, a, t).call(this, e, String(!0));
else
switch (s) {
case !0:
case !1:
r(this, a, t).call(this, e, String(s));
break;
case "undefined":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" requires a boolean value, or the string "undefined".`
);
}
break;
case "checked":
case "pressed":
if (typeof s > "u")
r(this, a, t).call(this, e, String(!0));
else
switch (s) {
case !0:
case !1:
r(this, a, t).call(this, e, String(s));
break;
case "mixed":
case "undefined":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" requires a boolean value, or any of the following strings: "mixed", "undefined".`
);
}
break;
case "current":
if (typeof s > "u")
r(this, a, t).call(this, e, String(!0));
else
switch (s) {
case !0:
case !1:
r(this, a, t).call(this, e, String(s));
break;
case "page":
case "step":
case "location":
case "date":
case "time":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" requires a boolean value, or any of the following strings: "page", "step", "location", "date", "time".`
);
}
break;
case "haspopup":
if (typeof s > "u")
r(this, a, t).call(this, e, String(!0));
else
switch (s) {
case !0:
case !1:
r(this, a, t).call(this, e, String(s));
break;
case "menu":
case "listbox":
case "tree":
case "grid":
case "dialog":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" requires a boolean value, or any of the following strings: "menu", "listbox", "tree", "grid", "dialog".`
);
}
break;
case "invalid":
if (typeof s > "u")
r(this, a, t).call(this, e, String(!0));
else
switch (s) {
case !0:
case !1:
r(this, a, t).call(this, e, String(s));
break;
case "grammar":
case "spelling":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" requires a boolean value, or any of the following strings: "grammar", "spelling".`
);
}
break;
case "autocomplete":
switch (s) {
case "both":
case "inline":
case "list":
case "none":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}`
);
}
break;
case "dropeffect":
switch (s) {
case "copy":
case "execute":
case "link":
case "move":
case "none":
case "popup":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}`
);
}
break;
case "live":
switch (s) {
case "assertive":
case "off":
case "polite":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}`
);
}
break;
case "orientation":
switch (s) {
case "horizontal":
case "undefined":
case "vertical":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}`
);
}
break;
case "relevant":
switch (s) {
case "additions":
case "additions text":
case "all":
case "removals":
case "text":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}`
);
}
break;
case "sort":
switch (s) {
case "ascending":
case "descending":
case "none":
case "other":
r(this, a, t).call(this, e, s);
break;
default:
throw new TypeError(
`"aria-${e}" only accepts the values specified at: https://www.w3.org/TR/wai-aria-1.2/#aria-${e}`
);
}
break;
case "colcount":
case "colindex":
case "colspan":
case "level":
case "posinset":
case "rowcount":
case "rowindex":
case "rowspan":
case "setsize":
case "valuemax":
case "valuemin":
case "valuenow": {
if (typeof s == "bigint" || typeof s == "number" || typeof s == "string") {
const o = Number(s);
if (Number.isNaN(o))
throw new TypeError(
`"aria-${e}" requires a number or numerical string.`
);
r(this, a, t).call(this, e, String(o));
} else
throw new TypeError(
`"aria-${e}" requires a number or numerical string.`
);
break;
}
default: {
const o = e;
throw new TypeError(
`Invalid attribute: "aria-${o}". Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").`
);
}
}
return this;
}
/**
* Removes the given aria attribute from the wrapped Element.
*
* @param attribute The aria attribute to remove, without the `aria-` prefix.
*/
unset(e) {
if (!arguments.length)
throw new TypeError(
"EasyAria.unset() requires 1 argument, but received 0."
);
if (typeof e != "string")
throw new TypeError(
'Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").'
);
switch (e = e.toLowerCase(), e) {
case "keyshortcuts":
case "label":
case "placeholder":
case "roledescription":
case "valuetext":
case "activedescendant":
case "details":
case "errormessage":
case "controls":
case "describedby":
case "flowto":
case "labelledby":
case "owns":
case "atomic":
case "busy":
case "disabled":
case "modal":
case "multiline":
case "multiselectable":
case "readonly":
case "required":
case "expanded":
case "grabbed":
case "hidden":
case "selected":
case "checked":
case "current":
case "haspopup":
case "invalid":
case "pressed":
case "autocomplete":
case "dropeffect":
case "live":
case "orientation":
case "relevant":
case "sort":
case "colcount":
case "colindex":
case "colspan":
case "level":
case "posinset":
case "rowcount":
case "rowindex":
case "rowspan":
case "setsize":
case "valuemax":
case "valuemin":
case "valuenow":
this.el.removeAttribute(`aria-${e}`);
break;
default: {
const s = e;
throw new TypeError(
`Invalid attribute: "aria-${s}". Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").`
);
}
}
return this;
}
// Implementation for `get()`
get(e) {
if (!arguments.length)
throw new TypeError(
"EasyAria.get() requires 1 argument, but received 0."
);
if (typeof e != "string")
throw new TypeError(
'Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").'
);
e = e.toLowerCase();
const s = this.el.getAttribute(`aria-${String(e)}`);
switch (e) {
case "activedescendant":
case "controls":
case "describedby":
case "details":
case "errormessage":
case "flowto":
case "keyshortcuts":
case "label":
case "labelledby":
case "owns":
case "placeholder":
case "roledescription":
case "valuetext":
return s;
case "autocomplete":
switch (s) {
case "both":
case "inline":
case "list":
case "none":
return s;
}
break;
case "dropeffect":
switch (s) {
case "copy":
case "execute":
case "link":
case "move":
case "none":
case "popup":
return s;
}
break;
case "live":
switch (s) {
case "assertive":
case "off":
case "polite":
return s;
}
break;
case "orientation":
switch (s) {
case "horizontal":
case "undefined":
case "vertical":
return s;
}
break;
case "relevant":
switch (s) {
case "additions":
case "additions text":
case "all":
case "removals":
case "text":
return s;
}
break;
case "sort":
switch (s) {
case "ascending":
case "descending":
case "none":
case "other":
return s;
}
break;
case "expanded":
case "grabbed":
case "hidden":
case "selected":
switch (s) {
case "true":
return !0;
case "false":
return !1;
case "undefined":
return s;
}
break;
case "checked":
case "pressed":
switch (s) {
case "true":
return !0;
case "false":
return !1;
case "mixed":
case "undefined":
return s;
}
break;
case "current":
switch (s) {
case "true":
return !0;
case "false":
return !1;
case "page":
case "step":
case "location":
case "date":
case "time":
return s;
}
break;
case "haspopup":
switch (s) {
case "true":
return !0;
case "false":
return !1;
case "menu":
case "listbox":
case "tree":
case "grid":
case "dialog":
return s;
}
break;
case "invalid":
switch (s) {
case "true":
return !0;
case "false":
return !1;
case "grammar":
case "spelling":
return s;
}
break;
case "atomic":
case "busy":
case "disabled":
case "modal":
case "multiline":
case "multiselectable":
case "readonly":
case "required":
switch (s) {
case "true":
return !0;
case "false":
return !1;
}
break;
case "colcount":
case "colindex":
case "colspan":
case "level":
case "posinset":
case "rowcount":
case "rowindex":
case "rowspan":
case "setsize":
case "valuemax":
case "valuemin":
case "valuenow": {
const c = Number(s);
if (!Number.isNaN(c))
return c;
break;
}
default: {
const c = e;
throw new TypeError(
`Invalid attribute: "aria-${c}". Please specify an un-prefixed ARIA 1.2 attribute (e.g., "checked").`
);
}
}
return null;
}
// ================== Convenience methods ==================
// =============== Setter methods ===============
/** Sets `aria-checked` to `true`. */
check() {
return this.set("checked");
}
/** Sets `aria-checked` to `false`. */
uncheck() {
return this.set("checked", !1);
}
/**
* Toggles the state of `aria-checked` between `true` and `false`.
* Sets it to `true` if its current value is neither.
*/
toggleChecked() {
return this.set("checked", !this.isChecked());
}
/**
* Sets `aria-controls` to the given value.
*
* @param value A space-separated string of ID references, an Element,
* or array/NodeList of Elements whose ID(s) to use for the attribute.
*/
control(e) {
return this.set("controls", e);
}
/**
* Sets `aria-describedby` to the given value.
*
* @param value A space-separated string of ID references, an Element,
* or array/NodeList of Elements whose ID(s) to use for the attribute.
*/
describeWith(e) {
return this.set("describedby", e);
}
/** Sets `aria-disabled` to `true`. */
disable() {
return this.set("disabled");
}
/** Sets `aria-disabled` to `false`. */
enable() {
return this.set("disabled", !1);
}
/**
* Toggles the state of `aria-disabled` between `true` and `false`.
* Sets it to `true` if its current value is neither.
*/
toggleDisabled() {
return this.set("disabled", !this.isDisabled());
}
/** Sets `aria-expanded` to `true`. */
expand() {
return this.set("expanded");
}
/** Sets `aria-expanded` to `false`. */
collapse() {
return this.set("expanded", !1);
}
/**
* Toggles the state of `aria-expanded` between `true` and `false`.
* Sets it to `true` if its current value is neither.
*/
toggleExpanded() {
return this.set("expanded", !this.isExpanded());
}
/**
* Sets `aria-flowto` to the given value.
*
* @param value A space-separated string of ID references, an Element,
* or array/NodeList of Elements whose ID(s) to use for the attribute.
*/
flowTo(e) {
return this.set("flowto", e);
}
/**
* Sets `aria-grabbed` to `true`.
*
* @deprecated in ARIA 1.1.
* The `aria-grabbed` state is expected to be replaced by a new feature
* in a future version of WAI-ARIA. Authors are therefore advised to treat
* `aria-grabbed` as deprecated.
*/
grab() {
return this.set("grabbed");
}
/**
* Sets `aria-grabbed` to `false`.
*
* @deprecated in ARIA 1.1.
* The `aria-grabbed` state is expected to be replaced by a new feature
* in a future version of WAI-ARIA. Authors are therefore advised to treat
* `aria-grabbed` as deprecated.
*/
ungrab() {
return this.set("grabbed", !1);
}
/**
* Toggles the state of `aria-grabbed` between `true` and `false`.
* Sets it to `true` if its current value is neither.
*
* @deprecated in ARIA 1.1.
* The `aria-grabbed` state is expected to be replaced by a new feature
* in a future version of WAI-ARIA. Authors are therefore advised to treat
* `aria-grabbed` as deprecated.
*/
toggleGrabbed() {
return this.set("grabbed", !this.isGrabbed());
}
/** Sets `aria-hidden` to `true`. */
hide() {
return this.set("hidden");
}
/** Sets `aria-hidden` to `false`. */
unhide() {
return this.set("hidden", !1);
}
/**
* Toggles the state of `aria-expanded` between `true` and `false`.
* Sets it to `true` if its current value is neither.
*/
toggleHidden() {
return this.set("hidden", !this.isHidden());
}
/** Sets `aria-label` to the given string. */
label(e) {
return this.set("label", e);
}
/**
* Sets `aria-labelledby` to the given value.
*
* @param value A space-separated string of ID references, an Element,
* or array/NodeList of Elements whose ID(s) to use for the attribute.
*/
labelWith(e) {
return this.set("labelledby", e);
}
/**
* Sets `aria-owns` to the given value.
*
* @param value A space-separated string of ID references, an Element,
* or array/NodeList of Elements whose ID(s) to use for the attribute.
*/
own(e) {
return this.set("owns", e);
}
/** Sets `aria-pressed` to `true`. */
press() {
return this.set("pressed");
}
/** Sets `aria-pressed` to `false`. */
unpress() {
return this.set("pressed", !1);
}
/**
* Toggles the state of `aria-pressed` between `true` and `false`.
* Sets it to `true` if its current value is neither.
*/
togglePressed() {
return this.set("pressed", !this.isPressed());
}
/** Sets `aria-required` to `true`. */
require() {
return this.set("required");
}
/** Sets `aria-required` to `false`. */
unrequire() {
return this.set("required", !1);
}
/**
* Toggles the state of `aria-required` between `true` and `false`.
*/
toggleRequired() {
return this.set("required", !this.isRequired());
}
/** Sets `aria-roledescription` to the given string. */
describeRole(e) {
return this.set("roledescription", e);
}
/** Sets `aria-selected` to `true`. */
select() {
return this.set("selected");
}
/** Sets `aria-selected` to `false`. */
unselect() {
return this.set("selected", !1);
}
/**
* Toggles the state of `aria-selected` between `true` and `false`.
* Sets it to `true` if its current value is neither.
*/
toggleSelected() {
return this.set("selected", !this.isSelected());
}
// =============== Boolean methods ===============
/**
* @returns `true` if `aria-atomic` is set to `true`, otherwise returns `false`.
*/
isAtomic() {
return this.get("atomic") === !0;
}
/**
* @returns `true` if `aria-busy` is set to `true`, otherwise returns `false`.
*/
isBusy() {
return this.get("busy") === !0;
}
/**
* @returns `true` if `aria-checked` is set to `true`, otherwise returns `false`.
*/
isChecked() {
return this.get("checked") === !0;
}
/**
* @param value Any of the tokens supported by `aria-current`, except `true` or `false`.
* @returns `true` if `aria-current` is set to the given value,
* or any of its supported values if none is provided, except `false`,
* in which case it returns `false`.
*/
isCurrent(e) {
const s = this.get("current");
return e ? s === e : s === !0 || s === "page" || s === "step" || s === "location" || s === "date" || s === "time";
}
/**
* @returns `true` if `aria-disabled` is set to `true`, otherwise returns `false`.
*/
isDisabled() {
return this.get("disabled") === !0;
}
/**
* @returns `true` if `aria-expanded` is set to `true`, otherwise returns `false`.
*/
isExpanded() {
return this.get("expanded") === !0;
}
/**
* @returns `true` if `aria-grabbed` is set to `true`, otherwise returns `false`.
* @deprecated in ARIA 1.1.
* The `aria-grabbed` state is expected to be replaced by a new feature
* in a future version of WAI-ARIA. Authors are therefore advised to treat
* `aria-grabbed` as deprecated.
*/
isGrabbed() {
return this.get("grabbed") === !0;
}
/**
* @param value Any of the tokens supported by `aria-haspopup`, except `true` or `false`.
* @returns `true` if `aria-haspopup` is set to the given value,
* or any of its supported values if none is provided, except `false`,
* in which case it returns `false`.
*/
hasPopup(e) {
const s = this.get("haspopup");
return e ? s === e : s === !0 || s === "menu" || s === "listbox" || s === "tree" || s === "grid" || s === "dialog";
}
/**
* @returns `true` if `aria-hidden` is set to `true` only on the wrapped Element.
* This method does not consider whether an ancestor has `aria-hidden` set to `true`.
*/
isHidden() {
return this.get("hidden") === !0;
}
/**
* @param value Any of the tokens supported by `aria-invalid`, except `true` or `false`.
* @returns `true` if `aria-invalid` is set to the given value,
* or any of its supported values if none is provided, except `false`,
* in which case it returns `false`.
*/
isInvalid(e) {
const s = this.get("invalid");
return e ? s === e : s === !0 || s === "grammar" || s === "spelling";
}
/**
* @returns `true` if `aria-modal` is set to `true`, otherwise returns `false`.
*/
isModal() {
return this.get("modal") === !0;
}
/**
* @returns `true` if `aria-multiline` is set to `true`, otherwise returns `false`.
*/
isMultiline() {
return this.get("multiline") === !0;
}
/**
* @returns `true` if `aria-multiselectable` is set to `true`, otherwise returns `false`.
*/
isMultiselectable() {
return this.get("multiselectable") === !0;
}
/**
* @returns `true` if `aria-pressed` is set to `true`, otherwise returns `false`.
*/
isPressed() {
return this.get("pressed") === !0;
}
/**
* @returns `true` if `aria-readonly` is set to `true`, otherwise returns `false`.
*/
isReadonly() {
return this.get("readonly") === !0;
}
/**
* @returns `true` if `aria-required` is set to `true`, otherwise returns `false`.
*/
isRequired() {
return this.get("required") === !0;
}
/**
* @returns `true` if `aria-selected` is set to `true`, otherwise returns `false`.
*/
isSelected() {
return this.get("selected") === !0;
}
};
f = new WeakMap(), w = new WeakSet(), k = function() {
return `easy-aria-id-${m(this, f)._++}`;
}, l = new WeakSet(), u = function(e) {
var s;
return e instanceof Element ? (e.id || (e.id = r(s = n, w, k).call(s)), e.id) : "";
}, a = new WeakSet(), t = function(e, s) {
this.el.setAttribute(`aria-${e}`, s);
}, /** Generates a unique ID. */
d(n, w), /**
* Returns the ID of a given Element. If no ID exists,
* assigns a newly generated ID and returns it.
*/
d(n, l), /** Counter for generating new IDs. */
d(n, f, 1);
let p = n;
function $(i) {
if (typeof i == "string") {
const e = document.querySelector(i);
if (e)
return new p(e);
} else if (i instanceof Element)
return new p(i);
return null;
}
export {
$ as default
};