Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This directive helps provide dynamic tab sequences on the client. All it needs is a set of so called 'design' values on DOM nodes inside your document (<input ... svysablo-tabseq="2" ...) and an optional config attribute (<div ... svysablo-tabseq-config:{container: true} ...).

Based on only these two things that you can add to a new custom component as needed, the svysablo-tabseq directive will generate and dynamically manage the "tabIndex" attributes for all the DOM elements displayed in the browser that use this directive.

Note
titleIMPORTANT

One must always have in the DOM structure a top-most svysablo-tabseq element marked with

Code Block
languagexml
<someTag ... svysablo-tabseq="1" svysablo-tabseq-config="{root: true}"/>

. This can be for example the <body> tag.

Note
titleIMPORTANT

svysablo-tabseq requires you to include a full jQuery lib in your page, before angular.js. It will not work with angular shipped jQLite only (because it relies on jquery trigger() which is not available in jQLite). Servoy already does this, so this note is only relevant for sablo users.

...

Code Block
languagexml
<!DOCTYPE html>
<html ng-app="myApp" svysablo-tabseq="1" svysablo-tabseq-config="{root: true}">

  <head>
    <title>Tabseq</title>
    <link href="css/style.css" rel="stylesheet" />
    <script src="../lib/jquery-1.11.1.js"></script>
    <script src="../lib/angular-1.3.0-beta.2/angular.js"></script>
    <script src="controllers/impl.js"></script>
  </head>

  <body ng-controller="myController">
        <mycustomcomponent svysablo-tabseq="model1.tabSeq"></mycustomcomponent>
        <div svysablo-tabseq="20" svysablo-tabseq-config="{container: true, reservedGap: 50}">
            <input svysablo-tabseq="1" value="a"/>
            <input svysablo-tabseq="-2" value="b"/>
            <input svysablo-tabseq="1" value="c"/>
        </div>
        <mycustomcomponent svysablo-tabseq="model2.tabSeq"></mycustomcomponent>
  </body>

</html>

...

Code Block
languagexml
        <mycustomcomponent svysablo-tabseq="model1.tabSeq" tabIndex='53'></mycustomcomponent>
        <div svysablo-tabseq="20" svysablo-tabseq-config="{container: true, reservedGap: 50}">
            <input svysablo-tabseq="1" value="a" tabIndex='2'/>
            <input svysablo-tabseq="-2" value="b" tabIndex='-1'/>
            <input svysablo-tabseq="1" value="c" tabIndex='2'/>
        </div>
        <mycustomcomponent svysablo-tabseq="model2.tabSeq" tabIndex='1'></mycustomcomponent>

Notice that I intentionally used 10, 20, 30 as 'design' tab indexes for the 2 custom components and the parent div of the inputs. This is just to show that only their order matters, as at runtime the real tabIndex that is generated by svysablo-tabseq directive and used by the browser will start from 1 and increase accordingly.

Also notice that "-2" is a special 'design' value that means 'this tag should be skipped completely by tab sequence'. It will always generate a "tabIndex='-1'" for that DOM element and for any child DOM elements that it might have using svysablo-tabseq directive.

"0" is a special 'design' value as well and it means 'this tag should use default tab sequence'. It will remove "tabIndex" attributes for that DOM element and for any child DOM elements that it might have using svysablo-tabseq directive.

Duplicate 'design' tab indexes on the same level are permitted and will generate duplicate tabIndex attribute values (it lets the browser decide which one gets focus first).

Another thing to notice is the div's configuration as tab sequence container (svysablo-tabseq-config="{container: true, reservedGap: 50}). This means that child DOM elements of that div are considered to be traversed by tab sequence at the 'design' tab index value of that div/container. So at runtime all child DOM elements of that div will get a tabIndex value that sets them between the parent div's siblings, according to the 'design' tab index value of the parent and it's siblings. Also notice the child 'design' values are not related to the ones on the container level. They only logically make sense as compared to the ones on the same level - in this case the 'input' siblings.

About 'reservedGap': it is an optional configuration option; it will work without it as well. It tells svysablo-tabseq that it should 'reserve' a number of tabIndexes for that container on top of the ones it currently needs. That can help later on, if more elements are added to that container and it needs more tabIndexes assigned - it can just use them without recalculating the tabIndexes of the parents (so less calculations to be done in the browser) - at least for a while, until it runs out of reserved indexes.

...

Code Block
languagexml
        <mycustomcomponent svysablo-tabseq="model1.tabSeq" tabIndex='53'></mycustomcomponent>
        <div svysablo-tabseq="20" svysablo-tabseq-config="{container: true, reservedGap: 50}">
            <input svysablo-tabseq="1" value="a" tabIndex='3'/>
            <input svysablo-tabseq="-2" value="b" tabIndex='-1'/>
            <input svysablo-tabseq="1" value="c" tabIndex='3'/>
            <input svysablo-tabseq="0" value="new1" tabIndex='2'/>
            <input svysablo-tabseq="2" value="new2" tabIndex='4'/>
            <input svysablo-tabseq="3" value="new3" tabIndex='5'/>
              (...)
            <input svysablo-tabseq="10" value="new10" tabIndex='12'/>
         </div>
        <mycustomcomponent svysablo-tabseq="model2.tabSeq" tabIndex='1'></mycustomcomponent>

...

Code Block
languagexml
        <mycustomcomponent svysablo-tabseq="model1.tabSeq" tabIndex='143'></mycustomcomponent>
        <div svysablo-tabseq="20" svysablo-tabseq-config="{container: true, reservedGap: 50}">
            <input svysablo-tabseq="1" value="a" tabIndex='3'/>
            <input svysablo-tabseq="-2" value="b" tabIndex='-1'/>
            <input svysablo-tabseq="1" value="c" tabIndex='3'/>
            <input svysablo-tabseq="0" value="new1" tabIndex='2'/>
            <input svysablo-tabseq="2" value="new2" tabIndex='4'/>
            <input svysablo-tabseq="3" value="new3" tabIndex='5'/>
              (...)
            <input svysablo-tabseq="90" value="new90" tabIndex='92'/>
         </div>
        <mycustomcomponent svysablo-tabseq="model2.tabSeq" tabIndex='1'></mycustomcomponent>