aria-query — это специализированная библиотека для
работы с ARIA-ролями и свойствами в JavaScript. Она предоставляет
структуру данных и утилиты для проверки соответствия элементов DOM
спецификациям WAI-ARIA. Центральными объектами библиотеки являются
ARIA roles, ARIA
properties/attributes, а также mappings,
связывающие роли с поддерживаемыми свойствами.
В ARIA различают несколько типов ролей:
button, checkbox, slider,
tab и др.).article, region,
heading).banner, main, navigation,
complementary).Каждая роль может иметь обязательные свойства (required properties) и поддерживаемые свойства (supported properties). Обязательные свойства должны присутствовать в элементе DOM, чтобы роль считалась корректно реализованной.
Например, роль slider требует наличие свойства
aria-valuemin, aria-valuemax и
aria-valuenow. Без этих свойств элемент не будет корректно
интерпретирован вспомогательными технологиями.
Библиотека предоставляет несколько ключевых коллекций:
Roles — карта всех ролей с их характеристиками. Каждая роль описывается объектом с полями:
name — название ролиrequiredProps — список обязательных свойствsupportedProps — список дополнительных поддерживаемых
свойствabstract — булевое значение, указывающее, что роль
абстрактная и не должна использоваться напрямуюProperties — карта ARIA-свойств с их типами и
допустимыми значениями (string, token,
boolean, tristate и др.).
Эти структуры позволяют динамически проверять корректность разметки и валидировать элементы на соответствие спецификации ARIA.
Для проверки обязательных свойств сначала необходимо определить роль
элемента. Aria-query предоставляет объект roles с методами
для поиска по имени:
import { roles } from 'aria-query';
const role = roles.get('slider');
console.log(role.requiredProps);
// ['aria-valuemin', 'aria-valuemax', 'aria-valuenow']
Если роль не найдена, проверка свойств невозможна, так как нет информации о требованиях.
Для проверки конкретного элемента используется сопоставление его атрибутов с обязательными свойствами роли:
function validateRequiredProps(element) {
const roleName = element.getAttribute('role');
const role = roles.get(roleName);
if (!role) return false; // неизвестная роль
return role.requiredProps.every(prop => element.hasAttribute(prop));
}
const slider = document.querySelector('#volumeSlider');
console.log(validateRequiredProps(slider)); // true или false
Метод every гарантирует, что все обязательные
свойства присутствуют, что является ключевым требованием для
корректной реализации ARIA-ролей.
Абстрактные роли Абстрактные роли
(abstract: true) не проверяются на обязательные свойства,
так как они не предназначены для использования в DOM. Пример:
range — базовая роль для slider и
spinbutton.
Наследование свойств Некоторые роли наследуют
обязательные свойства от родительских ролей. В aria-query
это учитывается через поле superClass. При проверке
необходимо учитывать не только requiredProps текущей роли,
но и свойства из superClass.
Типы свойств Свойства могут иметь разные типы:
string, integer, boolean и
token. Для обязательных свойств важна не только их
наличность, но и корректность значения. Например,
aria-valuenow для slider должен быть числом
между aria-valuemin и aria-valuemax.
function validatePropTypes(element, role) {
return role.requiredProps.every(prop => {
const value = element.getAttribute(prop);
const type = role.props[prop]?.type;
if (!type) return true; // неизвестный тип
switch(type) {
case 'integer': return !isNaN(parseInt(value, 10));
case 'boolean': return value === 'true' || value === 'false';
default: return typeof value === 'string';
}
});
}
aria-query
предоставляет готовые объекты для итерации и фильтрации ролей и свойств.
Это облегчает автоматическую генерацию проверок, например, для линтеров
и тестов доступности.import { roles } from 'aria-query';
const widgets = Array.from(roles)
.filter(([name, data]) => data.superClass.has('widget'))
.map(([name]) => name);
console.log(widgets);
// ['button', 'checkbox', 'slider', 'tab', ...]
Проверка обязательных свойств необходима для:
Правильная реализация гарантирует, что вспомогательные технологии смогут корректно взаимодействовать с интерактивными элементами, повышая общую доступность интерфейса.
Для больших приложений рекомендуется кэшировать результаты проверки,
чтобы избежать повторных обращений к DOM и коллекциям
roles. Также можно создавать универсальные
функции-валидаторы для всех виджетов, что упрощает поддержку и
тестирование компонентов.
const cachedValidation = new Map();
function isValidElement(element) {
const roleName = element.getAttribute('role');
if (cachedValidation.has(roleName)) return cachedValidation.get(roleName);
const role = roles.get(roleName);
if (!role) return false;
const result = role.requiredProps.every(prop => element.hasAttribute(prop));
cachedValidation.set(roleName, result);
return result;
}
Эта стратегия позволяет эффективно проверять обязательные свойства даже на больших страницах с множеством интерактивных элементов.