jQuery 使用箭头键导航 HTML 表格
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22817451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use arrow keys to navigate an HTML table
提问by Lane
I've created a very basic spreadsheet using an HTML table. It works perfectly, except the user must use the mouse to click on every <td>
in order to edit it. I'm capturing the click event with jQuery and displaying a dialog to edit it. I would like the user to be able to use the arrow keys to navigate to each cell, with the cell css background changing to indicate focus, and clicking the Enter key would trigger the jQuery dialog event. I'm using jQuery 1.9.
我使用 HTML 表格创建了一个非常基本的电子表格。它工作得很好,除了用户必须使用鼠标点击每一个<td>
才能编辑它。我正在使用 jQuery 捕获单击事件并显示一个对话框以对其进行编辑。我希望用户能够使用箭头键导航到每个单元格,单元格 css 背景更改以指示焦点,单击 Enter 键将触发 jQuery 对话框事件。我正在使用 jQuery 1.9。
Here is a jsfiddleof basically what I have.
这是我所拥有的基本内容的jsfiddle。
How do you save the currently selected cell, so that when you click on a cell with the mouse, and then use the arrow keys, it will navigate from the 'current' cell?
如何保存当前选定的单元格,以便当您用鼠标单击一个单元格,然后使用箭头键时,它将从“当前”单元格导航?
Thanks.
谢谢。
回答by huehuehue
Below is a vanilla JavaScript solution using the onkeydownevent and using the previousElementSiblingand nextElementSiblingproperties.
下面是一个使用onkeydown事件并使用previousElementSibling和nextElementSibling属性的普通JavaScript 解决方案。
https://jsfiddle.net/rh5aoxsL/
https://jsfiddle.net/rh5aoxsL/
The problem with using tabindexis that you dont get to navigate the way you would in Excel and you can navigate away from the spreadsheet itself.
使用tabindex的问题在于您无法像在 Excel 中那样导航,您可以离开电子表格本身。
The HTML
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>
The CSS
CSS
table {
border-collapse: collapse;
border: 1px solid black;
}
table td {
border: 1px solid black;
padding: 10px;
text-align: center;
}
The JavaScript
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);
}
}
回答by Lane
I figured it out, based on information I found on a few other posts. I rolled it all together, and the results are perfect.
我想通了,根据我在其他一些帖子中找到的信息。我把它全部卷在一起,结果是完美的。
Note:You have to put a tabindex
attribute on every <td>
to allow navigation.
注意:您必须在tabindex
each 上放置一个属性<td>
以允许导航。
Here's the jsfiddle. The same code is broken out below.
这是jsfiddle。下面列出了相同的代码。
The HTML:
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>
The CSS:
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;
}
The jQuery:
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();
}
});
回答by Madhav Saraf
This code will properly helps you to navigate the table using arrow keys. In every cell there are textboxes if you want to edit press f2 and edit the cell.
此代码将正确帮助您使用箭头键导航表格。如果要编辑,请按 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>
回答by pcalkins
For arrow key focusing, I ended up bundling together a bunch of different solutions posted here and came up with this. Still not sure why .next(), or .prev() wouldn't work for rows... seemed to need .prevAll and .nextAll for some reason:
对于箭头键聚焦,我最终将这里发布的一堆不同的解决方案捆绑在一起并提出了这个。仍然不确定为什么 .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();
}
});