govuk-frontend
Version:
GOV.UK Frontend contains the code you need to start building a user interface for government platforms and services.
114 lines (109 loc) • 3.52 kB
JavaScript
import { getBreakpoint } from '../../common/index.mjs';
import { Component } from '../../component.mjs';
import { ElementError } from '../../errors/index.mjs';
/**
* Service Navigation component
*
* @preserve
*/
class ServiceNavigation extends Component {
/**
* @param {Element | null} $root - HTML element to use for header
*/
constructor($root) {
super($root);
this.$menuButton = void 0;
this.$menu = void 0;
this.menuIsOpen = false;
this.mql = null;
const $menuButton = this.$root.querySelector('.govuk-js-service-navigation-toggle');
if (!$menuButton) {
return this;
}
const menuId = $menuButton.getAttribute('aria-controls');
if (!menuId) {
throw new ElementError({
component: ServiceNavigation,
identifier: 'Navigation button (`<button class="govuk-js-service-navigation-toggle">`) attribute (`aria-controls`)'
});
}
const $menu = document.getElementById(menuId);
if (!$menu) {
throw new ElementError({
component: ServiceNavigation,
element: $menu,
identifier: `Navigation (\`<ul id="${menuId}">\`)`
});
}
this.$menu = $menu;
this.$menuButton = $menuButton;
this.setupResponsiveChecks();
this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
}
setupResponsiveChecks() {
const breakpoint = getBreakpoint('tablet');
if (!breakpoint.value) {
throw new ElementError({
component: ServiceNavigation,
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
});
}
this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
this.mql.addEventListener('change', () => this.checkMode());
} else {
this.mql.addListener(() => this.checkMode());
}
this.checkMode();
}
checkMode() {
if (!this.mql || !this.$menu || !this.$menuButton) {
return;
}
if (this.mql.matches) {
this.$menu.removeAttribute('hidden');
setAttributes(this.$menuButton, attributesForHidingButton);
} else {
removeAttributes(this.$menuButton, Object.keys(attributesForHidingButton));
this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen.toString());
if (this.menuIsOpen) {
this.$menu.removeAttribute('hidden');
} else {
this.$menu.setAttribute('hidden', '');
}
}
}
handleMenuButtonClick() {
this.menuIsOpen = !this.menuIsOpen;
this.checkMode();
}
}
ServiceNavigation.moduleName = 'govuk-service-navigation';
const attributesForHidingButton = {
hidden: '',
'aria-hidden': 'true'
};
/**
* Sets a group of attributes on the given element
*
* @param {Element} $element - The element to set the attribute on
* @param {{[attributeName: string]: string}} attributes - The attributes to set
*/
function setAttributes($element, attributes) {
for (const attributeName in attributes) {
$element.setAttribute(attributeName, attributes[attributeName]);
}
}
/**
* Removes a list of attributes from the given element
*
* @param {Element} $element - The element to remove the attributes from
* @param {string[]} attributeNames - The names of the attributes to remove
*/
function removeAttributes($element, attributeNames) {
for (const attributeName of attributeNames) {
$element.removeAttribute(attributeName);
}
}
export { ServiceNavigation };
//# sourceMappingURL=service-navigation.mjs.map