156 lines
4.8 KiB
JavaScript
156 lines
4.8 KiB
JavaScript
|
|
/**
|
||
|
|
* @file
|
||
|
|
*
|
||
|
|
* Sidebar component.
|
||
|
|
*
|
||
|
|
* Only few common things. Like close all popovers when one is opened.
|
||
|
|
*
|
||
|
|
* @type {Drupal~behavior}
|
||
|
|
*
|
||
|
|
* @prop {Drupal~behaviorAttach} attach
|
||
|
|
* Attaches the behavior to the `.admin-toolbar` element.
|
||
|
|
*/
|
||
|
|
|
||
|
|
(
|
||
|
|
(Drupal, once) => {
|
||
|
|
/**
|
||
|
|
* Drupal behaviors object.
|
||
|
|
*
|
||
|
|
* @type {Drupal~behaviors}
|
||
|
|
*/
|
||
|
|
|
||
|
|
Drupal.behaviors.navigation = {
|
||
|
|
attach(context) {
|
||
|
|
/**
|
||
|
|
* Sidebar element with the `.admin-toolbar` class.
|
||
|
|
*
|
||
|
|
* @type {HTMLElement}
|
||
|
|
*/
|
||
|
|
once('navigation', '.admin-toolbar', context).forEach((sidebar) => {
|
||
|
|
const backButton = sidebar.querySelector(
|
||
|
|
'[data-toolbar-back-control]',
|
||
|
|
);
|
||
|
|
if (!backButton) {
|
||
|
|
// We're in layout editing mode and the .admin-toolbar we have in
|
||
|
|
// scope here is the empty one that only exists to leave space for
|
||
|
|
// the one added by layout builder. We need to use an empty
|
||
|
|
// .admin-toolbar element because the css uses the adjacent
|
||
|
|
// sibling selector.
|
||
|
|
// @see \navigation_page_top();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* All menu triggers.
|
||
|
|
*
|
||
|
|
* @type {NodeList}
|
||
|
|
*/
|
||
|
|
const buttons = sidebar.querySelectorAll(
|
||
|
|
'[data-toolbar-menu-trigger]',
|
||
|
|
);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* All popovers and tooltip triggers.
|
||
|
|
*
|
||
|
|
* @type {NodeList}
|
||
|
|
*/
|
||
|
|
// const popovers = sidebar.querySelectorAll('[data-toolbar-popover]');
|
||
|
|
|
||
|
|
/**
|
||
|
|
* NodeList of all tooltip elements.
|
||
|
|
*
|
||
|
|
* @type {NodeList}
|
||
|
|
*/
|
||
|
|
const tooltips = sidebar.querySelectorAll('[data-drupal-tooltip]');
|
||
|
|
|
||
|
|
const closeButtons = () => {
|
||
|
|
buttons.forEach((button) => {
|
||
|
|
button.dispatchEvent(
|
||
|
|
new CustomEvent('toolbar-menu-set-toggle', {
|
||
|
|
detail: {
|
||
|
|
state: false,
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
);
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
const closePopovers = (current = false) => {
|
||
|
|
// TODO: Find way to use popovers variable.
|
||
|
|
// This change needed because BigPipe replaces user popover.
|
||
|
|
sidebar
|
||
|
|
.querySelectorAll('[data-toolbar-popover]')
|
||
|
|
.forEach((popover) => {
|
||
|
|
if (
|
||
|
|
current &&
|
||
|
|
current instanceof Element &&
|
||
|
|
popover.isEqualNode(current)
|
||
|
|
) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
popover.dispatchEvent(
|
||
|
|
new CustomEvent('toolbar-popover-close', {}),
|
||
|
|
);
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
// Add click event listeners to all buttons and then contains the callback
|
||
|
|
// to expand / collapse the button's menus.
|
||
|
|
sidebar.addEventListener('click', (e) => {
|
||
|
|
if (e.target.matches('button, button *')) {
|
||
|
|
e.target.closest('button').focus();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// We want to close all popovers when we close sidebar.
|
||
|
|
sidebar.addEventListener('toggle-admin-toolbar-content', (e) => {
|
||
|
|
if (!e.detail.state) {
|
||
|
|
closePopovers();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// When any popover opened we close all others.
|
||
|
|
sidebar.addEventListener('toolbar-popover-toggled', (e) => {
|
||
|
|
if (e.detail.state) {
|
||
|
|
closeButtons();
|
||
|
|
closePopovers(e.target);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// When any menu opened we close all others.
|
||
|
|
sidebar.addEventListener('toolbar-menu-toggled', (e) => {
|
||
|
|
if (e.detail.state) {
|
||
|
|
// We want to close buttons on when new opened only if they are on same level.
|
||
|
|
const targetLevel = e.detail.level;
|
||
|
|
buttons.forEach((button) => {
|
||
|
|
const buttonLevel = button.dataset.toolbarMenuTrigger;
|
||
|
|
if (
|
||
|
|
!button.isEqualNode(e.target) &&
|
||
|
|
+buttonLevel === +targetLevel
|
||
|
|
) {
|
||
|
|
button.dispatchEvent(
|
||
|
|
new CustomEvent('toolbar-menu-set-toggle', {
|
||
|
|
detail: {
|
||
|
|
state: false,
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
backButton.addEventListener('click', closePopovers);
|
||
|
|
|
||
|
|
// Tooltips triggered on hover and focus so add an extra event listener
|
||
|
|
// to close all popovers.
|
||
|
|
tooltips.forEach((tooltip) => {
|
||
|
|
['mouseover', 'focus'].forEach((e) => {
|
||
|
|
tooltip.addEventListener(e, closePopovers);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|
||
|
|
)(Drupal, once);
|