简体   繁体   English

使用箭头键导航HTML表格

[英]Use arrow keys to navigate an HTML table

I've created a very basic spreadsheet using an HTML table. 我使用HTML表创建了一个非常基本的电子表格。 It works perfectly, except the user must use the mouse to click on every <td> in order to edit it. 它完美无缺,但用户必须使用鼠标点击每个<td>才能进行编辑。 I'm capturing the click event with jQuery and displaying a dialog to edit it. 我正在使用jQuery捕获click事件并显示一个对话框来编辑它。 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. 我希望用户能够使用箭头键导航到每个单元格,单元格css背景更改以指示焦点,单击Enter键将触发jQuery对话框事件。 I'm using jQuery 1.9. 我正在使用jQuery 1.9。

Here is a jsfiddle of 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. 谢谢。

Below is a vanilla JavaScript solution using the onkeydown event and using the previousElementSibling and nextElementSibling properties. 下面是一个使用onkeydown事件并使用previousElementSiblingnextElementSibling属性的vanilla JavaScript解决方案。

https://jsfiddle.net/rh5aoxsL/ https://jsfiddle.net/rh5aoxsL/

The problem with using tabindex is 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);
  }
}

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. 注意:您必须在每个<td>上放置一个tabindex属性以允许导航。

Here's the jsfiddle . 这是jsfiddle The same code is broken out below. 下面列出了相同的代码。

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();
    }
});

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> 
Hope this will helps to you..!! 希望这会对你有所帮助.. !!

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();
    }

});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM