Reputation: 4339
I have a <table> that is set up roughly like this
Name Description Notes
===========================================
[___________] [_________] [_________]
There are quite a few rows and rather than the users tabbing through rows, I'd like to implement pressing the Up/Down keys to move up and down in the selected column.
The rows have the ID 'row_{ID}' where ID is the database ID. The fields have the ID 'name_{ID}', 'description_{ID}', 'notes_{ID}' etc.
I'm trapping the press with jQuery like:
$('input[id^="name_"]').bind('keyup', function(e) {
if(e.keyCode == 38)
...
else if(e.keyCode == 40)
...
});
Essentially I want, if the user is in row 2 of the description and press up, that they move to row 1 description field, and if they press down they move to row 3 description field.
I can't work out the way to select the next or previous rows. Can anyone provide assistance?
Upvotes: 2
Views: 5428
Reputation: 69905
Try this
Working demo
$(function(){
$('input[id^="name_"], input[id^="description_"], input[id^="notes_"]')
.bind('keyup', function(e) {
var $this = $(this);
var $tr = $this.closest("tr");
var id = this.id.substring(0, this.id.indexOf("_"));
if(e.keyCode == 38){
$tr.prev().find('input[id^='+id+']').focus();
}
else if(e.keyCode == 40)
{
$tr.next().find("input[id^='"+id+"']").focus();
}
});
});
Upvotes: 3
Reputation: 92893
I'll provide a sample of my own recent code which did almost the exact same thing. Hopefully it will be of some value.
// select events from the table using the keyboard arrows
$(document).keydown(function(e) {
if (e.keyCode==39 || e.keyCode==40) { // right, down
// if no radio buttons are checked, select the first one
if (!$("input:radio[name='rownum']:checked").length)
$("input:radio[name='rownum']:first").attr("checked",true);
// otherwise, select the next one
else
$("input:radio[name='rownum']:checked").closest("tr").next().find("input").attr("checked",true);
// highlight the row, un-highlight its siblings, and check its radio button
$("input:radio[name='rownum']:checked").closest("tr")
.addClass('selected')
.siblings().removeClass('selected').end()
.find('input').attr('checked','checked');
} else if (e.keyCode==37 || e.keyCode==38) { // left, up
// if no radio buttons are checked, select the last one
if (!$("input:radio[name='rownum']:checked").length)
$("input:radio[name='rownum']:last").attr("checked",true);
// otherwise, select the previous one
else
$("input:radio[name='rownum']:checked").closest("tr").prev().find("input").attr("checked",true);
// highlight the row, un-highlight its siblings, and check its radio button
$("input:radio[name='rownum']:checked").closest("tr")
.addClass('selected')
.siblings().removeClass('selected').end()
.find('input').attr('checked','checked');
}
}); // end keydown
Upvotes: 0
Reputation: 219920
To go down:
$(this).closest('tr').next().find('input[name=' + $(this).attr('name') + ']').focus();
To go up:
$(this).closest('tr').prev().find('input[name=' + $(this).attr('name') + ']').focus();
That is, assuming your input
s are all named the same.
Otherwise, you'll have to change that selector a bit, or use jQuery's .index()
on the td
and then select with .eq()
.
Upvotes: 6