按列的垂直顺序设置tabindex

7
我正在为我的文本输入类型分配tabindex,这些输入类型不是被禁用/隐藏的。以下是我尝试过的方法,它有效。然而,索引的顺序是在表格中水平分配的。我需要tabindex以列的方式而不是水平方式排序。有什么建议如何实现?我希望排序顺序如下所示。此问题是对进入键遵循tabindex(在将Enter键更改为表现为Tab的情况下)的后续问题。
   col1 col2 col3
    1      3    7
    2      4    8
           5    9 
           6   10  

(":input:not([disabled]):not(:hidden)").not($(":submit")).not($(":reset")).each(function (i) { $(this).attr('tabindex', i + 1); })

为什么不在服务器端设置tabindex?如果有人没有启用JavaScript或脚本加载失败怎么办? - gcampbell
我认为这并不是必要的。你为什么不专注于使用键盘箭头进行编程导航,并修复使用回车键进行导航(在我的Chrome OSX上无法正常工作)?这将使它更像你显然想要实现的表格处理器。 - actimel
@user5249203 抱歉,我不知道在哪里。请发布一个链接。 - actimel
垂直标签导航真的那么重要吗? - actimel
让我们在聊天中继续这个讨论 - user5249203
显示剩余6条评论
4个回答

5

这个例子将帮助你根据列设置 tabindex

function fixVerticalTabindex(selector) {
  if (typeof selector == 'undefined') {
    selector = '.reset-tabindex';
  }
  var tabindex = 1;
  $(selector).each(function(i, tbl) {
    $(tbl).find('tr').first().find('td').each(function(clmn, el) {
      $(tbl).find('tr td:nth-child(' + (clmn + 1) + ') input').each(function(j, input) {
        $(input).attr('placeholder', tabindex);
        $(input).attr('tabindex', tabindex++);
      });
    });
  });
}
$(function() {
  $('#btn-fix').click(function() {
    fixVerticalTabindex('.reset-tabindex');
  });
});
table {
  border: 1px solid red;
}

