forked from amazingfate/help
Ever since the contents of the modules and lang menus started being populated upon click, the flow for screenreader users has been potentially confusing. This patch introduces a11y-toggle into the mix: https://github.com/edenspiekermann/a11y-toggle Checkboxes were changed into buttons. This hopefully makes it clear we want the user to click them. The contents tree still uses the checkbox hack, because its items are populated upon page load. Change-Id: I3482bea0c8669f96794498fc37d9d18fe3f829d5 Reviewed-on: https://gerrit.libreoffice.org/72467 Tested-by: Jenkins Tested-by: Olivier Hallot <olivier.hallot@libreoffice.org> Reviewed-by: Olivier Hallot <olivier.hallot@libreoffice.org>
101 lines
2.6 KiB
JavaScript
101 lines
2.6 KiB
JavaScript
/*
|
|
MIT License
|
|
|
|
Copyright (c) 2016 Edenspiekermann
|
|
|
|
*/
|
|
|
|
(function () {
|
|
'use strict';
|
|
|
|
var internalId = 0;
|
|
var togglesMap = {};
|
|
var targetsMap = {};
|
|
|
|
function $ (selector, context) {
|
|
return Array.prototype.slice.call(
|
|
(context || document).querySelectorAll(selector)
|
|
);
|
|
}
|
|
|
|
function getClosestToggle (element) {
|
|
if (element.closest) {
|
|
return element.closest('[data-a11y-toggle]');
|
|
}
|
|
|
|
while (element) {
|
|
if (element.nodeType === 1 && element.hasAttribute('data-a11y-toggle')) {
|
|
return element;
|
|
}
|
|
|
|
element = element.parentNode;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function handleToggle (toggle) {
|
|
var target = toggle && targetsMap[toggle.getAttribute('aria-controls')];
|
|
|
|
if (!target) {
|
|
return false;
|
|
}
|
|
|
|
var toggles = togglesMap['#' + target.id];
|
|
var isExpanded = target.getAttribute('aria-hidden') === 'false';
|
|
|
|
target.setAttribute('aria-hidden', isExpanded);
|
|
toggles.forEach(function (toggle) {
|
|
toggle.setAttribute('aria-expanded', !isExpanded);
|
|
});
|
|
}
|
|
|
|
var initA11yToggle = function (context) {
|
|
togglesMap = $('[data-a11y-toggle]', context).reduce(function (acc, toggle) {
|
|
var selector = '#' + toggle.getAttribute('data-a11y-toggle');
|
|
acc[selector] = acc[selector] || [];
|
|
acc[selector].push(toggle);
|
|
return acc;
|
|
}, togglesMap);
|
|
|
|
var targets = Object.keys(togglesMap);
|
|
targets.length && $(targets).forEach(function (target) {
|
|
var toggles = togglesMap['#' + target.id];
|
|
var isExpanded = target.hasAttribute('data-a11y-toggle-open');
|
|
var labelledby = [];
|
|
|
|
toggles.forEach(function (toggle) {
|
|
toggle.id || toggle.setAttribute('id', 'a11y-toggle-' + internalId++);
|
|
toggle.setAttribute('aria-controls', target.id);
|
|
toggle.setAttribute('aria-expanded', isExpanded);
|
|
labelledby.push(toggle.id);
|
|
});
|
|
|
|
target.setAttribute('aria-hidden', !isExpanded);
|
|
target.hasAttribute('aria-labelledby') || target.setAttribute('aria-labelledby', labelledby.join(' '));
|
|
|
|
targetsMap[target.id] = target;
|
|
});
|
|
};
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
initA11yToggle();
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var toggle = getClosestToggle(event.target);
|
|
handleToggle(toggle);
|
|
});
|
|
|
|
document.addEventListener('keyup', function (event) {
|
|
if (event.which === 13 || event.which === 32) {
|
|
var toggle = getClosestToggle(event.target);
|
|
if (toggle && toggle.getAttribute('role') === 'button') {
|
|
handleToggle(toggle);
|
|
}
|
|
}
|
|
});
|
|
|
|
window && (window.a11yToggle = initA11yToggle);
|
|
})();
|