How to make my div with role="button" attribute clickable with the enter key
Asked Answered
D

1

6

I have an app that needs to be fully navigable by keyboard. When I click on the header of a div (generated by a javascript/jquery function), an event listener is triggered. I was able to highlight the headers with tab by adding the attributes role="button" and tabindex="0", but it's still only clickable by mouse. The ARIA documentation is kind of hard to follow and I don't have much time left.

HTML

<section id="js-item-root">

  <div class="item">
    <h2 class="item-header js-item-header" id="1" role="button" tabindex="1">Title of the First Div</div>
    <p>This is a paragraph</p>
  </div>

  <div class="item">
    <h2 class="item-header js-item-header" id="2" role="button" tabindex="2" >Title of the Second Div</div>
    <p>This is also a paragraph</p>
  </div>

</section>

CSS

.item {
  border: solid black 2px;
  margin: 15px;
  padding: 15px;
}

.item-header {
  border-bottom: solid black 1px;
  background-color: lightgrey;
  padding: 5px 0;
}

Javascript/Jquery:

function handleHeaderClick() {
  $('#js-item-root').on('click', '.js-item-header', function(event) {
    event.preventDefault();

    console.log(this.id)
  }
}

how to I get the console.log to work when I highlight the header with the tab key and press enter?

//Progress update detailed below

I was able to get my code working right by trading my <div>s for <button>s and setting the width to width: 100%, but I still want to learn a way to make a div ACT like a button. I tried creating a new function that sawpped the 'click' for a 'keypress', but that didn't work. Is there something else I'm missing?

Depreciatory answered 13/12, 2020 at 16:57 Comment(5)
Hint: You need a key event listener also on those elements and check which key was usedBritish
I've tried "$('#js-item-root').on('keypress', '.js-item-header', function(event) { event.preventDefault(); console.log(this.id) }" , but it's still not working with the attribute.Depreciatory
Ok, that should work. But your question was about keys so you need a key event listener also ... like .on('keydown'...British
neither 'keypress' or 'keydown' are workingDepreciatory
Create a runnable demo that shows what you tried and be a bit more specific than "not working". Any errors, what actually happens etc?British
P
2

Sometimes using a button element isn't possible without creating invalid html - e.g. when you need to use block level elements such as headings and divs inside the button. For those times I use the following snippet to get back what you lose from using a real button:

// --------------------------------------------
// Allow role=button to behave like a real <button> el.
// by triggering the click on spacebar/enter keydown
// --------------------------------------------

document.querySelectorAll('div[role="button"]').forEach(el => {
    el.addEventListener('keydown', e => {
        const keyDown = e.key !== undefined ? e.key : e.keyCode;
        if ( (keyDown === 'Enter' || keyDown === 13) || (['Spacebar', ' '].indexOf(keyDown) >= 0 || keyDown === 32)) {
            // (prevent default so the page doesn't scroll when pressing space)
            e.preventDefault();
            el.click();
        }
    });
});
Perbunan answered 10/10, 2022 at 16:12 Comment(2)
Better to attach a listener to the whole document and use event delegation, rather than attaching to every element. This won't cover dynamically created elements.Lolly
I disagree that it's automatically "better" to use event delegation. I'd say you should keep things as simple as possible and use event delegation only when the need arises.Perbunan

© 2022 - 2024 — McMap. All rights reserved.