在选项卡索引中关注下一个元素

时间:2022-08-23 22:36:02

I am trying to move the focus to the next element in the tab sequence based upon the current element which has focus. Thus far I have not turned up anything in my searches.

我正在尝试将焦点移动到选项卡序列中的下一个元素,该元素基于具有焦点的当前元素。到目前为止,我还没有找到任何线索。

function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFocusIn 

    currentElementId = "";
    currentElement.nextElementByTabIndex.focus();
}

Of course the nextElementByTabIndex is the key part for this to work. How do I find the next element in the tab sequence? The solution would need to be based using JScript and not something like JQuery.

当然,nextElementByTabIndex是这个工作的关键部分。如何找到选项卡序列中的下一个元素?解决方案需要使用JScript而不是JQuery。

12 个解决方案

#1


16  

Without jquery: First of all, on your tab-able elements, add class="tabable" this will let us select them later.

没有jquery:首先,在可选项卡的元素上,添加class="tabable",这将让我们稍后选择它们。

var lastTabIndex = 10;
function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFOcusIn
    var curIndex = currentElement.tabIndex; //get current elements tab index
    if(curIndex == lastTabIndex) { //if we are on the last tabindex, go back to the beginning
        curIndex = 0;
    }
    var tabbables = document.querySelectorAll("tabable"); //get all tabable elements
    for(var i=0; i<tabbables.length; i++) { //loop through each element
        if(tabbables[i].tabIndex == (curIndex+1)) { //check the tabindex to see if it's the element we want
            tabbables[i].focus(); //if it's the one we want, focus it and exit the loop
            break;
        }
    }
}

#2


55  

I've never implemented this, but I've looked into a similar problem, and here's what I would try.

我从来没有实现过这个,但是我研究过一个类似的问题,以下是我要尝试的。

Try this first

First, I would see if you could simply fire a keypress event for the Tab key on the element that currently has focus. There may be a different way of doing this for different browsers.

首先,我将查看是否可以简单地为当前具有焦点的元素上的Tab键触发一个按键事件。对于不同的浏览器,可能有不同的方法来实现这一点。

If that doesn't work, you'll have to work harder…

Referencing the jQuery implementation, you must:

引用jQuery实现,您必须:

  1. Listen for Tab and Shift+Tab
  2. 听Tab和Shift+Tab
  3. Know which elements are tab-able
  4. 知道哪些元素是可制表的。
  5. Understand how tab order works
  6. 理解制表符顺序是如何工作的

1. Listen for Tab and Shift+Tab

Listening for Tab and Shift+Tab are probably well-covered elsewhere on the web, so I'll skip that part.

听Tab和Shift+Tab可能在web上的其他地方有很好的介绍,所以我将跳过这一部分。

2. Know which elements are tab-able

Knowing which elements are tab-able is trickier. Basically, an element is tab-able if it is focusable and does not have the attribute tabindex="-1" set. So then we must ask which elements are focusable. The following elements are focusable:

知道哪些元素是可制表的比较困难。基本上,如果一个元素是可调焦的,并且没有属性tabindex="-1"集,那么我们必须问哪些元素是可调焦的。以下要素是可聚焦的:

  • input, select, textarea, button, and object elements that aren't disabled.
  • 输入、选择、textarea、button和对象元素,这些都不是禁用的。
  • a and area elements that have an href or have a numerical value for tabindex set.
  • a和具有href或具有tabindex set数值的区域元素。
  • any element that has a numerical value for tabindex set.
  • 为tabindex集合具有数值的任何元素。

Furthermore, an element is focusable only if:

此外,只有当:

  • None of its ancestors are display: none.
  • 它的祖先没有出现过:没有。
  • The computed value of visibility is visible. This means that the nearest ancestor to have visibility set must have a value of visible. If no ancestor has visibility set, then the computed value is visible.
  • 可见性的计算值是可见的。这意味着具有可见集的最近的祖先必须具有可见值。如果没有祖先具有可见性集,则计算值是可见的。

More details are in another Stack Overflow answer.

更多细节在另一个堆栈溢出答案中。

3. Understand how tab order works

The tab order of elements in a document is controlled by the tabindex attribute. If no value is set, the tabindex is effectively 0.

文档中元素的选项卡顺序由tabindex属性控制。如果没有设置值,则tabindex实际上是0。

The tabindex order for the document is: 1, 2, 3, …, 0.

