Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simulating the TAB keydown: focusing next element as determined by `tabIndex`

Tags:

I have two input elements, the first is focused, and I want to focus the second by simulating the TAB keypress/keydown event. (Note: I don't want to use .next() or such.)

This is my code, inspired from this question:

$('input').first().focus();  var e = $.Event('keydown');  e.which = 9; // TAB $(':focus').trigger(e); 

Please see http://jsfiddle.net/3PcPH/

The code doesn't work. What is wrong?

like image 960
Randomblue Avatar asked Sep 05 '11 02:09

Randomblue


People also ask

How do you move focus on next field when Enter is pressed?

FCS is a jQuery plugin that has the ability to automatically move focus on the next form field when Enter key is pressed. The main goal of the plugin is to set focus on the next input field by pressing Enter key. It also supports any type of form controls like textarea, button, select, and more.

What does Tabindex =- 1 mean?

A negative value (usually tabindex="-1" ) means that the element is not reachable via sequential keyboard navigation, but could be focused with JavaScript or visually by clicking with the mouse. It's mostly useful to create accessible widgets with JavaScript.

What can I use instead of Tabindex?

Instead of using tabindex , simply adjust the page's source code order to support a logical navigation and reading order, then use CSS to adjust the visual presentation.


2 Answers

There is no simple programmatic way to do this using Javascript... so here's a brute force way.

According to W3:

Elements that may receive focus should be navigated by user agents according to the following rules:

  1. Those elements that support the tabindex attribute and assign a positive value to it are navigated first. Navigation proceeds from the element with the lowest tabindex value to the element with the highest value. Values need not be sequential nor must they begin with any particular value. Elements that have identical tabindex values should be navigated in the order they appear in the character stream.
  2. Those elements that do not support the tabindex attribute or support it and assign it a value of "0" are navigated next. These elements are navigated in the order they appear in the character stream.
  3. Elements that are disabled do not participate in the tabbing order.

I accomplished this by storing the order of elements in the form that have tabIndex > 0 in their tabIndex order and then concatenating the rest of the elements in the order they appear within the document. The following code simulates a tab keypress when focused on a form input and the letter 'z' is pressed (but you can change this to whatever condition you require):

$(':input').keypress(function(e){       // if 'z' pressed     if (e.which == 122) {          // if we haven't stored the tabbing order         if (!this.form.tabOrder) {              var els = this.form.elements,                 ti = [],                 rest = [];              // store all focusable form elements with tabIndex > 0             for (var i = 0, il = els.length; i < il; i++) {                 if (els[i].tabIndex > 0 &&                     !els[i].disabled &&                      !els[i].hidden &&                      !els[i].readOnly &&                     els[i].type !== 'hidden') {                     ti.push(els[i]);                 }             }              // sort them by tabIndex order             ti.sort(function(a,b){ return a.tabIndex - b.tabIndex; });              // store the rest of the elements in order             for (i = 0, il = els.length; i < il; i++) {                 if (els[i].tabIndex == 0 &&                     !els[i].disabled &&                      !els[i].hidden &&                      !els[i].readOnly &&                     els[i].type !== 'hidden') {                     rest.push(els[i]);                 }             }              // store the full tabbing order             this.form.tabOrder = ti.concat(rest);         }          // find the next element in the tabbing order and focus it         // if the last element of the form then blur         // (this can be changed to focus the next <form> if any)         for (var j = 0, jl = this.form.tabOrder.length; j < jl; j++) {             if (this === this.form.tabOrder[j]) {                 if (j+1 < jl) {                     $(this.form.tabOrder[j+1]).focus();                 } else {                     $(this).blur();                 }             }         }      }  }); 

See demo

like image 119
mVChr Avatar answered Dec 02 '22 05:12

mVChr


The default tabbing behavior is to just go to the next (in source order) form element so you could just iterate through all the elements you care about, find the one that has focus, and move the focus to the next one. We have the :input selector for finding the form elements so something like this:

var $all = $('form :input'); var focused = $(':focus')[0]; for(var i = 0; i < $all.length - 1; ++i) {     if($all[i] != focused)         continue;     $all[i + 1].focus();     break; } // Must have been focused on the last one or none of them. if(i == $all.length - 1)     $all[0].focus(); 

Demo: http://jsfiddle.net/ambiguous/Avugy/1/

Or you could set tabindex attributes and increment them with wrap-around:

var next_idx = parseInt($(':focus').attr('tabindex'), 10) + 1; var $next_input = $('form [tabindex=' + next_idx + ']'); if($next_input.length)     $next_input.focus(); else     $('form [tabindex]:first').focus(); 

Demo: http://jsfiddle.net/ambiguous/k9VpV/

Dealing with gaps in the tabindex attribute values is left as an exercise.

like image 24
mu is too short Avatar answered Dec 02 '22 07:12

mu is too short