aria-api

access ARIA information from JavaScript
git clone https://git.ce9e.org/aria-api.git

commit
032ad4fd0079a8797b2d0ea88c1712c970a503f5
parent
9a10de5818daf67b637f1fa106a23f2e82017c4d
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-01-30 08:25
lint: use const/let

Diffstat

M lib/atree.js 48 ++++++++++++++++++++++++------------------------
M lib/attrs.js 36 ++++++++++++++++++------------------
M lib/constants.js 14 +++++++-------
M lib/name.js 70 ++++++++++++++++++++++++++++++------------------------------
M lib/query.js 22 ++++++++++------------

5 files changed, 94 insertions, 96 deletions


diff --git a/lib/atree.js b/lib/atree.js

@@ -1,10 +1,10 @@
    1    -1 var attrs = require('./attrs');
   -1     1 const attrs = require('./attrs');
    2     2 
    3    -1 var _getOwner = function(node, owners) {
   -1     3 const _getOwner = function(node, owners) {
    4     4 	if (node.nodeType === node.ELEMENT_NODE && node.id) {
    5    -1 		var selector = '[aria-owns~="' + CSS.escape(node.id) + '"]';
   -1     5 		const selector = '[aria-owns~="' + CSS.escape(node.id) + '"]';
    6     6 		if (owners) {
    7    -1 			for (var owner of owners) {
   -1     7 			for (const owner of owners) {
    8     8 				if (owner.matches(selector)) {
    9     9 					return owner;
   10    10 				}
@@ -15,12 +15,12 @@ var _getOwner = function(node, owners) {
   15    15 	}
   16    16 };
   17    17 
   18    -1 var _getParentNode = function(node, owners) {
   -1    18 const _getParentNode = function(node, owners) {
   19    19 	return _getOwner(node, owners) || node.parentNode;
   20    20 };
   21    21 
   22    -1 var detectLoop = function(node, owners) {
   23    -1 	var seen = [node];
   -1    22 const detectLoop = function(node, owners) {
   -1    23 	const seen = [node];
   24    24 	while ((node = _getParentNode(node, owners))) {
   25    25 		if (seen.includes(node)) {
   26    26 			return true;
@@ -29,35 +29,35 @@ var detectLoop = function(node, owners) {
   29    29 	}
   30    30 };
   31    31 
   32    -1 var getOwner = function(node, owners) {
   33    -1 	var owner = _getOwner(node, owners);
   -1    32 const getOwner = function(node, owners) {
   -1    33 	const owner = _getOwner(node, owners);
   34    34 	if (owner && !detectLoop(node, owners)) {
   35    35 		return owner;
   36    36 	}
   37    37 };
   38    38 
   39    -1 var getParentNode = function(node, owners) {
   -1    39 const getParentNode = function(node, owners) {
   40    40 	return getOwner(node, owners) || node.parentNode;
   41    41 };
   42    42 
   43    -1 var isHidden = function(node) {
   -1    43 const isHidden = function(node) {
   44    44 	return node.nodeType === node.ELEMENT_NODE && attrs.getAttribute(node, 'hidden');
   45    45 };
   46    46 
   47    -1 var getChildNodes = function(node, owners) {
   48    -1 	var childNodes = [];
   -1    47 const getChildNodes = function(node, owners) {
   -1    48 	const childNodes = [];
   49    49 
   50    -1 	for (var i = 0; i < node.childNodes.length; i++) {
   51    -1 		var child = node.childNodes[i];
   -1    50 	for (let i = 0; i < node.childNodes.length; i++) {
   -1    51 		const child = node.childNodes[i];
   52    52 		if (!getOwner(child, owners) && !isHidden(child)) {
   53    53 			childNodes.push(child);
   54    54 		}
   55    55 	}
   56    56 
   57    57 	if (node.nodeType === node.ELEMENT_NODE) {
   58    -1 		var owns = attrs.getAttribute(node, 'owns') || [];
   59    -1 		for (var i = 0; i < owns.length; i++) {
   60    -1 			var child = document.getElementById(owns[i]);
   -1    58 		const owns = attrs.getAttribute(node, 'owns') || [];
   -1    59 		for (let i = 0; i < owns.length; i++) {
   -1    60 			const child = document.getElementById(owns[i]);
   61    61 			// double check with getOwner for consistency
   62    62 			if (child && getOwner(child, owners) === node && !isHidden(child)) {
   63    63 				childNodes.push(child);
@@ -68,18 +68,18 @@ var getChildNodes = function(node, owners) {
   68    68 	return childNodes;
   69    69 };
   70    70 
   71    -1 var walk = function(root, fn) {
   72    -1 	var owners = document.querySelectorAll('[aria-owns]');
   73    -1 	var queue = [root];
   -1    71 const walk = function(root, fn) {
   -1    72 	const owners = document.querySelectorAll('[aria-owns]');
   -1    73 	let queue = [root];
   74    74 	while (queue.length) {
   75    -1 		var item = queue.shift();
   -1    75 		const item = queue.shift();
   76    76 		fn(item);
   77    77 		queue = getChildNodes(item, owners).concat(queue);
   78    78 	}
   79    79 };
   80    80 
   81    -1 var searchUp = function(node, test) {
   82    -1 	var candidate = getParentNode(node);
   -1    81 const searchUp = function(node, test) {
   -1    82 	const candidate = getParentNode(node);
   83    83 	if (candidate) {
   84    84 		if (test(candidate)) {
   85    85 			return candidate;

diff --git a/lib/attrs.js b/lib/attrs.js

@@ -1,23 +1,23 @@
    1    -1 var constants = require('./constants.js');
   -1     1 const constants = require('./constants.js');
    2     2 
    3     3 // candidates can be passed for performance optimization
    4    -1 var getRole = function(el, candidates) {
   -1     4 const getRole = function(el, candidates) {
    5     5 	if (el.hasAttribute('role')) {
    6    -1 		var roles = el.getAttribute('role').toLowerCase().split(/\s+/);
   -1     6 		const roles = el.getAttribute('role').toLowerCase().split(/\s+/);
    7     7 		if (roles.length > 1 && candidates) {
    8     8 			return [roles, candidates];
    9     9 		}
   10    -1 		for (var role of roles) {
   -1    10 		for (const role of roles) {
   11    11 			if (!candidates || candidates.includes(role)) {
   12    12 				return role;
   13    13 			}
   14    14 		}
   15    15 	} else {
   16    -1 		var roles = candidates ? candidates : Object.keys(constants.roles);
   17    -1 		for (var role of roles) {
   18    -1 			var r = constants.roles[role];
   -1    16 		const roles = candidates ? candidates : Object.keys(constants.roles);
   -1    17 		for (const role of roles) {
   -1    18 			const r = constants.roles[role];
   19    19 			if (r) {
   20    -1 				var selector = (r.selectors || []).join(',');
   -1    20 				const selector = (r.selectors || []).join(',');
   21    21 				if (selector && el.matches(selector)) {
   22    22 					return role;
   23    23 				}
@@ -26,16 +26,16 @@ var getRole = function(el, candidates) {
   26    26 	}
   27    27 };
   28    28 
   29    -1 var hasRole = function(el, roles) {
   30    -1 	var candidates = [].concat.apply([], roles.map(role => {
   -1    29 const hasRole = function(el, roles) {
   -1    30 	const candidates = [].concat.apply([], roles.map(role => {
   31    31 		return (constants.roles[role] || {}).subRoles || [role];
   32    32 	}));
   33    33 	return !!getRole(el, candidates);
   34    34 };
   35    35 
   36    -1 var getAttribute = function(el, key) {
   -1    36 const getAttribute = function(el, key) {
   37    37 	if (constants.attributeStrongMapping.hasOwnProperty(key)) {
   38    -1 		var value = el[constants.attributeStrongMapping[key]];
   -1    38 		const value = el[constants.attributeStrongMapping[key]];
   39    39 		if (value) {
   40    40 			return value;
   41    41 		}
@@ -52,14 +52,14 @@ var getAttribute = function(el, key) {
   52    52 		if (el.matches('details:not([open]) > :not(summary)')) {
   53    53 			return true;
   54    54 		}
   55    -1 		var style = window.getComputedStyle(el);
   -1    55 		const style = window.getComputedStyle(el);
   56    56 		if (style.display === 'none' || style.visibility === 'hidden') {
   57    57 			return true;
   58    58 		}
   59    59 	}
   60    60 
   61    -1 	var type = constants.attributes[key];
   62    -1 	var raw = el.getAttribute('aria-' + key);
   -1    61 	const type = constants.attributes[key];
   -1    62 	const raw = el.getAttribute('aria-' + key);
   63    63 
   64    64 	if (raw) {
   65    65 		if (type === 'bool') {
@@ -88,7 +88,7 @@ var getAttribute = function(el, key) {
   88    88 	// list -> aria-controls
   89    89 
   90    90 	if (key === 'level') {
   91    -1 		for (var i = 1; i <= 6; i++) {
   -1    91 		for (let i = 1; i <= 6; i++) {
   92    92 			if (el.tagName.toLowerCase() === 'h' + i) {
   93    93 				return i;
   94    94 			}
@@ -98,8 +98,8 @@ var getAttribute = function(el, key) {
   98    98 	}
   99    99 
  100   100 	if (key in constants.attrsWithDefaults) {
  101    -1 		var role = getRole(el);
  102    -1 		var defaults = (constants.roles[role] || {}).defaults;
   -1   101 		const role = getRole(el);
   -1   102 		const defaults = (constants.roles[role] || {}).defaults;
  103   103 		if (defaults && defaults.hasOwnProperty(key)) {
  104   104 			return defaults[key];
  105   105 		}

diff --git a/lib/constants.js b/lib/constants.js

@@ -67,7 +67,7 @@ exports.attributeWeakMapping = {
   67    67 };
   68    68 
   69    69 // https://www.w3.org/TR/html/dom.html#sectioning-content-2
   70    -1 var scoped = ['article *', 'aside *', 'nav *', 'section *'].join(',');
   -1    70 const scoped = ['article *', 'aside *', 'nav *', 'section *'].join(',');
   71    71 
   72    72 // https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings
   73    73 // https://www.w3.org/TR/wai-aria/roles
@@ -604,11 +604,11 @@ exports.roles = {
  604   604 	},
  605   605 };
  606   606 
  607    -1 var getSubRoles = function(role) {
  608    -1 	var children = (exports.roles[role] || {}).childRoles || [];
  609    -1 	var descendents = children.map(getSubRoles);
   -1   607 const getSubRoles = function(role) {
   -1   608 	const children = (exports.roles[role] || {}).childRoles || [];
   -1   609 	const descendents = children.map(getSubRoles);
  610   610 
  611    -1 	var result = [role];
   -1   611 	const result = [role];
  612   612 
  613   613 	descendents.forEach(list => {
  614   614 		list.forEach(r => {
@@ -623,9 +623,9 @@ var getSubRoles = function(role) {
  623   623 
  624   624 exports.attrsWithDefaults = [];
  625   625 
  626    -1 for (var role in exports.roles) {
   -1   626 for (const role in exports.roles) {
  627   627 	exports.roles[role].subRoles = getSubRoles(role);
  628    -1 	for (var key in exports.roles[role].defaults) {
   -1   628 	for (const key in exports.roles[role].defaults) {
  629   629 		if (!exports.attrsWithDefaults.includes(key)) {
  630   630 			exports.attrsWithDefaults.push(key);
  631   631 		}

diff --git a/lib/name.js b/lib/name.js

@@ -1,11 +1,11 @@
    1    -1 var constants = require('./constants.js');
    2    -1 var atree = require('./atree.js');
    3    -1 var query = require('./query.js');
    4    -1 
    5    -1 var getPseudoContent = function(node, selector) {
    6    -1 	var styles = window.getComputedStyle(node, selector);
    7    -1 	var ret = styles.getPropertyValue('content');
    8    -1 	var inline = styles.display.substr(0, 6) === 'inline';
   -1     1 const constants = require('./constants.js');
   -1     2 const atree = require('./atree.js');
   -1     3 const query = require('./query.js');
   -1     4 
   -1     5 const getPseudoContent = function(node, selector) {
   -1     6 	const styles = window.getComputedStyle(node, selector);
   -1     7 	const ret = styles.getPropertyValue('content');
   -1     8 	const inline = styles.display.substr(0, 6) === 'inline';
    9     9 	if (!ret) {
   10    10 		return '';
   11    11 	}
@@ -20,12 +20,12 @@ var getPseudoContent = function(node, selector) {
   20    20 	}
   21    21 };
   22    22 
   23    -1 var getContent = function(root, visited) {
   24    -1 	var children = atree.getChildNodes(root);
   -1    23 const getContent = function(root, visited) {
   -1    24 	const children = atree.getChildNodes(root);
   25    25 
   26    -1 	var ret = '';
   27    -1 	for (var i = 0; i < children.length; i++) {
   28    -1 		var node = children[i];
   -1    26 	let ret = '';
   -1    27 	for (let i = 0; i < children.length; i++) {
   -1    28 		const node = children[i];
   29    29 		if (node.nodeType === node.TEXT_NODE) {
   30    30 			ret += node.textContent;
   31    31 		} else if (node.nodeType === node.ELEMENT_NODE) {
@@ -44,13 +44,13 @@ var getContent = function(root, visited) {
   44    44 	return ret;
   45    45 };
   46    46 
   47    -1 var allowNameFromContent = function(el) {
   48    -1 	var role = query.getRole(el);
   -1    47 const allowNameFromContent = function(el) {
   -1    48 	const role = query.getRole(el);
   49    49 	return (constants.roles[role] || {}).nameFromContents;
   50    50 };
   51    51 
   52    -1 var getName = function(el, recursive, visited, directReference) {
   53    -1 	var ret = '';
   -1    52 const getName = function(el, recursive, visited, directReference) {
   -1    53 	let ret = '';
   54    54 
   55    55 	visited = visited || [];
   56    56 	if (visited.includes(el)) {
@@ -66,9 +66,9 @@ var getName = function(el, recursive, visited, directReference) {
   66    66 
   67    67 	// B
   68    68 	if (!recursive && el.matches('[aria-labelledby]')) {
   69    -1 		var ids = el.getAttribute('aria-labelledby').split(/\s+/);
   70    -1 		var strings = ids.map(id => {
   71    -1 			var label = document.getElementById(id);
   -1    69 		const ids = el.getAttribute('aria-labelledby').split(/\s+/);
   -1    70 		const strings = ids.map(id => {
   -1    71 			const label = document.getElementById(id);
   72    72 			return label ? getName(label, true, visited, true) : '';
   73    73 		});
   74    74 		ret = strings.join(' ');
@@ -79,7 +79,7 @@ var getName = function(el, recursive, visited, directReference) {
   79    79 		if (query.matches(el, 'textbox,button')) {
   80    80 			ret = el.value || el.textContent;
   81    81 		} else if (query.matches(el, 'combobox,listbox')) {
   82    -1 			var selected = query.querySelector(el, ':selected') || query.querySelector(el, 'option');
   -1    82 			const selected = query.querySelector(el, ':selected') || query.querySelector(el, 'option');
   83    83 			if (selected) {
   84    84 				ret = getName(selected, recursive, visited);
   85    85 			} else {
@@ -98,7 +98,7 @@ var getName = function(el, recursive, visited, directReference) {
   98    98 
   99    99 	// D
  100   100 	if (!ret.trim() && !recursive && el.labels) {
  101    -1 		var strings = Array.prototype.map.call(el.labels, label => {
   -1   101 		const strings = Array.prototype.map.call(el.labels, label => {
  102   102 			return getName(label, true, visited);
  103   103 		});
  104   104 		ret = strings.join(' ');
@@ -113,9 +113,9 @@ var getName = function(el, recursive, visited, directReference) {
  113   113 		ret = el.title;
  114   114 	}
  115   115 	if (!ret.trim()) {
  116    -1 		for (var selector in constants.nameFromDescendant) {
   -1   116 		for (const selector in constants.nameFromDescendant) {
  117   117 			if (el.matches(selector)) {
  118    -1 				var descendant = el.querySelector(constants.nameFromDescendant[selector]);
   -1   118 				const descendant = el.querySelector(constants.nameFromDescendant[selector]);
  119   119 				if (descendant) {
  120   120 					ret = getName(descendant, true, visited);
  121   121 				}
@@ -123,7 +123,7 @@ var getName = function(el, recursive, visited, directReference) {
  123   123 		}
  124   124 	}
  125   125 	if (!ret.trim() && el.matches('svg *')) {
  126    -1 		var svgTitle = el.querySelector('title');
   -1   126 		const svgTitle = el.querySelector('title');
  127   127 		if (svgTitle && svgTitle.parentElement === el) {
  128   128 			ret = svgTitle.textContent;
  129   129 		}
@@ -140,7 +140,7 @@ var getName = function(el, recursive, visited, directReference) {
  140   140 	}
  141   141 
  142   142 	if (!ret.trim()) {
  143    -1 		for (var selector in constants.nameDefaults) {
   -1   143 		for (const selector in constants.nameDefaults) {
  144   144 			if (el.matches(selector)) {
  145   145 				ret = constants.nameDefaults[selector];
  146   146 			}
@@ -162,29 +162,29 @@ var getName = function(el, recursive, visited, directReference) {
  162   162 		ret = ' ';
  163   163 	}
  164   164 
  165    -1 	var before = getPseudoContent(el, ':before');
  166    -1 	var after = getPseudoContent(el, ':after');
   -1   165 	const before = getPseudoContent(el, ':before');
   -1   166 	const after = getPseudoContent(el, ':after');
  167   167 	return before + ret + after;
  168   168 };
  169   169 
  170    -1 var getNameTrimmed = function(el) {
   -1   170 const getNameTrimmed = function(el) {
  171   171 	return getName(el).replace(/\s+/g, ' ').trim();
  172   172 };
  173   173 
  174    -1 var getDescription = function(el) {
  175    -1 	var ret = '';
   -1   174 const getDescription = function(el) {
   -1   175 	let ret = '';
  176   176 
  177   177 	if (el.matches('[aria-describedby]')) {
  178    -1 		var ids = el.getAttribute('aria-describedby').split(/\s+/);
  179    -1 		var strings = ids.map(id => {
  180    -1 			var label = document.getElementById(id);
   -1   178 		const ids = el.getAttribute('aria-describedby').split(/\s+/);
   -1   179 		const strings = ids.map(id => {
   -1   180 			const label = document.getElementById(id);
  181   181 			return label ? getName(label, true) : '';
  182   182 		});
  183   183 		ret = strings.join(' ');
  184   184 	} else if (el.matches('[aria-description]')) {
  185   185 		ret = el.getAttribute('aria-description');
  186   186 	} else if (el.matches('svg *')) {
  187    -1 		var svgDesc = el.querySelector('desc');
   -1   187 		const svgDesc = el.querySelector('desc');
  188   188 		if (svgDesc && svgDesc.parentElement === el) {
  189   189 			ret = svgDesc.textContent;
  190   190 		}

diff --git a/lib/query.js b/lib/query.js

@@ -1,26 +1,24 @@
    1    -1 var attrs = require('./attrs.js');
    2    -1 var atree = require('./atree.js');
   -1     1 const attrs = require('./attrs.js');
   -1     2 const atree = require('./atree.js');
    3     3 
    4     4 
    5    -1 var matches = function(el, selector) {
    6    -1 	var actual;
    7    -1 
   -1     5 const matches = function(el, selector) {
    8     6 	if (selector.substr(0, 1) === ':') {
    9    -1 		var attr = selector.substr(1);
   -1     7 		const attr = selector.substr(1);
   10     8 		return attrs.getAttribute(el, attr);
   11     9 	} else if (selector.substr(0, 1) === '[') {
   12    -1 		var match = /\[([a-z]+)="(.*)"\]/.exec(selector);
   13    -1 		actual = attrs.getAttribute(el, match[1]);
   14    -1 		var rawValue = match[2];
   -1    10 		const match = /\[([a-z]+)="(.*)"\]/.exec(selector);
   -1    11 		const actual = attrs.getAttribute(el, match[1]);
   -1    12 		const rawValue = match[2];
   15    13 		return actual.toString() === rawValue;
   16    14 	} else {
   17    15 		return attrs.hasRole(el, selector.split(','));
   18    16 	}
   19    17 };
   20    18 
   21    -1 var _querySelector = function(all) {
   -1    19 const _querySelector = function(all) {
   22    20 	return function(root, role) {
   23    -1 		var results = [];
   -1    21 		const results = [];
   24    22 		try {
   25    23 			atree.walk(root, node => {
   26    24 				if (node.nodeType === node.ELEMENT_NODE) {
@@ -42,7 +40,7 @@ var _querySelector = function(all) {
   42    40 	};
   43    41 };
   44    42 
   45    -1 var closest = function(el, selector) {
   -1    43 const closest = function(el, selector) {
   46    44 	return atree.searchUp(el, candidate => {
   47    45 		if (candidate.nodeType === candidate.ELEMENT_NODE) {
   48    46 			return matches(candidate, selector);