skip to Main Content

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.

2

Answers


  1. You need to NOT prevent default so scrolling works. I could have tested this if you had posted an example with HTML

    Try this

    $('input[type="radio"][role="tab"]').on('keydown', function(e) {
      if (e.key == 'ArrowDown' || e.key == 'ArrowUp') {
        // Stop propagation to the tab control but allow default behavior
        e.stopPropagation();
      }
    });
    
    Login or Signup to reply.
  2. 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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search