文档的列表顺序是:1、2、3、…、0。

Initially, when the body element (or no element) has focus, the first element in the tab order is the lowest non-zero tabindex. If multiple elements have the same tabindex, you then go in document order until you reach the last element with that tabindex. Then you move to the next lowest tabindex and the process continues. Finally, finish with those elements with a zero (or empty) tabindex.

最初,当body元素(或无元素)具有焦点时,制表符顺序中的第一个元素是最低的非零制表索引。如果多个元素有相同的表索引,那么您将按文档顺序执行,直到使用该tabindex到达最后一个元素。然后移动到下一个最低的tabindex,这个过程继续。最后,用一个0(或空)tabindex结束这些元素。

#3


20  

I created a simple jQuery plugin which does just this. It uses the ':tabbable' selector of jQuery UI to find the next 'tabbable' element and selects it.

我创建了一个简单的jQuery插件。它使用“:tabable”的jQuery UI选择器来查找下一个“可选项”元素并选择它。

Example usage:

使用示例:

// Simulate tab key when element is clicked 
$('.myElement').bind('click', function(event){
    $.tabNext();
    return false;
});

#4


16  

Here's something I build for this purpose:

以下是我为此而设计的东西:

        focusNextElement: function () {
            //add all elements we want to include in our selection
            var focussableElements = 'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])';
            if (document.activeElement && document.activeElement.form) {
                var focussable = Array.prototype.filter.call(document.activeElement.form.querySelectorAll(focussableElements),
                function (element) {
                    //check for visibility while always include the current activeElement 
                    return element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement
                });
                var index = focussable.indexOf(document.activeElement);
                if(index > -1) {
                   var nextElement = focussable[index + 1] || focussable[0];
                   nextElement.focus();
                }                    
            }
        }

Features:

  • configurable set of focusable elements
  • 可调焦元素的可配置集合
  • no jQuery needed
  • 不需要jQuery
  • works in all modern browsers
  • 适用于所有现代浏览器。
  • fast & lightweight
  • 快速和轻量级

#5


6  

The core of the answer lies on finding the next element:

答案的核心在于找到下一个元素:

  function findNextTabStop(el) {
    var universe = document.querySelectorAll('input, button, select, textarea, a[href]');
    var list = Array.prototype.filter.call(universe, function(item) {return item.tabIndex >= "0"});
    var index = list.indexOf(el);
    return list[index + 1] || list[0];
  }

Usage:

用法:

var nextEl = findNextTabStop(element);
nextEl.focus();

Notice I don't care about prioritizing tabIndex.

注意,我不关心表索引的优先级。

#6


2  

As mentioned in a comment above, I don't think that any browsers expose tab order information. Here a simplified approximation of what the browser does to get the next element in tab order:

正如上面的评论所提到的,我认为任何浏览器都不会公开标签顺序信息。这里有一个简化的浏览器的近似值,以获得下一个元素的标签顺序:

var allowedTags = {input: true, textarea: true, button: true};

var walker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_ELEMENT,
  {
    acceptNode: function(node)
    {
      if (node.localName in allowedTags)
        return NodeFilter.FILTER_ACCEPT;
      else
        NodeFilter.FILTER_SKIP;
    }
  },
  false
);
walker.currentNode = currentElement;
if (!walker.nextNode())
{
  // Restart search from the start of the document
  walker.currentNode = walker.root;
  walker.nextNode();
}
if (walker.currentNode && walker.currentNode != walker.root)
  walker.currentNode.focus();

This only considers some tags and ignores tabindex attribute but might be enough depending on what you are trying to achieve.

这只考虑了一些标记,并忽略了tabindex属性,但这可能取决于您要实现的目标。

#7


1  

It seems that you can check the tabIndex property of an element to determine if it is focusable. An element that is not focusable has a tabindex of "-1".

似乎您可以检查元素的tabIndex属性,以确定它是否可调焦。不可调焦的元素的表索引为“-1”。

Then you just need to know the rules for tab stops:

