2

I work entering data online to a form that I would like to change the tabbing order but have had no luck using Greasemonkey and Scriptish. I am able to remove tabindexes of -1 to make fields accessible in Scriptish. However, whenever I try to set the tabindex on a field, the field ends up being skipped when tabbing.

This works to remove tabindex:

var eth = document.getElementById('Ethnicities-111');
if (eth)
eth.removeAttribute('tabindex');

This makes a different text area field inaccessible:

var tb = document.getElementById('EybComments');
if (tb)
tb.setAttribute('tabindex' '1');
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Thank you! I was able to solve the problem by assigning a tabindex of 1 to the first focusable element and then assigning tabindexes to the other fields in the order I desired. – user5377002 Sep 30 '15 at 16:46
  • Great! Then [tick the check-mark next to the answer, below](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235). – Brock Adams Oct 01 '15 at 15:57

1 Answers1

0

See Sequential focus navigation and the tabindex attribute. If you alter tab orders keep the following points in mind:

  1. If tabindex is not set, then tab order flows naturally as described in the above spec.
  2. If 2 elements have the same tabindex, the natural order will be used when within that tabindex value (see the demo below).
  3. If the tabindex is negative, browsers normally won't allow that node to be tabbed to, but browsers don't have to honor this rule.
  4. If tabindex is removed, then the last used tab order may still apply (Firefox, etc.) rather than the natural order.
    See the demo below.

This means that it is not enough to removeAttribute('tabindex') -- especially if it was set to -1! You must set positive values and the positive values should make sense given the surrounding nodes and the desired taborder.

The following demo shows the effects of various types of tabindex changes.
Note especially how the "natural" order changes based on the previous tabindex values before they were cleared.

Press the "Run code snippet" button, below.

$("#startInp").focus ();

$("button").click ( function (zEvent) {
    $("#startInp")  .focus ();
    var targNodes   = $("td > label > input");
    targNodes.removeProp ("tabindex");
    $("#endInp")    .prop ("tabindex", "7")
                    .prev ("span").text ('Normal next in tab (ti=7)')
                    ;

    switch (zEvent.target.id) {
        case "btnUseNatural":
            targNodes.prev ("span").text ("tabindex not set");
            $("#endInp")    .prop ("tabindex", "2")
                            .prev ("span").text ('Normal next in tab (ti=2)')
                            ;
            break;

        case "btnUseSequential":
            targNodes.each ( function () {
                var jThis   = $(this);
                var tabIdx  = jThis.data ("tabidx");
                jThis.prop ("tabindex", tabIdx);
                jThis.prev ("span").text ('tabindex = ' + tabIdx);
            } );
            break;

        case "btnUseSawtooth":
            targNodes.each ( function () {
                var jThis       = $(this);
                var tabIdx      = jThis.data ("tabidx") + "";
                var newTabIdx   = 0;

                switch (tabIdx) {
                    case "1":   newTabIdx = 1;  break;
                    case "2":   newTabIdx = 3;  break;
                    case "3":   newTabIdx = 5;  break;
                    case "4":   newTabIdx = 2;  break;
                    case "5":   newTabIdx = 4;  break;
                    case "6":   newTabIdx = 6;  break;
                    case "-1":  newTabIdx = -1; break;
                }
                jThis.prop ("tabindex", newTabIdx);
                jThis.prev ("span").text ('tabindex = ' + newTabIdx);
            } );
            break;

        case "btnUseAllOnes":
        case "btnUseAllEights":
            var tabIdx      = zEvent.target.id == "btnUseAllOnes"  ?  "1"  :  "8";
            targNodes.prop ("tabindex", tabIdx);
            targNodes.prev ("span").text ('tabindex = ' + tabIdx);

            $('input[data-tabidx="-1"]').prop ("tabindex", "-1")
            .prev ("span").text ("tabindex = -1");
            ;
            break;
    }
} );
div   { margin: -2ex auto 2em auto; }
input { margin: auto 2em auto 0.5ex; }
label > span {
    width: 14ex;
    display: inline-block;
    text-align: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<h2>Set tab order to:</h2>
<div>
    <button id="btnUseNatural">Natural</button>
    <button id="btnUseSequential">Sequential</button>
    <button id="btnUseSawtooth">Sawtooth</button>
    <button id="btnUseAllOnes">All Ones</button>
    <button id="btnUseAllEights">All Eights</button>
</div>
<p> Tab around the following nodes to see the effect of tabindex changes.<br>
    <label>Start here  (ti=1):<input id="startInp" type="text" tabindex="1"></label>
</p>
<table>
    <tr>
        <td><label><span>tabindex not set</span>:<input data-tabidx="1" type="text"></label></td>
        <td><label><span>tabindex not set</span>:<input data-tabidx="2" type="text"></label></td>
        <td><label><span>tabindex not set</span>:<input data-tabidx="3" type="text"></label></td>
    </tr>
    <tr>
        <td><label><span>tabindex = -1</span>:<input data-tabidx="-1" tabindex="-1" type="text"></label></td>
        <td colspan="2"><=== Will almost always be skipped</td>
    </tr>
    <tr>
        <td><label><span>tabindex not set</span>:<input data-tabidx="4" type="text"></label></td>
        <td><label><span>tabindex not set</span>:<input data-tabidx="5" type="text"></label></td>
        <td><label><span>tabindex not set</span>:<input data-tabidx="6" type="text"></label></td>
    </tr>
</table>
<p>
    <label><span>Normal next in tab (ti=2)</span>:<input id="endInp" type="text" tabindex="2"></label>
</p>
Brock Adams
  • 90,639
  • 22
  • 233
  • 295