关注下一个元素在Tab索引中
我正在尝试将焦点移动到基于当前具有焦点的元素的选项卡序列中的下一个元素。 到目前为止,我还没有发现任何东西在我的search。
function OnFocusOut() { var currentElement = $get(currentElementId); // ID set by OnFocusIn currentElementId = ""; currentElement.nextElementByTabIndex.focus(); }
当然nextElementByTabIndex是这个工作的关键部分。 如何find选项卡序列中的下一个元素? 解决scheme需要使用JScript而不是像JQuery。
没有jquery:首先,在你的tab-able元素上,添加class="tabable"
这会让我们稍后select它们。
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; } } }
我从来没有实现过,但我已经看到了类似的问题,这就是我会尝试。
先试试这个
首先,我会看看你是否可以简单地触发当前有焦点的元素上的Tab键的keypress
事件 。 对于不同的浏览器可能有不同的方法。
如果这样做不行,你就得努力工作。
引用jQuery的实现,你必须:
- 听取Tab和Shift + Tab
- 知道哪些元素是可选的
- 了解标签顺序如何工作
1.听取Tab和Shift + Tab
听取Tab和Shift + Tab可能在networking上的其他地方被很好地覆盖,所以我会跳过这一部分。
2.知道哪些元素是可选的
知道哪些元素是制表符是棘手的。 基本上,如果一个元素是可聚焦的,并且没有设置属性tabindex="-1"
,那么这个元素是可选项。 那么我们必须问哪些元素是可以聚焦的。 以下内容是可重点的:
-
input
,select
,textarea
,button
和没有被禁用的object
元素。 -
a
和具有href
或具有用于tabindex
设置的数字值的area
元素。 - 任何具有
tabindex
设置数值的元素。
此外,一个元素只有在以下情况下才可以对焦:
- 没有祖先
display: none
。 - 计算出的
visibility
值是visible
。 这意味着最近的具有visibility
集合的祖先必须具有visibility
的值。 如果没有祖先的visibility
设置,那么计算的值是visible
。
更多的细节在另一个堆栈溢出的答案 。
3.了解标签顺序如何工作
文档中元素的Tab顺序由tabindex
属性控制。 如果没有设置值, tabindex
实际上是0
。
该文档的tabindex
顺序是:1,2,3,…,0。
最初,当body
元素(或没有元素)具有焦点时,tab键顺序中的第一个元素是最低的非零tabindex
。 如果多个元素具有相同的tabindex
, tabindex
文档顺序进行操作,直到到达具有该tabindex
的最后一个元素。 然后你移到下一个最低的tabindex
,这个过程继续。 最后,用零(或空) tabindex
完成这些元素。
我创build了一个简单的jQuery插件 。 它使用jQuery UI的':tabbable'select器来查找下一个'tabbable'元素并select它。
用法示例:
// Simulate tab key when element is clicked $('.myElement').bind('click', function(event){ $.tabNext(); return false; });
这是我为此构build的东西:
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(); } } }
特征:
- 可configuration的一组可移动元素
- 不需要jQuery
- 适用于所有现代浏览器
- 快速和轻量级
答案的核心在于find下一个要素:
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]; }
用法:
var nextEl = findNextTabStop(element); nextEl.focus();
注意我不关心优先化tabIndex
。
正如在上面的评论中提到的,我不认为任何浏览器公开标签订单信息。 这里简化一下浏览器按Tab键顺序获取下一个元素的方法:
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();
这只考虑一些标签,并忽略tabindex
属性,但可能是足够的,取决于你想要达到什么。
看来你可以检查一个元素的tabIndex
属性,以确定它是否是可聚焦的。 不可聚焦的元素的tabindex
为“-1”。
那么你只需要知道制表符的规则:
-
tabIndex="1"
具有最高tabIndex="1"
。 -
tabIndex="2"
具有次高的优先级。 - 接下来是
tabIndex="3"
,以此类推。 -
tabIndex="0"
(或默认情况下为可用)具有最低的优先级。 -
tabIndex="-1"
(或默认情况下是不可放置的)不作为制表位。 - 对于具有相同tabIndex的两个元素,DOM中第一个出现的元素具有较高的优先级。
下面是一个如何使用纯Javascriptbuild立制表符列表的例子:
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]); }
我们先走DOM,按索引顺序收集所有制表符。 然后我们汇集最后的名单。 请注意,我们在列表的最后添加了tabIndex="0"
的项目,之后的tabIndex
为1,2,3等项目
对于一个完整的例子,你可以使用“回车”键来查看,看看这个小提琴 。
您是否为每个要循环的元素指定了自己的tabIndex值? 如果是这样,你可以试试这个:
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 }
你正在使用jQuery,对不对?
希望这是有帮助的。
<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)" />
然后使用简单的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; } } } }