然后你只需要知道标签停止的规则:

  • tabIndex="1" has the highest priorty.
  • tabIndex="1"具有最高的优先级。
  • tabIndex="2" has the next highest priority.
  • tabIndex="2"具有下一个最高的优先级。
  • tabIndex="3" is next, and so on.
  • 下一个是tabIndex="3",依此类推。
  • tabIndex="0" (or tabbable by default) has the lowest priority.
  • tabIndex="0"(默认情况下可制表)具有最低的优先级。
  • tabIndex="-1" (or not tabbable by default) does not act as a tab stop.
  • tabIndex="-1"(默认情况下不能制表)不充当制表符停止。
  • For two elements that have the same tabIndex, the one that appears first in the DOM has the higher priority.
  • 对于具有相同tabIndex的两个元素,最先出现在DOM中的元素具有更高的优先级。

Here is an example of how to build the list of tab stops, in sequence, using pure Javascript:

下面是一个如何使用纯Javascript按顺序构建选项卡停止列表的示例:

function getTabStops(o, a, el) {
    // Check if this element is a tab stop
    if (el.tabIndex > 0) {
        if (o[el.tabIndex]) {
            o[el.tabIndex].push(el);
        } else {
            o[el.tabIndex] = [el];
        }
    } else if (el.tabIndex === 0) {
        // Tab index "0" comes last so we accumulate it seperately
        a.push(el);
    }
    // Check if children are tab stops
    for (var i = 0, l = el.children.length; i < l; i++) {
        getTabStops(o, a, el.children[i]);
    }
}

var o = [],
    a = [],
    stops = [],
    active = document.activeElement;

getTabStops(o, a, document.body);

// Use simple loops for maximum browser support
for (var i = 0, l = o.length; i < l; i++) {
    if (o[i]) {
        for (var j = 0, m = o[i].length; j < m; j++) {
            stops.push(o[i][j]);
        }
    }
}
for (var i = 0, l = a.length; i < l; i++) {
    stops.push(a[i]);
}

We first walk the DOM, collecting up all tab stops in sequence with their index. We then assemble the final list. Notice that we add the items with tabIndex="0" at the very end of the list, after the items with a tabIndex of 1, 2, 3, etc.

我们首先遍历DOM,用索引按顺序收集所有选项卡停止。然后我们组装最后的列表。注意,我们在列表的末尾添加了tabIndex="0"的项,在表索引为1、2、3等的项之后。

For a fully working example, where you can tab around using the "enter" key, check out this fiddle.

对于一个完全工作的示例,您可以使用“enter”键进行切换,请查看这个小提琴。

#8


0  

Did you specify your own tabIndex values for each element you want to cycle through? if so, you can try this:

您是否为要循环的每个元素指定了自己的表索引值?如果有,你可以试试:

var lasTabIndex = 10; //Set this to the highest tabIndex you have
function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFocusIn 

    var curIndex = $(currentElement).attr('tabindex'); //get the tab index of the current element
    if(curIndex == lastTabIndex) { //if we are on the last tabindex, go back to the beginning
        curIndex = 0;
    }
    $('[tabindex=' + (curIndex + 1) + ']').focus(); //set focus on the element that has a tab index one greater than the current tab index
}

You are using jquery, right?

您正在使用jquery,对吗?

#9


0  

Hope this is helpful.

希望这是有帮助的。

<input size="2" tabindex="1" id="one"
  maxlength="2" onkeyup="toUnicode(this)" />

<input size="2" tabindex="2" id="two"
  maxlength="2" onkeyup="toUnicode(this)" />

<input size="2" tabindex="3" id="three"
 maxlength="2" onkeyup="toUnicode(this)" />

then use simple javascript

然后使用简单的javascript

function toUnicode(elmnt)
{
  var next;
 if (elmnt.value.length==elmnt.maxLength)
{
next=elmnt.tabIndex + 1;
//look for the fields with the next tabIndex
var f = elmnt.form;
for (var i = 0; i < f.elements.length; i++)
{
  if (next<=f.elements[i].tabIndex)
  {
    f.elements[i].focus();
    break;
    }
   }
  }
}

#10


0  

Tabbable is a small JS package that gives you a list of all tabbable elements in tab order. So you could find your element within that list, then focus on the next list entry.

tabatable是一个小JS包,它按tab的顺序为您提供所有可制表元素的列表。所以你可以在列表中找到你的元素,然后关注下一个列表条目。

The package correctly handles the complicated edge cases mentioned in other answers (e.g., no ancestor can be display: none). And it doesn't depend on jQuery!

该包正确地处理其他答案中提到的复杂的边缘情况(例如,不能显示任何祖先:none)。它不依赖于jQuery!

As of this writing (version 1.1.1), it has the caveats that it doesn't support IE8, and that browser bugs prevent it from handling contenteditable correctly.

