Creating a Loop for Tabs on an HTML Form

When navigating through form input boxes using the tab key, it usually goes in order. However, I discovered that you can actually customize this order by using tabindex=x. Since I have 5 inputs on my form, I use tabindex 5 times to specify the order. But after those 5, the focus moves to other elements on the page. Is there a way to create a loop so that the tab key cycles only through those initial 5 items? Unfortunately, I can't use tabindex=0 because then I'd have to add it to hundreds of other items as well. So, my question is how can I establish a "tab loop" for these specific 5 items?

Answer №1

Tab looping cannot be set up declaratively. This functionality is meant to align with the standard tabbing behavior of the browser, which includes navigating through all tab-able elements on the page and in the browser interface.

If you wish to restrict tabbing from a specific group of elements, JavaScript will be necessary. It's important to understand why this limitation is being imposed, provide clear visual indicators that certain elements are focused over others, and consider users who rely on keyboard navigation without visuals.

If after careful consideration you decide to alter the tabbing sequence, one approach is to create hidden tabbable elements (though still displayed) positioned before and after your target form items. These elements will redirect focus back to the beginning or end of the form as needed.

preFormDummy.addEventListener('focus', function(e){
  lastFormItem.focus() }, true )

postFormDummy.addEventListener('focus', function(e){
  firstFormItem.focus() }, true )

Remember to initially disable these dummy elements and only enable them once the form is accessed, signalling a modal state. Disable them again once the form interaction is complete.

It is crucial to conduct user testing to gauge reactions to this adjusted tabbing behavior. Feedback will reveal if users find it helpful or unsettling due to unexpected changes in tab navigation.

Answer №2

After experimenting with jQueryUI, I discovered a simple method to accomplish this task. I established a .tabloop class and implemented the code snippet below.

If you're looking for the :tabbable selector, it's not inherent in jQuery but can be easily created using jQueryUI.

