dsfr4drupal-1.x-dev/js/dropbutton.js
js/dropbutton.js
/**
* @file
* Manage "dropbutton" behaviors.
*/
((Drupal, once) => {
Drupal.behaviors.dsfr4drupalDropbutton = {
attach: function (context) {
once("dsfr4drupal-dropbutton", ".dropbutton-multiple:has(.dropbutton--dsfr4drupal)", context).forEach(element => {
element.querySelector(".dropbutton-toggle").addEventListener("click", () => {
this.updatePosition(element);
window.addEventListener("scroll", () => Drupal.debounce(this.updatePositionIfOpen(element), 100));
window.addEventListener("resize", () => Drupal.debounce(this.updatePositionIfOpen(element), 100));
});
});
},
updatePosition: (element) => {
const preferredDir = document.documentElement.dir ?? "ltr";
const secondaryAction = element.querySelector(".secondary-action");
const dropMenu = secondaryAction.querySelector(".dropbutton__items");
const toggleHeight = element.offsetHeight;
const dropMenuWidth = dropMenu.offsetWidth;
const dropMenuHeight = dropMenu.offsetHeight;
const boundingRect = secondaryAction.getBoundingClientRect();
const spaceBelow = window.innerHeight - boundingRect.bottom;
const spaceLeft = boundingRect.left;
const spaceRight = window.innerWidth - boundingRect.right;
// Calculate the menu position based on available space and the preferred
// reading direction.
const leftAlignStyles = {
left: `${boundingRect.left}px`,
right: "auto"
};
const rightAlignStyles = {
left: "auto",
right: `${window.innerWidth - boundingRect.right}px`
};
if (preferredDir === "ltr") {
if (spaceRight >= dropMenuWidth) {
Object.assign(dropMenu.style, leftAlignStyles);
}
else {
Object.assign(dropMenu.style, rightAlignStyles);
}
}
else {
if (spaceLeft >= dropMenuWidth) {
Object.assign(dropMenu.style, rightAlignStyles);
}
else {
Object.assign(dropMenu.style, leftAlignStyles);
}
}
if (spaceBelow >= dropMenuHeight) {
dropMenu.style.top = `${boundingRect.bottom}px`;
}
else {
dropMenu.style.top = `${boundingRect.top - toggleHeight - dropMenuHeight}px`
}
},
updatePositionIfOpen: (element) => {
if (element.classList.contains("open")) {
this.updatePosition(element);
}
},
};
})(Drupal, once);