在撰写本文时(1.1.1版),它有一个注意事项:它不支持IE8,浏览器bug阻止它正确地处理contenteditable。

#11


0  

This is my first post on SO, so I don't have enough reputation to comment the accepted answer, but I had to modify the code to the following:

这是我在SO上的第一个帖子,所以我没有足够的声誉去评论已经被接受的答案,但是我不得不修改代码如下:

export function focusNextElement () {
  //add all elements we want to include in our selection
  const focussableElements = 
    'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled])'
  if (document.activeElement && document.activeElement.form) {
      var focussable = Array.prototype.filter.call(
        document.activeElement.form.querySelectorAll(focussableElements),
      function (element) {
          // if element has tabindex = -1, it is not focussable
          if ( element.hasAttribute('tabindex') && element.tabIndex === -1 ){
            return false
          }
          //check for visibility while always include the current activeElement 
          return (element.offsetWidth > 0 || element.offsetHeight > 0 || 
            element === document.activeElement)
      });
      console.log(focussable)
      var index = focussable.indexOf(document.activeElement);
      if(index > -1) {
         var nextElement = focussable[index + 1] || focussable[0];
         console.log(nextElement)
         nextElement.focus()
      }                    
  }
}

The changing of var to constant is non-critical. The main change is that we get rid of the selector that checks tabindex != "-1". Then later, if the element has the attribute tabindex AND it is set to "-1", we do NOT consider it focussable.

var对常数的变化是非临界的。主要的变化是我们去掉了检查tabindex != "-1"的选择器。然后,如果元素具有属性tabindex并将其设置为“-1”,我们就不认为它是集中的。

The reason I needed to change this was because when adding tabindex="-1" to an <input>, this element was still considered focussable because it matches the "input[type=text]:not([disabled])" selector. My change is equivalent to "if we are a non-disabled text input, and we have a tabIndex attribute, and the value of that attribute is -1, then we should not be considered focussable.

我需要更改它的原因是,当向添加tabindex="-1"时,这个元素仍然被认为是focussable,因为它与"input[type=text]:not([disabled])"选择器相匹配。我的更改等价于“如果我们是一个非禁用的文本输入,并且我们有一个tabIndex属性,并且该属性的值为-1,那么我们就不应该被认为是集中的。

I believe that when the author of the accepted answer edited their answer to account for the tabIndex attribute, they did not do so correctly. Please let me know if this is not the case

我认为,当被接受的答案的作者编辑他们的答案以解释tabIndex属性时,他们做得并不正确。如果情况不是这样,请告诉我。

#12


0  

Here is a more complete version of focusing on the next element. It follows the spec guidelines and sorts the list of elements correctly by using tabindex. Also a reverse variable is defined if you want to get the previous element.

这里有一个更完整的版本,关注下一个元素。它遵循spec指南,并通过使用tabindex对元素列表进行正确排序。如果您想要获得前面的元素,还可以定义一个反向变量。

function focusNextElement( reverse, activeElem ) {
  /*check if an element is defined or use activeElement*/
  activeElem = activeElem instanceof HTMLElement ? activeElem : document.activeElement;

  let queryString = [
      'a:not([disabled]):not([tabindex="-1"])',
      'button:not([disabled]):not([tabindex="-1"])',
      'input:not([disabled]):not([tabindex="-1"])',
      'select:not([disabled]):not([tabindex="-1"])',
      '[tabindex]:not([disabled]):not([tabindex="-1"])'
      /* add custom queries here */
    ].join(','),
    queryResult = Array.prototype.filter.call(document.querySelectorAll(queryString), elem => {
      /*check for visibility while always include the current activeElement*/
      return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem === activeElem;
    }),
    indexedList = queryResult.slice().filter(elem => {
      /* filter out all indexes not greater than 0 */
      return elem.tabIndex == 0 || elem.tabIndex == -1 ? false : true;
    }).sort((a, b) => {
      /* sort the array by index from smallest to largest */
      return a.tabIndex != 0 && b.tabIndex != 0 
        ? (a.tabIndex < b.tabIndex ? -1 : b.tabIndex < a.tabIndex ? 1 : 0) 
        : a.tabIndex != 0 ? -1 : b.tabIndex != 0 ? 1 : 0;
    }),
    focusable = [].concat(indexedList, queryResult.filter(elem => {
      /* filter out all indexes above 0 */
      return elem.tabIndex == 0 || elem.tabIndex == -1 ? true : false;
    }));

  /* if reverse is true return the previous focusable element
     if reverse is false return the next focusable element */
  return reverse ? (focusable[focusable.indexOf(activeElem) - 1] || focusable[focusable.length - 1]) 
    : (focusable[focusable.indexOf(activeElem) + 1] || focusable[0]);
}