// Focus loop within an element with the tabloop class
$(function() {
  $(document).on('keydown', '.tabloop :tabbable:not([readonly])', function(e) {

    // Only consider Tab key (code 9)
    if (e.keyCode != 9)
      return;

    var loop = $(this).closest('.tabloop');

    // Obtain first and last tabbable elements
    var firstTabbable = loop.find(':tabbable:not([readonly])').first();
    var lastTabbable = loop.find(':tabbable:not([readonly])').last();

    // When leaving the first element with Shift + Tab, focus on the last one
    if (firstTabbable.is(e.target) && e.shiftKey == true) {
      e.preventDefault();
      lastTabbable.focus();
    }

    // When leaving the last element with Tab, focus on the first one
    if (lastTabbable.is(e.target) && e.shiftKey == false) {
      e.preventDefault();
      firstTabbable.focus();
    }
  });
});
.tabloop {
  border: 1px red solid;
  padding: 1ch;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<p>
  <label for="text1">Field 1:</label>
  <input type="text" id="text1">
</p>

<p>
  <label for="text2">Field 2:</label>
  <input type="text" id="text2">
</p>

<p>
  <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">Link</a>
</p>

<p>
  <button type="button">Button</button>
</p>

<div class="tabloop">

  <p>
    <label for="text3">Field 3:</label>
    <input type="text" id="text3">
  </p>

  <p>
    <label for="text4">Field 4:</label>
    <input type="text" id="text4">
  </p>

  <p>
    <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">Link</a>
  </p>

  <p>
    <button type="button">Button</button>
  </p>
</div>

Answer №3

Following up on @NicolasBernier's JqueryUI solution, here is the modified code that successfully worked without using the ':tabbable' keyword.

// This section deals with the first tabbable element
$('containerOfInterest').find('firstTabbableElement(e.g. "a")').first().on('keydown', function (e) {

    // Handling shift and tab on the first element
    if (e.shiftKey == true && e.keyCode == 9) {
        console.log('Shift tab on first')
        e.preventDefault();
        
        $('containerOfInterest').find('lastTabbableElement(e.g. "button")').last().focus();
    }
});

// Handling tab on the last element: focusing back to the first one
$('containerOfInterest').find('lastTabbableElement(e.g. "button")').last().on('keydown', function (e) {

    // Leaving the last element with Tab : focus the first one
    if (e.shiftKey == false && e.keyCode == 9) {
        console.log('tab on last')
        e.preventDefault();

        $('containerOfInterest').find('firstTabbableElement(e.g. "a")').first().focus();
    }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A guide on extracting the text attribute of an element using an index in jQuery

object.option[index].title = object.option[index].text I am looking to convert this JavaScript code into jQuery. Any assistance would be greatly appreciated. ...

ability to reach the sub-element dictionaries in typescript

class ProvinciaComponent extends CatalogoGenerico implements OnInit, AfterViewInit { page: Page = new Page({sort: {field: 'description', dir: 'asc'}}); dataSource: ProvinciaDataSource; columns = ['codprovi ...

Identify the Google Maps Marker currently displayed on the screen

Is there a way to generate a list of markers within the zoom range for Google Maps, similar to the functionality on this site I'm curious if I can achieve this using jQuery or if there is a built-in function for Google Maps v3? Thank you! ...

Vue Labyrinthine Design theme

Looking for some guidance from experienced developers out there! I'm currently exploring how to incorporate Mazeletter as a background feature for each page in an app project I've been working on. This is all new territory for me, so any assista ...

In what way is the background-color of WindowInfoBackground utilized?

I attempted to implement background-color : WindowInfoBackground;. The property background-color : WindowInfoBackground; allows for the assignment of the system color to the background-color attribute. Despite using this particular value, the backgroun ...

Utilize background-size:cover and incorporate text in a horizontally scrolling webpage

Struggling to create a minimalist HTML layout with a horizontal scrollbar, featuring a large image on the left and a lengthy text with columns on the right? I suspect the issue lies in the implementation of position:relative with float, as well as position ...

In an HTML table, configure a column to expand to fill the remaining space while also having a minimum width of 300

Is there a way to create a column in the middle of an HTML table that fills the remaining space with a minimum width of 300px? Take a look at this JSfiddle for reference. HTML: <table> <tr> <td class="fixed-width">Fixed width col ...

Verify if the value in a textbox exceeds the number entered in an array of textboxes

My goal is to compare the value of a single text box, labeled as "totalmarkstoall", with multiple arrays of text boxes labeled as "marksscored". The JavaScript code below is set up to compare these values using a key up function. The issue I am facing is ...

Issue with sending data from JQuery Ajax to PHP codeExplanation:The problem

Here is the output from myscript.js: [{"orcamento":"10","atual":"20","desvio":"","data":"2015-01-01","nome_conta":"BBB","nome_categoria":"abc","nome_entidade":"def"}] This is the content of myscript.js: if (addList.length) { $.ajax($.extend({}, ajax ...

Performance problems arising from use of Tailwind CSS drop-shadow class

Lately, I've been struggling to pinpoint the root cause of a drastic FPS drop in my application. The issue arises after using the app for some time, leading to a performance plunge down to around 10FPS. After investigating, I discovered that eliminati ...

Error: Unable to access undefined properties while trying to read 'add' value. Issue identified in the code related to "classlist.add" function

I am currently facing an issue where I receive the error message: Uncaught TypeError: Cannot read properties of undefined (reading 'add') when trying to add a class to a div using a button. After researching on Stack Overflow, I stumbled upon a ...

"Embrace the power of Ajax and JSON with no regrets

function register() { hideshow('loading', 1); //error(0); $.ajax({ type: 'POST', dataType: 'json', url: 'submit.php', data: $('#regForm').serialize(), su ...

Experiencing a PHP Contact Form Problem - Unable to Identify the 400 Error Cause

Greetings! I'm fairly new to all this website creation stuff and I'm currently working on setting up a contact form from a template that I stumbled upon. Despite my best efforts in configuring the PHP code, I keep encountering a 400 response erro ...

Utilizing jQuery's .ready() method within the body section of a document to modify the onload event following the printing of the body

Recently, I took over a tabbed page that uses multiple queries to determine which tabs should be displayed. My goal is to add some PHP logic that will automatically set focus on a specific tab when the page finishes loading. I'm wondering if it&apos ...

How to execute a system command or external command in Node.js

I am encountering an issue with Node.js. When using Python, I would typically perform an external command execution like this: import subprocess subprocess.call("bower init", shell=True) Although I have explored child_process.exec and spawn in Node.js, I ...

Issue with Firefox compatibility in Backbone.js

Greetings! I am currently utilizing Backbone.js and require.js for my application, experiencing difficulty with template rendering in Firefox. Interestingly, it works without issues in both Chrome and IE. Allow me to present the code responsible for rende ...

Exploring nested routes with HashRouter in React

I've been working on a dashboard/admin control panel application using React, but I'm facing some challenges when it comes to handling component rendering accurately. Initially, my main App component is structured like this: <React.Fragment&g ...

Neglecting asynchronous Ajax functions once they have been called

I currently have a function that looks like this: $("#transfer").click(function(){ var token_rec = $("#token_rec").val(); var user_rec = $("#user_rec").val(); var subdomain_rec = $("#subdominio_rec").val(); var req_rec ...

Tips on showing content while filtering is taking longer with AngularJS

When working in Angular, I encountered a situation where filtering a large amount of data in a table was slowing down the process. To address this issue, I wanted to display a spinner every time a filter operation was in progress. Here is an example simil ...

Injecting CSS styles into dynamically inserted DOM elements

Utilizing Javascript, I am injecting several DOM elements into the page. Currently, I can successfully inject a single DOM element and apply CSS styling to it: var $e = $('<div id="header"></div>'); $('body').append($e); $ ...