input {
  border: 1px solid black;
  width: 75px;
  height: 65px;
  font-size: 25px;
  text-align: center;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>

<table class="reset-tabindex">
  <tr>
    <td><input /></td>
    <td>no input</td>
    <td>no input</td>
  </tr>
  <tr>
    <td>no input</td>
    <td><input /></td>
    <td><input /></td>
  </tr>
  <tr>
    <td><input /></td>
    <td>no input</td>
    <td><input /></td>
  </tr>
</table>
<br /><br />
<table class="reset-tabindex">
  <tr>
    <td><input /></td>
    <td><input /></td>
    <td><input /></td>
    <td><input /></td>
    <td><input /></td>
  </tr>
  <tr>
    <td>no input</td>
    <td>no input</td>
    <td>no input</td>
    <td>no input</td>
    <td><input /></td>
  </tr>
  <tr>
    <td><input /></td>
    <td><input /></td>
    <td><input /></td>
    <td><input /></td>
    <td><input /></td>
  </tr>
  <tr>
    <td>no input</td>
    <td>no input</td>
    <td><input /></td>
    <td><input /></td>
    <td><input /></td>
  </tr>
  <tr>
    <td>no input</td>
    <td>no input</td>
    <td><input /></td>
    <td><input /></td>
    <td><input /></td>
  </tr>
</table>
<br /><br />
<button id="btn-fix">Click to fix vertical tabindex</button>

该函数将自行“修复”每个表格(不会混淆不同表格的列)。

我没有检查过具有colspan/rowspan的表格的功能,但我猜测它将不能正常工作。

代码行 $(input).attr('placeholder', tabindex);仅用于预览和调试,您可以在生产中删除它。

2
基于这个解决方案,我修改了代码,使其也可以使用回车键和标签键,并以列为单位模式工作。
我认为对于这种情况指定tabindex属性并不是最好的想法。您需要在每次更改列数或行数时重新计算它们。此外,它会改变页面上可聚焦元素的流程(先是表格,然后是其周围的元素)。

/*!
* based on formNavigation https://github.com/omichelsen/FormNavigation
*/
(function ($) {
  $.fn.formNavigation = function () {
    $(this).each(function () {
      // Events triggered on keyup
      $(this).find('input').on('keyup', function(e) {
        switch (e.which) {
          // arrow right
          case 39:
            $(this).closest('td').next().find('input').focus();
            break;

          // arrow left
          case 37:
            $(this).closest('td').prev().find('input').focus();
            break;

          // arrow bottom
          case 40:
            $(this).closest('tr').next().children().eq($(this).closest('td').index()).find('input').focus();
            break;

          // arrow top
          case 38:
            $(this).closest('tr').prev().children().eq($(this).closest('td').index()).find('input').focus();
            break;

          // enter
          case 13:
            if ($(this).closest('td').next().find('input').length>0) {
              // when there is another column on right
              $(this).closest('td').next().find('input').focus();
            } else {
              // when last column reached
              $(this).closest('tr').next().children().eq(1).find('input').focus();
            }
            break;
        }
      });
      
      // Events triggered on keydown (repeatable when holding the key)
      $(this).find('input').on('keydown', function(e) {
        // Vertical navigation using tab as OP wanted
        if (e.which === 9 && !e.shiftKey) {
          // navigate forward
          if ($(this).closest('tr').next().find('input').length>0) {
            // when there is another row below
            e.preventDefault();
            $(this).closest('tr').next().children().eq($(this).closest('td').index()).find('input').focus();
          } else if ($(this).closest('tbody').find('tr:first').children().eq($(this).closest('td').index()+1).find('input').length>0) {
            // when last row reached
            e.preventDefault();
            $(this).closest('tbody').find('tr:first').children().eq($(this).closest('td').index()+1).find('input').focus();
          }
        } else if (e.which === 9 && e.shiftKey) {
          // navigate backward
          if ($(this).closest('tr').prev().find('input').length>0) {
            // when there is another row above
            e.preventDefault();
            $(this).closest('tr').prev().children().eq($(this).closest('td').index()).find('input').focus();
          } else if ($(this).closest('tbody').find('tr:last').children().eq($(this).closest('td').index()-1).find('input').length>0) {
            // when first row reached
            e.preventDefault();
            $(this).closest('tbody').find('tr:last').children().eq($(this).closest('td').index()-1).find('input').focus();
          }
        }
      });
    });
  };
})(jQuery);

// usage
$('.gridexample').formNavigation();
/* For demonstration only */
.gridexample {
  font-size: 1.1em;
}
.gridexample th {
  padding: .15em .5em;
}
.gridexample td {
  padding: .1em;
  width: 5em;
}
.gridexample input[type="text"] {
  width: 100%;
  line-height: 2;
  box-sizing: border-box;
}
<p>
  Sample <a href="#">links</a> around the table (to simulate <a href="#">focus</a> outside the table).
</p>

<table class="gridexample">
  <thead>
    <tr>
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td><input type="text"></td>
      <td><input type="text"></td>
      <td><input type="text"></td>
      <td><input type="text"></td>
    </tr>
    <tr>
      <th>2</th>
      <td><input type="text"></td>
      <td><input type="text"></td>
      <td><input type="text"></td>
      <td><input type="text"></td>
    </tr>
    <tr>
      <th>3</th>
      <td><input type="text"></td>
      <td><input type="text"></td>
      <td><input type="text"></td>
      <td><input type="text"></td>
    </tr>
    <tr>
      <th>4</th>
      <td><input type="text"></td>
      <td><input type="text"></td>
      <td><input type="text"></td>
      <td><input type="text"></td>
    </tr>
  </tbody>
</table>

<p>
  Sample <a href="#">links</a> around the table (to simulate <a href="#">focus</a> outside the table).
</p>

<!-- jQuery needed for this solution -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>


0
从这里的@Merlyn Morgan-Graham解决方案(如何使用jQuery将表格中的选项卡顺序从水平重新分配为垂直?)和@dekel的解决方案,我得出了以下答案。它在大多数情况下都有效。输入键跟随tabindex(在将输入键更改为像tab一样行事的情况下)
function assignTabIndex() {
    // Define variables 
    var maxRowCount = 0;        
    // Loop through all rows and find the children (td) length
    // Get the maxRowCount
    $('table tbody tr').each(function() {
        maxRowCount = Math.max(maxRowCount, $(this).children('td').length);        
    });

    // Define and start the cell count at 1
    var cellCounter = 1;
    // Loop through the table, column first instead of row first
    for (var columnIndex = 0; columnIndex < maxRowCount; ++columnIndex) {
        // Loop through all the rows for the current column
        $('form table tr').each(function() {
            // ...but only look at cells matching the current column
            var cellForCurrentColumn = $(this)
                .children('td')
                .eq(columnIndex)
                .find('input[type =text]:not([disabled])');
            // Some rows could be bigger than others,
            // so cellForCurrentColumn might not exist for shorter rows
            if (cellForCurrentColumn != null) {
                // Set the tab index and then increment the counter
                cellForCurrentColumn.attr('tabindex', cellCounter++);
            }
        });
    }
};
// Enter key to follow tab index

   function EnterKeyAsTabKey() {
    $(document).ready(function() {
        assignTabIndex(); //call the assignTabIndex function

        // Will only run once the page Document Object Model (DOM) is ready for JavaScript code 
        // Create a jQuery object containing the html element 'input', and not disabled
        // Create a .not() method to exclude buttons for keypress event
        $(":input:not([disabled])").not($(":button")).keypress(function(evt) {
            // If the keypress event code is 13 (Enter)
            if (event.which === 13 && this.type !== 'submit' || 'reset') {
                evt.preventDefault();
                // Get the attribute type and if the type is not submit
                itype = $(this).prop('type');
                // Get the current Tabindex
                currentTabindex = $(this).attr('tabindex');
                // alert(currentTabindex); // alert to check the value a variable has. Good for trouble shoot
                if (currentTabindex) {
                    nextInput = $('input[tabindex^="' + (parseInt(currentTabindex) + 1) + '"]');
                    // console.log(this, nextInput); // to print next input in console. Good for trouble shoot
                    if (nextInput.length) {
                        nextInput.focus();
                    } else
                        return false;

                }

            }
        });
    })
};

0

如果您的所有输入都在同级 div 中(假设每个都在 Bootstrap col-md-* 中),这里是解决方案:

let columns_number=4; // static for me, but you can send/get it via data-columns="4" as form attribute

$('form').find('input, select, textarea').each(function(){
    $(this).attr('tabindex', $(this).attr('type')==='submit' ? 999 : $(this).closest('div').index()%columns_number+1);
});

JSFiddle: https://jsfiddle.net/x5oh7edf/

JSFiddle:https://jsfiddle.net/x5oh7edf/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接