#1


16  

Without jquery: First of all, on your tab-able elements, add class="tabable" this will let us select them later.

没有jquery:首先,在可选项卡的元素上,添加class="tabable",这将让我们稍后选择它们。

var lastTabIndex = 10;
function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFOcusIn
    var curIndex = currentElement.tabIndex; //get current elements tab index
    if(curIndex == lastTabIndex) { //if we are on the last tabindex, go back to the beginning
        curIndex = 0;
    }
    var tabbables = document.querySelectorAll("tabable"); //get all tabable elements
    for(var i=0; i<tabbables.length; i++) { //loop through each element
        if(tabbables[i].tabIndex == (curIndex+1)) { //check the tabindex to see if it's the element we want
            tabbables[i].focus(); //if it's the one we want, focus it and exit the loop
            break;
        }
    }
}

#2


55  

I've never implemented this, but I've looked into a similar problem, and here's what I would try.

我从来没有实现过这个,但是我研究过一个类似的问题,以下是我要尝试的。

Try this first

First, I would see if you could simply fire a keypress event for the Tab key on the element that currently has focus. There may be a different way of doing this for different browsers.

首先,我将查看是否可以简单地为当前具有焦点的元素上的Tab键触发一个按键事件。对于不同的浏览器,可能有不同的方法来实现这一点。

If that doesn't work, you'll have to work harder…

Referencing the jQuery implementation, you must:

引用jQuery实现,您必须:

  1. Listen for Tab and Shift+Tab
  2. 听Tab和Shift+Tab
  3. Know which elements are tab-able
  4. 知道哪些元素是可制表的。
  5. Understand how tab order works
  6. 理解制表符顺序是如何工作的

1. Listen for Tab and Shift+Tab

Listening for Tab and Shift+Tab are probably well-covered elsewhere on the web, so I'll skip that part.

听Tab和Shift+Tab可能在web上的其他地方有很好的介绍,所以我将跳过这一部分。

2. Know which elements are tab-able

Knowing which elements are tab-able is trickier. Basically, an element is tab-able if it is focusable and does not have the attribute tabindex="-1" set. So then we must ask which elements are focusable. The following elements are focusable:

知道哪些元素是可制表的比较困难。基本上,如果一个元素是可调焦的,并且没有属性tabindex="-1"集,那么我们必须问哪些元素是可调焦的。以下要素是可聚焦的:

  • input, select, textarea, button, and object elements that aren't disabled.
  • 输入、选择、textarea、button和对象元素,这些都不是禁用的。
  • a and area elements that have an href or have a numerical value for tabindex set.
  • a和具有href或具有tabindex set数值的区域元素。
  • any element that has a numerical value for tabindex set.
  • 为tabindex集合具有数值的任何元素。

Furthermore, an element is focusable only if:

此外,只有当:

  • None of its ancestors are display: none.
  • 它的祖先没有出现过:没有。
  • The computed value of visibility is visible. This means that the nearest ancestor to have visibility set must have a value of visible. If no ancestor has visibility set, then the computed value is visible.
  • 可见性的计算值是可见的。这意味着具有可见集的最近的祖先必须具有可见值。如果没有祖先具有可见性集,则计算值是可见的。

More details are in another Stack Overflow answer.

更多细节在另一个堆栈溢出答案中。

3. Understand how tab order works

The tab order of elements in a document is controlled by the tabindex attribute. If no value is set, the tabindex is effectively 0.

文档中元素的选项卡顺序由tabindex属性控制。如果没有设置值,则tabindex实际上是0。

The tabindex order for the document is: 1, 2, 3, …, 0.

文档的列表顺序是:1、2、3、…、0。

Initially, when the body element (or no element) has focus, the first element in the tab order is the lowest non-zero tabindex. If multiple elements have the same tabindex, you then go in document order until you reach the last element with that tabindex. Then you move to the next lowest tabindex and the process continues. Finally, finish with those elements with a zero (or empty) tabindex.

