Handling the Enter and arrow keys using Javascript

Handling the Enter and arrow keys using Javascript

·

4 min read

I had a task assigned to handle an "enter" key in my internship. Actually, I am not entirely familiar with front-end development. But here is my effort to solve the task and learn new things.

So, the task was, to generate the table where the cells of the table are editable. And whenever the 'enter' button is pressed, the next cell has to be selected.

At first, it seemed easy, and I started to code. I knew this task was related to the event. But, as I was solving it, I needed to google a lot. And, after many errors, and solving those errors, I finally solved the task.

Here's how the solution looks.

First created an HTML file named 'index.html'

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Index</title>
</head>
<body>
    <h1 style="text-align:center">Demo of handling Enter and arrow keys</h1>
    <br>
    <div>
        <table id="dataTable">
            <tbody id="tableBody">

            </tbody>
        </table>
    </div>

</body>
</html>

Here I have created a table inside the div tag. I have decided to create a table dynamically.

Now, create a table dynamically.

function createTable(rows, columns) {
    for (let i=0; i<rows; i++) {
        let row = document.createElement('tr');

        for (let j=0; j<columns; j++) {
            let cell = document.createElement('td');

            cell.setAttribute('contenteditable', 'true') //makes cell editable
            cell.setAttribute('onkeyup','handleEvent(event)')  // calls postAnswer() function on keyup

            cell.innerHTML = `${i}${j}`;
            row.appendChild(cell);
        }
        document.getElementById('tableBody').appendChild(row);
    }

}

here, the rows and columns are the parameter i.e. the table can be generated of any rows and columns.

Now let's make the table look good using bootstrap. I used bootstrap cdn here.

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js" integrity="sha384-IDwe1+LCz02ROU9k972gdyvl+AESN10+x7tBKgc9I5HFtuNz0wWnPclzo6p9vxnk" crossorigin="anonymous"></script>

use the bootstrap cdn inside the <head> tag.

Add bootstrap class in the <table> tag.

<table class="table table-striped table-bordered" id="dataTable">
            <tbody id="tableBody">

            </tbody>
        </table>

Now the table seems a little good.

Now let's handle the Enter and arrow keys pressed. Here the main task is when an enter is pressed the next cell to the right has to be selected.

function handleEvent(event) {
    // handles events for "enter"/ "up"/ "down"/ "left"/ "right" arrow keys

    if (event.which == 13) {
        //prevents the default action of the event from happening
        event.preventDefault();

        if (event.target.nextSibling != null) {
            // go to next cell
            event.target.nextSibling.focus()
        }
        else {
            // go to next row's first cell
            event.target.parentElement.nextSibling.firstChild.focus()
        }
    }
}

This handles the enter key pressed and selects the right cell. But I wanted to handle the arrow keys as well so it will give a good user experience.

if (event.which == 39) {
        // go to next cell
        event.target.nextSibling.focus()
    }

    if (event.which == 37) {
        // go to previous cell
        event.target.previousSibling.focus()
    }

    if (event.which == 38) {
        // go to previous row's same cell
        event.target.parentElement.previousSibling.childNodes[event.target.cellIndex].focus()
    }

    if (event.which == 40) {
        // go to next row's same cell
        event.target.parentElement.nextSibling.childNodes[event.target.cellIndex].focus()
    }

this worked for all the arrow keys and provided a good user experience.

So here's what the final code looks like.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Index</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
    <script src="table.js"></script>
    <script src="events.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js" integrity="sha384-IDwe1+LCz02ROU9k972gdyvl+AESN10+x7tBKgc9I5HFtuNz0wWnPclzo6p9vxnk" crossorigin="anonymous"></script>

</head>
<body>
    <h1 style="text-align:center">Demo of handling Enter and arrow keys</h1>
    <br>
    <div>
        <table class="table table-striped table-bordered" id="dataTable">
            <tbody id="tableBody">

            </tbody>
        </table>
    </div>

    <script>
        createTable(10,10);
    </script>


</body>
</html>

table.js

function createTable(rows, columns) {
    for (let i=0; i<rows; i++) {
        let row = document.createElement('tr');

        for (let j=0; j<columns; j++) {
            let cell = document.createElement('td');

            cell.setAttribute('contenteditable', 'true') //makes cell editable
            cell.setAttribute('onkeyup','handleEvent(event)')  // calls postAnswer() function on keyup

            cell.innerHTML = `${i}${j}`;
            row.appendChild(cell);
        }
        document.getElementById('tableBody').appendChild(row);
    }

}

events.js

function handleEvent(event) {
    // handles events for "enter"/ "up"/ "down"/ "left"/ "right" arrow keys

    if (event.which == 13) {
        //prevents the default action of the event from happening
        event.preventDefault();

        if (event.target.nextSibling != null) {
            // go to next cell
            event.target.nextSibling.focus()
        }
        else {
            // go to next row's first cell
            event.target.parentElement.nextSibling.firstChild.focus()
        }
    }

    if (event.which == 39) {
        // go to next cell
        event.target.nextSibling.focus()
    }

    if (event.which == 37) {
        // go to previous cell
        event.target.previousSibling.focus()
    }

    if (event.which == 38) {
        // go to previous row's same cell
        event.target.parentElement.previousSibling.childNodes[event.target.cellIndex].focus()
    }

    if (event.which == 40) {
        // go to next row's same cell
        event.target.parentElement.nextSibling.childNodes[event.target.cellIndex].focus()
    }
}

And this is the final result of the code.

It was fun solving this task and I learned a little about the events too. I hope it is helpful for others too.

Note: I have made some improvement changes after writing this post.

link to GitHub: github.com/aakash-shakya/javascript-handlin..

demo link: aakas.com.np/javascript-handling-arrow-keys..