keewee279
keewee279

Reputation: 1654

jQuery: How to navigate from one td to a specific other td in a table

I am new to jQuery so I might approach this the wrong way but hope someone here can help me.

I have a pretty large HTML table that is created dynamically. To help the user I would like to bind a navigation event to the arrow keys only for this table. In this example I would like to "jump" from on div to the next div (they also have the class "myClass"). The table is larger than the example below but the structure always repeats so every third td has an (editable) div.

So far I couldn't get this to work but the function does catch the arrow press as I can show alerts this way.

My jQuery:

$(document).on('keydown', '#tblCalendar', function(e){
    switch(e.which) {
        case 37: // left
            // similar action to the left
            break;                  
        case 39: // right
            $(this).closest('td').next().next().next().find('div').focus();
            break;          
        default: return; // exit handler
    }
    e.preventDefault(); // prevent default action
});

My HTML (simplified):

<tbody>
    <tr>
        <td></td>
        <td></td>
        <td><div class="myClass"></div></td>
        <td></td>
        <td></td>
        <td><div class="myClass"></div></td>
        // ...
    </tr>
    // ...
</tbody>

Many thanks in advance, Mike

Upvotes: 0

Views: 663

Answers (2)

insertusernamehere
insertusernamehere

Reputation: 23580

I've rebuild your function a little bit. Now it would involves only one DOM request to collect all editable elements and stores them in a variable. You can rotate through all of them using the left and right arrow keys. If no element is selected, it gets the first one. I've added a class to demonstrate that behavior. To adjust this to your needs, simply replace .addClass('active') with .get(0).focus().

Example of the principal with a class that toggles

var focusable = $('div.myClass');
var current = null;

$(document).on('keydown', function(event) {
    var next = null;

    if (37 == event.which || 39 == event.which) {
        if (null == current) {
            current = 0;
            focusable.eq(current).addClass('active');
            return;
        }

        if (37 == event.which) {
            next = current - 1;
            if (0 > next) {
                next = focusable.length - 1;
            }
        }

        if (39 == event.which) {
            next = current + 1;
            if (focusable.length == next) {
                next = 0;
            }
        }

        focusable.eq(current).removeClass('active');
        focusable.eq(next).addClass('active');
        current = next;
    }
});

Reduced code when there's no class toggle involved

var focusable = $('div.myClass');
var current = null;

$(document).on('keydown', function(event) {
    if (37 == event.which || 39 == event.which) {
        if (null == current) {
            current = 0;
            focusable.eq(current).get(0).focus();
            return;
        }

        if (37 == event.which) {
            --current;
            if (0 > current) {
                current = focusable.length - 1;
            }
        }

        if (39 == event.which) {
            ++current;
            if (focusable.length == current) {
                current = 0;
            }
        }

        focusable.eq(current).get(0).focus();
    }
});

Demo

Try before buy
Try before buy with focusable divs

Upvotes: 1

tymeJV
tymeJV

Reputation: 104775

You should use nextUntil to find the next td with a div in it:

$(this).closest('td').nextUntil("td div").focus();

Although I'm not sure how a div can get focus

Since this is referring to the entire table, change the handler to watch for keypresses on the contenteditable div

$(document).on('keydown', '#tblCalendar tr td div', function(e){

Upvotes: 1

Related Questions