Closed michaeltlombardi closed 3 years ago
Hey @michaeltlombardi
Interestingly enough I've been thinking about a very similar process for books in Drupal!
While adding something into accessible-menu proper would probably not be worth it (pretty unique case), you can easily just overwrite a function in accessible-menu after you've included it on the page.
I haven't tested anything yet myself, but my current idea is to rewrite the initialize()
function for menuToggles
so that it would actually look for either the openClass
or perhaps aria-expanded="true"
on the toggle in the DOM (which would be initially rendered by Drupal). If found, it would then trigger expand()
on itself.
My advise would be to try something similar.
Whenever I end up implementing this in my Drupal instance I can post here with how I actually went about doing it.
Thanks! I can try giving this override a shot. My javascript is pretty weak but that makes sense to me! If I find a functional solution I'll post it here myself. π
Hmmm, trying to do so using the CDN source and banging my head on things, will keep trying but if you've got a handy-dandy pseudo-code example of how to overwrite this, I'm π
Extant script in my site footer:
<script src="https://cdn.jsdelivr.net/npm/accessible-menu/dist/accessibleMenu.js"></script>
<script>
const navs = document.querySelectorAll("nav");
const menuSettings = {
menuItemSelector: ".menu-item",
submenuItemSelector: ".menu-item.dropdown",
submenuToggleSelector: ".dropdown-toggle",
submenuSelector: ".menu.dropdown",
};
const whitelistNavs = ["site-nav", "game-nav", "blog-nav"]
navs.forEach(nav => {
const menuElement = nav.querySelector(".menu");
if (whitelistNavs.includes(nav.id)) {
const controllerElement = nav.querySelector(".menu-toggle");
const menu = new AccessibleMenu.Menubar({
menuElement,
...menuSettings,
controllerElement,
containerElement: nav
});
}
});
</script>
Ended up with a lazy work around:
<script src="https://cdn.jsdelivr.net/npm/accessible-menu/dist/accessibleMenu.js"></script>
<script>
const navs = document.querySelectorAll("nav");
const menuSettings = {
menuItemSelector: ".menu-item",
submenuItemSelector: ".menu-item.dropdown",
submenuToggleSelector: ".dropdown-toggle",
submenuSelector: ".menu.dropdown",
};
const whitelistNavs = ["site-nav", "game-nav", "blog-nav"]
function openMenuItem(element) {
element.classList.remove("hide");
element.classList.add("show");
element.setAttribute("aria-expanded", true);
}
navs.forEach(nav => {
const menuElement = nav.querySelector(".menu");
if (whitelistNavs.includes(nav.id)) {
const controllerElement = nav.querySelector(".menu-toggle");
<!-- const lists = nav.querySelectorAll(ul[role=menubar]) -->
const menu = new AccessibleMenu.Menubar({
menuElement,
...menuSettings,
controllerElement,
containerElement: nav
});
const currentTreeElements = nav.querySelectorAll("ul.current");
for (let element of currentTreeElements) {
openMenuItem(element);
}
}
});
</script>
Since I'm using hugo to generate the pages, it was trivial to mark the current node and ancestor menus with the current
class.
@michaeltlombardi I don't have a Drupal book example yet, but I do have an example where I overwrite the expand/collapse functions for toggles to work with Bootstrap 3 (Disclaimer: this is super hacky, but I think its a similar method to what you would need to do).
/**
* Override's an AccessibleMenu's default expand/collapse functions
* allowing it to work natively with Bootstrap 3.
*
* @param {AccessibleMenu.DisclosureMenu} menu - The menu to alter.
*/
function overrideToggling(menu) {
menu.menuElements.submenuToggles.forEach(toggle => {
toggle.expand = () => {
toggle.dom.toggle.setAttribute("aria-expanded", "true");
// Add the open class
if (toggle.openClass !== "") {
if (typeof toggle.openClass === "string") {
toggle.elements.controlledMenu.dom.menu.classList.add(
toggle.openClass
);
toggle.domElements.parent.classList.add(toggle.openClass);
} else if (Array.isArray(toggle.openClass)) {
toggle.openClass.forEach(value => {
toggle.elements.controlledMenu.dom.menu.classList.add(value);
toggle.domElements.parent.classList.add(value);
});
}
}
// Remove the close class.
if (toggle.closeClass !== "") {
if (typeof toggle.closeClass === "string") {
toggle.elements.controlledMenu.dom.menu.classList.remove(
toggle.closeClass
);
toggle.domElements.parent.classList.remove(toggle.closeClass);
} else if (Array.isArray(toggle.closeClass)) {
toggle.closeClass.forEach(value => {
toggle.elements.controlledMenu.dom.menu.classList.remove(value);
toggle.domElements.parent.classList.remove(value);
});
}
}
};
toggle.collapse = () => {
toggle.dom.toggle.setAttribute("aria-expanded", "false");
// Add the close class
if (toggle.closeClass !== "") {
if (typeof toggle.closeClass === "string") {
toggle.elements.controlledMenu.dom.menu.classList.add(
toggle.closeClass
);
toggle.domElements.parent.classList.add(toggle.closeClass);
} else if (Array.isArray(toggle.closeClass)) {
toggle.closeClass.forEach(value => {
toggle.elements.controlledMenu.dom.menu.classList.add(value);
toggle.domElements.parent.classList.add(value);
});
}
}
// Remove the open class.
if (toggle.openClass !== "") {
if (typeof toggle.openClass === "string") {
toggle.elements.controlledMenu.dom.menu.classList.remove(
toggle.openClass
);
toggle.domElements.parent.classList.remove(toggle.openClass);
} else if (Array.isArray(toggle.openClass)) {
toggle.openClass.forEach(value => {
toggle.elements.controlledMenu.dom.menu.classList.remove(value);
toggle.domElements.parent.classList.remove(value);
});
}
}
};
});
}
In my case I just passed it an already-initialized DisclosureMenu to loop through.
You would need to use a similar method to replace the initialize function of the toggles and then re-initialize them once you made the edit.
Closing as "resolved" since I believe we have a solution here.
I unfortunately haven't had time to implement this for Drupal books yet, but with the release of v3.0.0 my approach will most likely change to writing a custom subclass that will look for a flag to "auto open" a menu toggle on initialization.
Hullo! So opening caveat, I'm a competent infrastructure/backend developer whose javascript and frontend are both much less polished.
That out of the way, I'm trying to use
accessible-menu
to build accessible disclosure navigation menus for both a site (with multiple "books") and the books via hugo. templating.For site navigation, this is less of an issue, but for navigation within a book, it would be extremely useful to be able to apply some automatic styling to indicate where in the book's navigation you currently are - possibly just by defaulting that section to expanded?
I've been introspecting on the initialized
AccessibleMenu.DisclosureMenu
object but can't seem to figure out a way to discover the appropriate elements and toggle them. If I tab through things and introspect, I can usefoo.currentMenuItem.menuElements.toggle.expand()
but I'm not sure I understand how to do this programmatically on page load.Is this a wild anti-pattern, to pre-expand a disclosure menu to the current page? If not, I'd love to understand how to do this with
accessible-menu
.Thanks in advance (and it's okay if you don't have time/interest in answering this! π)