Toggle aria-expanded="false" to "true"

grantsmith

Member
Local time
07:44
Joined
Aug 2, 2020
Messages
15

Hi,

I am rewriting a lump of jQuery into vanilla javascript, or at least trying to!

Everything that I require is working as I wish apart from the from toggling an aria-expanded from false to true.

jQuey:
// Hamburger
$(document).ready(function () {
    $(".hamburger").click(function () {
        $(this).toggleClass("is-active");
        $("body").toggleClass("noscroll");
        $(this).attr("aria-expanded", function (i, attr) {
            return attr == "true" ? "false" : "true";
        });
    });
});

// Display Mobile Menu

$(document).ready(function () {
    // Check for click events on the navbar burger icon
    $(".hamburger").click(function () {
        // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
        $(".nav").toggleClass("is-active");
        $(".navbar_menu-end").toggleClass("is-active");
    });
});

JavaScript:
// Hamburger Menu

document.addEventListener("DOMContentLoaded", function (event) {
    function menuClass() {
        // Look to menu Classes
        var mobileBtn = document.querySelector(".hamburger");
        var mobileNav = document.querySelector('.nav');

        //Toggle the various states
        mobileBtn.classList.toggle("is-active");
        mobileNav.classList.toggle('is-active');
        
        // Toggle attribute
        mobileBtn.toggleAttribute("aria-expanded", function (i, attr) {
            return attr == "true" ? "false" : "true";
        });
    }

    // Load the window function
    window.onload = function () {
        // Listen for events
        document.querySelector(".hamburger").addEventListener("click", menuClass);
        document.querySelector('.nav').addEventListener('click', menuClass);
    };
});

Not sure what I have misunderstood?

 
Solution

I know that you want to try it with plain/vanilla JavaScript and I think that this is great! There's so much overhead in most frameworks.
But at first I would like to show you how simple it can be with Alpine.JS:

HTML:
<nav x-data="{show...

Gummibeer

Astroneer
Moderator
Local time
08:44
Joined
Oct 5, 2019
Messages
1,156
Pronouns
he/him

I know that you want to try it with plain/vanilla JavaScript and I think that this is great! There's so much overhead in most frameworks.
But at first I would like to show you how simple it can be with Alpine.JS:

HTML:
<nav x-data="{show: false}">
    <button
        type="button"
        @click="show = !show"
        aria-controls="menu-list"
        aria-label="toggle main menu visibility"
        :aria-expanded="show ? 'true' : 'false'"
    >toggle menu</button>

    <ul :class="{'block': show, 'hidden': !show}" id="menu-list"></ul>
</nav>
That's it.^^ Really no JS file or anything.
The key is the x-data which defines an Alpine.JS template/watched element and an object as view data.
The @click="show = !show" adds a click listener and on-click it inverts show boolean.
And the solution to your question :aria-expanded="show ? 'true' : 'false'" is a bound attribute which has a callback that defines the conditional attribute value.
All notation is very similar to Vue.JS.

Now to your real question - doing it with vanilla JS.

The toggleAttribute function is only for boolean attributes like readonly, disabled or checked.


You will have to use setAttribute function that assigns a value to the attribute.

JavaScript:
var button = document.querySelector('#toggle')

button.addEventListener('click', () => {
  button.setAttribute(
    'aria-expanded',
    button.getAttribute('aria-expanded') === 'false' 
        ? 'true'
      : 'false'
  )
});

You will have to switch the elements - right now it toggles the attribute on the button. 😉
Here's the fiddle:

 
Solution

grantsmith

Member
Local time
07:44
Joined
Aug 2, 2020
Messages
15

Hey @Gummibeer,

Thanks for all the help. Yes, I've used Alpine.JS before and think it's great. However, this project literally has this one bit of JS, hence why any kind of framework just isn't viable.

I'll be keeping that AplineJs code for future use though 😄

Thanks again, much appreciated

 

Gummibeer

Astroneer
Moderator
Local time
08:44
Joined
Oct 5, 2019
Messages
1,156
Pronouns
he/him

Hey @Gummibeer,

Thanks for all the help. Yes, I've used Alpine.JS before and think it's great. However, this project literally has this one bit of JS, hence why any kind of framework just isn't viable.

I'll be keeping that AplineJs code for future use though 😄

Thanks again, much appreciated

No problem, yes I've done https://astrotomic.info also without any library. Even the count ups were super easy.
But I still know how much time it cost me to get this - I would say most common jQuery/bootstrap - working with alpine. 😅

 
Top