最初,当body元素(或无元素)具有焦点时,制表符顺序中的第一个元素是最低的非零制表索引。如果多个元素有相同的表索引,那么您将按文档顺序执行,直到使用该tabindex到达最后一个元素。然后移动到下一个最低的tabindex,这个过程继续。最后,用一个0(或空)tabindex结束这些元素。

#3


20  

I created a simple jQuery plugin which does just this. It uses the ':tabbable' selector of jQuery UI to find the next 'tabbable' element and selects it.

我创建了一个简单的jQuery插件。它使用“:tabable”的jQuery UI选择器来查找下一个“可选项”元素并选择它。

Example usage:

使用示例:

// Simulate tab key when element is clicked 
$('.myElement').bind('click', function(event){
    $.tabNext();
    return false;
});

#4


16  

Here's something I build for this purpose:

以下是我为此而设计的东西:

        focusNextElement: function () {
            //add all elements we want to include in our selection
            var focussableElements = 'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])';
            if (document.activeElement && document.activeElement.form) {
                var focussable = Array.prototype.filter.call(document.activeElement.form.querySelectorAll(focussableElements),
                function (element) {
                    //check for visibility while always include the current activeElement 
                    return element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement
                });
                var index = focussable.indexOf(document.activeElement);
                if(index > -1) {
                   var nextElement = focussable[index + 1] || focussable[0];
                   nextElement.focus();
                }                    
            }
        }

Features:

  • configurable set of focusable elements
  • 可调焦元素的可配置集合
  • no jQuery needed
  • 不需要jQuery
  • works in all modern browsers
  • 适用于所有现代浏览器。
  • fast & lightweight
  • 快速和轻量级

#5


6  

The core of the answer lies on finding the next element:

答案的核心在于找到下一个元素:

  function findNextTabStop(el) {
    var universe = document.querySelectorAll('input, button, select, textarea, a[href]');
    var list = Array.prototype.filter.call(universe, function(item) {return item.tabIndex >= "0"});
    var index = list.indexOf(el);
    return list[index + 1] || list[0];
  }

Usage:

用法:

var nextEl = findNextTabStop(element);
nextEl.focus();

Notice I don't care about prioritizing tabIndex.

注意,我不关心表索引的优先级。

#6


2  

As mentioned in a comment above, I don't think that any browsers expose tab order information. Here a simplified approximation of what the browser does to get the next element in tab order:

正如上面的评论所提到的,我认为任何浏览器都不会公开标签顺序信息。这里有一个简化的浏览器的近似值,以获得下一个元素的标签顺序:

var allowedTags = {input: true, textarea: true, button: true};

var walker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_ELEMENT,
  {
    acceptNode: function(node)
    {
      if (node.localName in allowedTags)
        return NodeFilter.FILTER_ACCEPT;
      else
        NodeFilter.FILTER_SKIP;
    }
  },
  false
);
walker.currentNode = currentElement;
if (!walker.nextNode())
{
  // Restart search from the start of the document
  walker.currentNode = walker.root;
  walker.nextNode();
}
if (walker.currentNode && walker.currentNode != walker.root)
  walker.currentNode.focus();

This only considers some tags and ignores tabindex attribute but might be enough depending on what you are trying to achieve.

这只考虑了一些标记,并忽略了tabindex属性,但这可能取决于您要实现的目标。

#7


1  

It seems that you can check the tabIndex property of an element to determine if it is focusable. An element that is not focusable has a tabindex of "-1".

似乎您可以检查元素的tabIndex属性,以确定它是否可调焦。不可调焦的元素的表索引为“-1”。

Then you just need to know the rules for tab stops:

然后你只需要知道标签停止的规则:

  • tabIndex="1" has the highest priorty.
  • tabIndex="1"具有最高的优先级。
  • tabIndex="2" has the next highest priority.
  • tabIndex="2"具有下一个最高的优先级。
  • tabIndex="3" is next, and so on.
  • 下一个是tabIndex="3",依此类推。
  • tabIndex="0" (or tabbable by default) has the lowest priority.
  • tabIndex="0"(默认情况下可制表)具有最低的优先级。
  • tabIndex="-1" (or not tabbable by default) does not act as a tab stop.
  • tabIndex="-1"(默认情况下不能制表)不充当制表符停止。
  • For two elements that have the same tabIndex, the one that appears first in the DOM has the higher priority.
  • 对于具有相同tabIndex的两个元素,最先出现在DOM中的元素具有更高的优先级。

