使用箭头键导航 HTML 表格
Posted
技术标签:
【中文标题】使用箭头键导航 HTML 表格【英文标题】:Use arrow keys to navigate an HTML table 【发布时间】:2014-05-14 02:10:08 【问题描述】:我使用 html 表格创建了一个非常基本的电子表格。它工作得很好,除了用户必须使用鼠标单击每个<td>
才能对其进行编辑。我正在使用 jQuery 捕获点击事件并显示一个对话框来编辑它。我希望用户能够使用箭头键导航到每个单元格,单元格 css 背景更改以指示焦点,单击 Enter 键将触发 jQuery 对话框事件。我正在使用 jQuery 1.9。
这是一个jsfiddle,基本上是我所拥有的。
如何保存当前选中的单元格,以便当你用鼠标点击一个单元格,然后使用箭头键时,它会从“当前”单元格导航?
谢谢。
【问题讨论】:
提供一个你现在拥有的 jsfiddle,我会为它做代码。 How can I make the up and down arrow keys navigate a table's rows, and programmatically apply the sudo :hover to those rows?的可能重复 您现在拥有哪些 HTML、CSS 和 javascript 代码?听起来您应该在单元格上使用contenteditable=true
,但您使用的是完全不同的方法吗?
@Diodeus:那个帖子很相似,但只遍历行,而不是单元格。而且只有键盘可以用于导航,鼠标也不能。
原理是一样的。您需要一个键盘处理程序和一个存储光标位置的方法。如果你寻找它们,有很多例子。 ***.com/search?q=javascript+arrow+keys+html+table
【参考方案1】:
对于箭头键聚焦,我最终将这里发布的一堆不同的解决方案捆绑在一起并提出了这个。仍然不确定为什么 .next() 或 .prev() 不适用于行...似乎出于某种原因需要 .prevAll 和 .nextAll:
$("input").keydown(function (e)
var textInput = this;
var val = textInput.value;
var isAtStart = false, isAtEnd = false;
var cellindex = $(this).parents('td').index();
if (typeof textInput.selectionStart == "number")
// Non-IE browsers
isAtStart = (textInput.selectionStart == 0);
isAtEnd = (textInput.selectionEnd == val.length);
else if (document.selection && document.selection.createRange)
// IE <= 8 branch
textInput.focus();
var selRange = document.selection.createRange();
var inputRange = textInput.createTextRange();
var inputSelRange = inputRange.duplicate();
inputSelRange.moveToBookmark(selRange.getBookmark());
isAtStart = inputSelRange.compareEndPoints("StartToStart", inputRange) == 0;
isAtEnd = inputSelRange.compareEndPoints("EndToEnd", inputRange) == 0;
// workaround for text inputs of 'number' not working in Chrome... selectionStart/End is null. Can no longer move cursor left or right inside this field.
if (textInput.selectionStart == null)
if (e.which == 37 || e.which == 39)
isAtStart = true;
isAtEnd = true;
if (e.which == 37)
if (isAtStart)
$(this).closest('td').prevAll('td').find("input").focus();
if (e.which == 39)
if (isAtEnd)
$(this).closest('td').nextAll('td').find("input").not(":hidden").first().focus();
if (e.which == 40)
$(e.target).closest('tr').nextAll('tr').find('td').eq(cellindex).find(':text').focus();
if (e.which == 38)
$(e.target).closest('tr').prevAll('tr').first().find('td').eq(cellindex).find(':text').focus();
);
【讨论】:
【参考方案2】:此代码将正确帮助您使用箭头键导航表格。 如果要编辑按 f2 并编辑单元格,则在每个单元格中都有文本框。
$(document).ready(function()
var tr,td,cell;
td=$("td").length;
tr=$("tr").length;
cell=td/(tr-1);//one tr have that much of td
//alert(cell);
$("td").keydown(function(e)
switch(e.keyCode)
case 37 : var first_cell = $(this).index();
if(first_cell==0)
$(this).parent().prev().children("td:last-child").focus();
else
$(this).prev("td").focus();break;//left arrow
case 39 : var last_cell=$(this).index();
if(last_cell==cell-1)
$(this).parent().next().children("td").eq(0).focus();
$(this).next("td").focus();break;//right arrow
case 40 : var child_cell = $(this).index();
$(this).parent().next().children("td").eq(child_cell).focus();break;//down arrow
case 38 : var parent_cell = $(this).index();
$(this).parent().prev().children("td").eq(parent_cell).focus();break;//up arrow
if(e.keyCode==113)
$(this).children().focus();
);
$("td").focusin(function()
$(this).css("outline","solid steelblue 3px");//animate('borderWidth': '3px','borderColor': '#f37736',100);
);
$("td").focusout(function()
$(this).css("outline","none");//.animate('borderWidth': '1px','borderColor': 'none',500);
);
);
input
width:100%;
border:none;
<html>
<head>
<title>Web Grid Using Arrow Key</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<h1>Web Grid Table</h1>
<div id="abc" class="table_here" role="grid">
<table class="table" border="1" style="width:50%; padding:15px;">
<tr>
<th>Name</th>
<th>Email</th>
<th>Mobile</th>
<th>Address</th>
</tr>
<tr role="row">
<td role="gridcell" tabindex="0" aria-label="name" aria-describedby="f2_key">
<input type="text" class="link" tabindex="-1" name="name" aria-label="name">
</td>
<td role="gridcell" tabindex="-1" aria-label="Email Id" aria-describedby="f2_key">
<input type="text" class="link" tabindex="-1" name="email" aria-label="email">
</td>
<td role="gridcell" tabindex="-1" aria-label="Mobile Number" aria-describedby="f2_key">
<input type="text" class="link" tabindex="-1" name="mob" aria-label="mobile">
</td>
<td role="gridcell" tabindex="-1" aria-label="Address" aria-describedby="f2_key">
<input type="text" class="link" tabindex="-1" name="add" aria-label="address">
</td>
<p id="f2_key" style="display:none;" aria-hidden="true">Press F2 Key To Edit cell</p>
</tr>
<tr role="row">
<td role="gridcell" tabindex="-1" aria-label="name" aria-describedby="f2_key">
<input type="text" tabindex="-1" class="link" name="name">
</td>
<td role="gridcell" tabindex="-1" aria-label="Email Id" aria-describedby="f2_key">
<input type="text" tabindex="-1" class="link" name="email">
</td>
<td role="gridcell" tabindex="-1" aria-label="Mobile Number" aria-describedby="f2_key">
<input type="text" tabindex="-1" class="link" name="mob">
</td>
<td role="gridcell" tabindex="-1" aria-label="Address" aria-describedby="f2_key">
<input type="text" tabindex="-1" class="link" name="add">
</td>
</tr>
<tr role="row">
<td role="gridcell" tabindex="-1" aria-label="name" aria-describedby="f2_key">
<input type="text" tabindex="-1" class="link" name="name">
</td>
<td role="gridcell" tabindex="-1" aria-label="Email Id" aria-describedby="f2_key">
<input type="text" tabindex="-1" class="link" name="email">
</td>
<td role="gridcell" tabindex="-1" aria-label="Mobile Number" aria-describedby="f2_key">
<input type="text" tabindex="-1" class="link" name="mob">
</td>
<td role="gridcell" tabindex="-1" aria-label="Address" aria-describedby="f2_key">
<input type="text" tabindex="-1" class="link" name="add">
</td>
</tr>
</table>
</div>
</body>
</html>
希望这对你有帮助..!!
【讨论】:
【参考方案3】:以下是使用 onkeydown 事件并使用 previousElementSibling 和 nextElementSibling 属性的普通 JavaScript 解决方案。
https://jsfiddle.net/rh5aoxsL/
使用 tabindex 的问题在于您无法像在 Excel 中那样导航,而您可以离开电子表格本身。
HTML
<table>
<tbody>
<tr>
<td id='start'>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>9</td>
<td>10</td>
<td>11</td>
<td>12</td>
</tr>
<tr>
<td>13</td>
<td>14</td>
<td>15</td>
<td>16</td>
</tr>
</tbody>
</table>
CSS
table
border-collapse: collapse;
border: 1px solid black;
table td
border: 1px solid black;
padding: 10px;
text-align: center;
JavaScript
var start = document.getElementById('start');
start.focus();
start.style.backgroundColor = 'green';
start.style.color = 'white';
function dotheneedful(sibling)
if (sibling != null)
start.focus();
start.style.backgroundColor = '';
start.style.color = '';
sibling.focus();
sibling.style.backgroundColor = 'green';
sibling.style.color = 'white';
start = sibling;
document.onkeydown = checkKey;
function checkKey(e)
e = e || window.event;
if (e.keyCode == '38')
// up arrow
var idx = start.cellIndex;
var nextrow = start.parentElement.previousElementSibling;
if (nextrow != null)
var sibling = nextrow.cells[idx];
dotheneedful(sibling);
else if (e.keyCode == '40')
// down arrow
var idx = start.cellIndex;
var nextrow = start.parentElement.nextElementSibling;
if (nextrow != null)
var sibling = nextrow.cells[idx];
dotheneedful(sibling);
else if (e.keyCode == '37')
// left arrow
var sibling = start.previousElementSibling;
dotheneedful(sibling);
else if (e.keyCode == '39')
// right arrow
var sibling = start.nextElementSibling;
dotheneedful(sibling);
【讨论】:
我制作了一个 jquery 版本并将其扩展为能够跨表导航,同时将一个类应用于“focussed”元素 - 虽然我不得不使用$(document).keydown(function(e) ...
,但我很失望并且我不能使用更有针对性的东西,例如$(document).on("keydown", "td", function(e) ...
- 有谁知道这是否只是因为tabindex
没有应用于<td>
- 我不想将tabindex
应用于<td>'s
,因为表格动态添加和删除。有没有办法更具体地打电话给on()
? jsFiddle
它还有:点击聚焦单元格,在行首或行尾时,左箭头或右箭头移动到上一行或下一行,如果存在,否则移动到上一个或下一个表存在,以及 Enter 按键事件的处理程序。
您能否编辑您的小提琴并添加页面包含多个表格时的逻辑。您当前的解决方案仅在一张桌子上效果最佳。例如当我们点击特定表格后,该表格的导航将开始。
我们可以对角材料表也应用相同的代码【参考方案4】:
根据我在其他一些帖子中找到的信息,我想通了。我把它们卷在一起,结果很完美。
注意:您必须在每个<td>
上添加一个tabindex
属性以允许导航。
这里是the jsfiddle。下面分解出相同的代码。
HTML:
<table>
<thead>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 6</th>
<th>Col 7</th>
<th>Col 8</th>
</tr>
</thead>
<tbody>
<tr>
<td tabindex="1">1</td>
<td tabindex="2">2</td>
<td tabindex="3">3</td>
<td tabindex="4">4</td>
<td tabindex="5">5</td>
<td tabindex="6">6</td>
<td tabindex="7">7</td>
<td tabindex="8">8</td>
</tr>
<tr>
<td tabindex="10">10</td>
<td tabindex="11">11</td>
<td tabindex="12">12</td>
<td tabindex="13">13</td>
<td tabindex="14">14</td>
<td tabindex="15">15</td>
<td tabindex="16">16</td>
<td tabindex="17">17</td>
</tr>
</tbody>
</table>
<div id="edit">
<form>
<input type="text" id="text" value="To edit..." />
<input type="submit" value="Save" />
</form>
</div>
CSS:
*
font-size: 12px;
font-family: 'Helvetica', Arial, Sans-Serif;
box-sizing: border-box;
table, th, td
border-collapse:collapse;
border: solid 1px #ccc;
padding: 10px 20px;
text-align: center;
th
background: #0f4871;
color: #fff;
tr:nth-child(2n)
background: #f1f1f1;
td:hover
color: #fff;
background: #CA293E;
td:focus
background: #f44;
.editing
border: 2px dotted #c9c9c9;
#edit
display: none;
jQuery:
var currCell = $('td').first();
var editing = false;
// User clicks on a cell
$('td').click(function()
currCell = $(this);
edit();
);
// Show edit box
function edit()
editing = true;
currCell.toggleClass("editing");
$('#edit').show();
$('#edit #text').val(currCell.html());
$('#edit #text').select();
// User saves edits
$('#edit form').submit(function(e)
editing = false;
e.preventDefault();
// Ajax to update value in database
$.get('#', '', function()
$('#edit').hide();
currCell.toggleClass("editing");
currCell.html($('#edit #text').val());
currCell.focus();
);
);
// User navigates table using keyboard
$('table').keydown(function (e)
var c = "";
if (e.which == 39)
// Right Arrow
c = currCell.next();
else if (e.which == 37)
// Left Arrow
c = currCell.prev();
else if (e.which == 38)
// Up Arrow
c = currCell.closest('tr').prev().find('td:eq(' +
currCell.index() + ')');
else if (e.which == 40)
// Down Arrow
c = currCell.closest('tr').next().find('td:eq(' +
currCell.index() + ')');
else if (!editing && (e.which == 13 || e.which == 32))
// Enter or Spacebar - edit cell
e.preventDefault();
edit();
else if (!editing && (e.which == 9 && !e.shiftKey))
// Tab
e.preventDefault();
c = currCell.next();
else if (!editing && (e.which == 9 && e.shiftKey))
// Shift + Tab
e.preventDefault();
c = currCell.prev();
// If we didn't hit a boundary, update the current cell
if (c.length > 0)
currCell = c;
currCell.focus();
);
// User can cancel edit by pressing escape
$('#edit').keydown(function (e)
if (editing && e.which == 27)
editing = false;
$('#edit').hide();
currCell.toggleClass("editing");
currCell.focus();
);
【讨论】:
我正在尝试将其应用于主干视图。导航似乎根本不起作用。我必须点击选项卡才能将注意力集中到表格的行上,然后按箭头键没有任何效果。为了使这项工作与骨干一起工作,我必须做哪些更改? @aliirz,我不确定。我看过Backbone,但我从未使用过它。如果您弄清楚需要更改的内容,请发布此问题的另一个答案;我想看看你的作品。以上是关于使用箭头键导航 HTML 表格的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Angular 9 中使用向上、向下、向左和向右箭头键导航动态输入和选择表内的字段?