190 lines
7.9 KiB
JavaScript
190 lines
7.9 KiB
JavaScript
import Mmenu from './../oncanvas/mmenu.oncanvas';
|
|
import options from './_options';
|
|
import configs from './_configs';
|
|
import translate from './translations/translate';
|
|
import { extendShorthandOptions } from './_options';
|
|
import * as DOM from '../../_modules/dom';
|
|
import { extend } from '../../_modules/helpers';
|
|
// Add the translations.
|
|
translate();
|
|
// Add the options and configs.
|
|
Mmenu.options.screenReader = options;
|
|
Mmenu.configs.screenReader = configs;
|
|
export default function () {
|
|
var _this = this;
|
|
// Extend options.
|
|
var options = extendShorthandOptions(this.opts.screenReader);
|
|
this.opts.screenReader = extend(options, Mmenu.options.screenReader);
|
|
// Extend configs.
|
|
var configs = this.conf.screenReader;
|
|
// Add Aria-* attributes
|
|
if (options.aria) {
|
|
// Add screenreader / aria hooks for add-ons
|
|
// In orde to keep this list short, only extend hooks that are actually used by other add-ons.
|
|
this.bind('initAddons:after', function () {
|
|
_this.bind('initMenu:after', function () {
|
|
this.trigger('initMenu:after:sr-aria', [].slice.call(arguments));
|
|
});
|
|
_this.bind('initNavbar:after', function () {
|
|
this.trigger('initNavbar:after:sr-aria', [].slice.call(arguments));
|
|
});
|
|
_this.bind('openPanel:start', function () {
|
|
this.trigger('openPanel:start:sr-aria', [].slice.call(arguments));
|
|
});
|
|
_this.bind('close:start', function () {
|
|
this.trigger('close:start:sr-aria', [].slice.call(arguments));
|
|
});
|
|
_this.bind('close:finish', function () {
|
|
this.trigger('close:finish:sr-aria', [].slice.call(arguments));
|
|
});
|
|
_this.bind('open:start', function () {
|
|
this.trigger('open:start:sr-aria', [].slice.call(arguments));
|
|
});
|
|
_this.bind('initOpened:after', function () {
|
|
this.trigger('initOpened:after:sr-aria', [].slice.call(arguments));
|
|
});
|
|
});
|
|
// Update aria-hidden for hidden / visible listitems
|
|
this.bind('updateListview', function () {
|
|
_this.node.pnls
|
|
.querySelectorAll('.mm-listitem')
|
|
.forEach(function (listitem) {
|
|
Mmenu.sr_aria(listitem, 'hidden', listitem.matches('.mm-hidden'));
|
|
});
|
|
});
|
|
// Update aria-hidden for the panels when opening and closing a panel.
|
|
this.bind('openPanel:start', function (panel) {
|
|
/** Panels that should be considered "hidden". */
|
|
var hidden = DOM.find(_this.node.pnls, '.mm-panel')
|
|
.filter(function (hide) { return hide !== panel; })
|
|
.filter(function (hide) { return !hide.parentElement.matches('.mm-panel'); });
|
|
/** Panels that should be considered "visible". */
|
|
var visible = [panel];
|
|
DOM.find(panel, '.mm-listitem_vertical .mm-listitem_opened').forEach(function (listitem) {
|
|
visible.push.apply(visible, DOM.children(listitem, '.mm-panel'));
|
|
});
|
|
// Set the panels to be considered "hidden" or "visible".
|
|
hidden.forEach(function (panel) {
|
|
Mmenu.sr_aria(panel, 'hidden', true);
|
|
});
|
|
visible.forEach(function (panel) {
|
|
Mmenu.sr_aria(panel, 'hidden', false);
|
|
});
|
|
});
|
|
this.bind('closePanel', function (panel) {
|
|
Mmenu.sr_aria(panel, 'hidden', true);
|
|
});
|
|
// Add aria-haspopup and aria-owns to prev- and next buttons.
|
|
this.bind('initPanel:after', function (panel) {
|
|
DOM.find(panel, '.mm-btn').forEach(function (button) {
|
|
Mmenu.sr_aria(button, 'haspopup', true);
|
|
var href = button.getAttribute('href');
|
|
if (href) {
|
|
Mmenu.sr_aria(button, 'owns', href.replace('#', ''));
|
|
}
|
|
});
|
|
});
|
|
// Add aria-hidden for navbars in panels.
|
|
this.bind('initNavbar:after', function (panel) {
|
|
/** The navbar in the panel. */
|
|
var navbar = DOM.children(panel, '.mm-navbar')[0];
|
|
/** Whether or not the navbar should be considered "hidden". */
|
|
var hidden = navbar.matches('.mm-hidden');
|
|
// Set the navbar to be considered "hidden" or "visible".
|
|
Mmenu.sr_aria(navbar, 'hidden', hidden);
|
|
});
|
|
// Text
|
|
if (options.text) {
|
|
// Add aria-hidden to titles in navbars
|
|
if (this.opts.navbar.titleLink == 'parent') {
|
|
this.bind('initNavbar:after', function (panel) {
|
|
/** The navbar in the panel. */
|
|
var navbar = DOM.children(panel, '.mm-navbar')[0];
|
|
/** Whether or not the navbar should be considered "hidden". */
|
|
var hidden = navbar.querySelector('.mm-btn_prev')
|
|
? true
|
|
: false;
|
|
// Set the navbar-title to be considered "hidden" or "visible".
|
|
Mmenu.sr_aria(DOM.find(navbar, '.mm-navbar__title')[0], 'hidden', hidden);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
// Add screenreader text
|
|
if (options.text) {
|
|
// Add screenreader / text hooks for add-ons
|
|
// In orde to keep this list short, only extend hooks that are actually used by other add-ons.
|
|
this.bind('initAddons:after', function () {
|
|
_this.bind('setPage:after', function () {
|
|
this.trigger('setPage:after:sr-text', [].slice.call(arguments));
|
|
});
|
|
_this.bind('initBlocker:after', function () {
|
|
this.trigger('initBlocker:after:sr-text', [].slice.call(arguments));
|
|
});
|
|
});
|
|
// Add text to the prev-buttons.
|
|
this.bind('initNavbar:after', function (panel) {
|
|
var navbar = DOM.children(panel, '.mm-navbar')[0];
|
|
if (navbar) {
|
|
var button = DOM.children(navbar, '.mm-btn_prev')[0];
|
|
if (button) {
|
|
button.innerHTML = Mmenu.sr_text(_this.i18n(configs.text.closeSubmenu));
|
|
}
|
|
}
|
|
});
|
|
// Add text to the next-buttons.
|
|
this.bind('initListview:after', function (listview) {
|
|
var parent = listview.closest('.mm-panel')['mmParent'];
|
|
if (parent) {
|
|
var next = DOM.children(parent, '.mm-btn_next')[0];
|
|
if (next) {
|
|
var text = _this.i18n(configs.text[next.parentElement.matches('.mm-listitem_vertical')
|
|
? 'toggleSubmenu'
|
|
: 'openSubmenu']);
|
|
next.innerHTML += Mmenu.sr_text(text);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
// Methods
|
|
(function () {
|
|
var attr = function (element, attr, value) {
|
|
element[attr] = value;
|
|
if (value) {
|
|
element.setAttribute(attr, value.toString());
|
|
}
|
|
else {
|
|
element.removeAttribute(attr);
|
|
}
|
|
};
|
|
/**
|
|
* Add aria (property and) attribute to a HTML element.
|
|
*
|
|
* @param {HTMLElement} element The node to add the attribute to.
|
|
* @param {string} name The (non-aria-prefixed) attribute name.
|
|
* @param {string|boolean} value The attribute value.
|
|
*/
|
|
Mmenu.sr_aria = function (element, name, value) {
|
|
attr(element, 'aria-' + name, value);
|
|
};
|
|
/**
|
|
* Add role attribute to a HTML element.
|
|
*
|
|
* @param {HTMLElement} element The node to add the attribute to.
|
|
* @param {string|boolean} value The attribute value.
|
|
*/
|
|
Mmenu.sr_role = function (element, value) {
|
|
attr(element, 'role', value);
|
|
};
|
|
/**
|
|
* Wrap a text in a screen-reader-only node.
|
|
*
|
|
* @param {string} text The text to wrap.
|
|
* @return {string} The wrapped text.
|
|
*/
|
|
Mmenu.sr_text = function (text) {
|
|
return '<span class="mm-sronly">' + text + '</span>';
|
|
};
|
|
})();
|