Here is an example of how to build the list of tab stops, in sequence, using pure Javascript:

下面是一个如何使用纯Javascript按顺序构建选项卡停止列表的示例:

function getTabStops(o, a, el) {
    // Check if this element is a tab stop
    if (el.tabIndex > 0) {
        if (o[el.tabIndex]) {
            o[el.tabIndex].push(el);
        } else {
            o[el.tabIndex] = [el];
        }
    } else if (el.tabIndex === 0) {
        // Tab index "0" comes last so we accumulate it seperately
        a.push(el);
    }
    // Check if children are tab stops
    for (var i = 0, l = el.children.length; i < l; i++) {
        getTabStops(o, a, el.children[i]);
    }
}

var o = [],
    a = [],
    stops = [],
    active = document.activeElement;

getTabStops(o, a, document.body);

// Use simple loops for maximum browser support
for (var i = 0, l = o.length; i < l; i++) {
    if (o[i]) {
        for (var j = 0, m = o[i].length; j < m; j++) {
            stops.push(o[i][j]);
        }
    }
}
for (var i = 0, l = a.length; i < l; i++) {
    stops.push(a[i]);
}

We first walk the DOM, collecting up all tab stops in sequence with their index. We then assemble the final list. Notice that we add the items with tabIndex="0" at the very end of the list, after the items with a tabIndex of 1, 2, 3, etc.

我们首先遍历DOM,用索引按顺序收集所有选项卡停止。然后我们组装最后的列表。注意,我们在列表的末尾添加了tabIndex="0"的项,在表索引为1、2、3等的项之后。

For a fully working example, where you can tab around using the "enter" key, check out this fiddle.

对于一个完全工作的示例,您可以使用“enter”键进行切换,请查看这个小提琴。

#8


0  

Did you specify your own tabIndex values for each element you want to cycle through? if so, you can try this:

您是否为要循环的每个元素指定了自己的表索引值?如果有,你可以试试:

var lasTabIndex = 10; //Set this to the highest tabIndex you have
function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFocusIn 

    var curIndex = $(currentElement).attr('tabindex'); //get the tab index of the current element
    if(curIndex == lastTabIndex) { //if we are on the last tabindex, go back to the beginning
        curIndex = 0;
    }
    $('[tabindex=' + (curIndex + 1) + ']').focus(); //set focus on the element that has a tab index one greater than the current tab index
}

You are using jquery, right?

您正在使用jquery,对吗?

#9


0  

Hope this is helpful.

希望这是有帮助的。

<input size="2" tabindex="1" id="one"
  maxlength="2" onkeyup="toUnicode(this)" />

<input size="2" tabindex="2" id="two"
  maxlength="2" onkeyup="toUnicode(this)" />

<input size="2" tabindex="3" id="three"
 maxlength="2" onkeyup="toUnicode(this)" />

then use simple javascript

然后使用简单的javascript

function toUnicode(elmnt)
{
  var next;
 if (elmnt.value.length==elmnt.maxLength)
{
next=elmnt.tabIndex + 1;
//look for the fields with the next tabIndex
var f = elmnt.form;
for (var i = 0; i < f.elements.length; i++)
{
  if (next<=f.elements[i].tabIndex)
  {
    f.elements[i].focus();
    break;
    }
   }
  }
}

#10


0  

Tabbable is a small JS package that gives you a list of all tabbable elements in tab order. So you could find your element within that list, then focus on the next list entry.

tabatable是一个小JS包,它按tab的顺序为您提供所有可制表元素的列表。所以你可以在列表中找到你的元素,然后关注下一个列表条目。

The package correctly handles the complicated edge cases mentioned in other answers (e.g., no ancestor can be display: none). And it doesn't depend on jQuery!

该包正确地处理其他答案中提到的复杂的边缘情况(例如,不能显示任何祖先:none)。它不依赖于jQuery!

As of this writing (version 1.1.1), it has the caveats that it doesn't support IE8, and that browser bugs prevent it from handling contenteditable correctly.

在撰写本文时(1.1.1版),它有一个注意事项:它不支持IE8,浏览器bug阻止它正确地处理contenteditable。

#11


0  

This is my first post on SO, so I don't have enough reputation to comment the accepted answer, but I had to modify the code to the following:

这是我在SO上的第一个帖子,所以我没有足够的声誉去评论已经被接受的答案,但是我不得不修改代码如下:

