Shtole
Shtole

Reputation: 354

Disable 'keydown' event listener for some keys

I want my Bootstrap tab switchers to stop eating Up and Down keys, so the page could scroll instead, as if they are not focused.

$('input[type="radio"][role="tab"]').on('keydown keyup', function (e)
{
    if (e.key == 'ArrowDown' || e.key == 'ArrowUp')
    {
        e.stopImmediatePropagation();
        e.preventDefault();

        // So far so good.

        $('body')[0].dispatchEvent(new KeyboardEvent(e.type, { 'key': e.key }));

        // No effect :(
    }
});

The code above made the controls stop responding to Up and Down, but unfortunately the page doesn't scroll nevertheless.

UPD Here's MRE: https://getbootstrap.com/docs/5.3/forms/checks-radios/#radio-toggle-buttons. Click any of the buttons (“Checked” or “Radio”) and try pressing ←, ↑, ↓ and →. I'm fine with ← and →, but I want the page to scroll, when I press ↓ and ↑.

UPD2 This kind of works:

$('input[type="radio"][role="tab"]').on('keydown keyup', function (e)
{
    if (e.key == 'ArrowDown' || e.key == 'ArrowUp')
    {
        e.stopImmediatePropagation();
        e.preventDefault();

        document.activeElement.blur();
    }
});

After the first pressing on ↓ or ↑, the element loses focus, then the page starts scrolling as usual. Not exactly what I wanted, but it's even better from UX viewpoint, I guess.

Upvotes: 0

Views: 80

Answers (1)

James
James

Reputation: 22237

I don't think re-dispatching the keyboard event will work. It might work for entering text into a field but probably not for scrolling a document.

I suggest you stick with preventDefault, and take control of the scroll yourself. You might need to change that part of the code to suit your page, but here's my example.

$('input[type="radio"][role="tab"]').on('keydown keyup', function (e)
{
    if (e.key == 'ArrowDown' || e.key == 'ArrowUp')
    {

        e.preventDefault();
        if (e.type === 'keydown') {
          window.scrollBy({
            left: 0, 
            top: e.key === 'ArrowDown' ? 30 : -30,
            behavior: "smooth"
          });
        }
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>

<p>prior content</p>

<input type="radio" role="tab" class="btn-check" name="options" id="option1" autocomplete="off" checked>
<label class="btn btn-secondary" for="option1">Checked</label>

<input type="radio" role="tab" class="btn-check" name="options" id="option2" autocomplete="off">
<label class="btn btn-secondary" for="option2">Radio</label>

<input type="radio" role="tab" class="btn-check" name="options" id="option3" autocomplete="off" disabled>
<label class="btn btn-secondary" for="option3">Disabled</label>

<input type="radio" role="tab" class="btn-check" name="options" id="option4" autocomplete="off">
<label class="btn btn-secondary" for="option4">Radio</label>


<p>following content</p>
<p>following content</p>
<p>following content</p>
<p>following content</p>
<p>following content</p>
<p>following content</p>
<p>following content</p>
<p>following content</p>
<p>following content</p>
<p>following content</p>
<p>following content</p>
<p>following content</p>

Upvotes: 1

Related Questions