12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- import getRootNode from '../dom/get-root-node';
- import cache from '../../core/base/cache';
- import { tokenList } from '../../core/utils';
- import standards from '../../standards';
- import { sanitize } from '../text/';
- const idRefsRegex = /^idrefs?$/;
- /**
- * Cache all ID references of a node and its children
- */
- function cacheIdRefs(node, idRefs, refAttrs) {
- if (node.hasAttribute) {
- if (node.nodeName.toUpperCase() === 'LABEL' && node.hasAttribute('for')) {
- const id = node.getAttribute('for');
- idRefs[id] = idRefs[id] || [];
- idRefs[id].push(node);
- }
- for (let i = 0; i < refAttrs.length; ++i) {
- const attr = refAttrs[i];
- const attrValue = sanitize(node.getAttribute(attr) || '');
- if (!attrValue) {
- continue;
- }
- const tokens = tokenList(attrValue);
- for (let k = 0; k < tokens.length; ++k) {
- idRefs[tokens[k]] = idRefs[tokens[k]] || [];
- idRefs[tokens[k]].push(node);
- }
- }
- }
- for (let i = 0; i < node.children.length; i++) {
- cacheIdRefs(node.children[i], idRefs, refAttrs);
- }
- }
- /**
- * Return all DOM nodes that use the nodes ID in the accessibility tree.
- * @param {Element} node
- * @returns {Element[]}
- */
- function getAccessibleRefs(node) {
- node = node.actualNode || node;
- let root = getRootNode(node);
- root = root.documentElement || root; // account for shadow roots
- let idRefsByRoot = cache.get('idRefsByRoot');
- if (!idRefsByRoot) {
- idRefsByRoot = new WeakMap();
- cache.set('idRefsByRoot', idRefsByRoot);
- }
- let idRefs = idRefsByRoot.get(root);
- if (!idRefs) {
- idRefs = {};
- idRefsByRoot.set(root, idRefs);
- const refAttrs = Object.keys(standards.ariaAttrs).filter(attr => {
- const { type } = standards.ariaAttrs[attr];
- return idRefsRegex.test(type);
- });
- cacheIdRefs(root, idRefs, refAttrs);
- }
- return idRefs[node.id] || [];
- }
- export default getAccessibleRefs;
|