export function focusNextElement () {
  //add all elements we want to include in our selection
  const focussableElements = 
    'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled])'
  if (document.activeElement && document.activeElement.form) {
      var focussable = Array.prototype.filter.call(
        document.activeElement.form.querySelectorAll(focussableElements),
      function (element) {
          // if element has tabindex = -1, it is not focussable
          if ( element.hasAttribute('tabindex') && element.tabIndex === -1 ){
            return false
          }
          //check for visibility while always include the current activeElement 
          return (element.offsetWidth > 0 || element.offsetHeight > 0 || 
            element === document.activeElement)
      });
      console.log(focussable)
      var index = focussable.indexOf(document.activeElement);
      if(index > -1) {
         var nextElement = focussable[index + 1] || focussable[0];
         console.log(nextElement)
         nextElement.focus()
      }                    
  }
}

The changing of var to constant is non-critical. The main change is that we get rid of the selector that checks tabindex != "-1". Then later, if the element has the attribute tabindex AND it is set to "-1", we do NOT consider it focussable.

var对常数的变化是非临界的。主要的变化是我们去掉了检查tabindex != "-1"的选择器。然后,如果元素具有属性tabindex并将其设置为“-1”,我们就不认为它是集中的。

The reason I needed to change this was because when adding tabindex="-1" to an <input>, this element was still considered focussable because it matches the "input[type=text]:not([disabled])" selector. My change is equivalent to "if we are a non-disabled text input, and we have a tabIndex attribute, and the value of that attribute is -1, then we should not be considered focussable.

我需要更改它的原因是,当向添加tabindex="-1"时,这个元素仍然被认为是focussable,因为它与"input[type=text]:not([disabled])"选择器相匹配。我的更改等价于“如果我们是一个非禁用的文本输入,并且我们有一个tabIndex属性,并且该属性的值为-1,那么我们就不应该被认为是集中的。

I believe that when the author of the accepted answer edited their answer to account for the tabIndex attribute, they did not do so correctly. Please let me know if this is not the case

我认为,当被接受的答案的作者编辑他们的答案以解释tabIndex属性时,他们做得并不正确。如果情况不是这样,请告诉我。

#12


0  

Here is a more complete version of focusing on the next element. It follows the spec guidelines and sorts the list of elements correctly by using tabindex. Also a reverse variable is defined if you want to get the previous element.

这里有一个更完整的版本,关注下一个元素。它遵循spec指南,并通过使用tabindex对元素列表进行正确排序。如果您想要获得前面的元素,还可以定义一个反向变量。

function focusNextElement( reverse, activeElem ) {
  /*check if an element is defined or use activeElement*/
  activeElem = activeElem instanceof HTMLElement ? activeElem : document.activeElement;

  let queryString = [
      'a:not([disabled]):not([tabindex="-1"])',
      'button:not([disabled]):not([tabindex="-1"])',
      'input:not([disabled]):not([tabindex="-1"])',
      'select:not([disabled]):not([tabindex="-1"])',
      '[tabindex]:not([disabled]):not([tabindex="-1"])'
      /* add custom queries here */
    ].join(','),
    queryResult = Array.prototype.filter.call(document.querySelectorAll(queryString), elem => {
      /*check for visibility while always include the current activeElement*/
      return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem === activeElem;
    }),
    indexedList = queryResult.slice().filter(elem => {
      /* filter out all indexes not greater than 0 */
      return elem.tabIndex == 0 || elem.tabIndex == -1 ? false : true;
    }).sort((a, b) => {
      /* sort the array by index from smallest to largest */
      return a.tabIndex != 0 && b.tabIndex != 0 
        ? (a.tabIndex < b.tabIndex ? -1 : b.tabIndex < a.tabIndex ? 1 : 0) 
        : a.tabIndex != 0 ? -1 : b.tabIndex != 0 ? 1 : 0;
    }),
    focusable = [].concat(indexedList, queryResult.filter(elem => {
      /* filter out all indexes above 0 */
      return elem.tabIndex == 0 || elem.tabIndex == -1 ? true : false;
    }));

  /* if reverse is true return the previous focusable element
     if reverse is false return the next focusable element */
  return reverse ? (focusable[focusable.indexOf(activeElem) - 1] || focusable[focusable.length - 1]) 
    : (focusable[focusable.indexOf(activeElem) + 1] || focusable[0]);
}