EventListener for keydown event not being triggered on window

Having trouble with the 2048 game implementation - the window.addEventListener("keydown", handleInput, {once:true}); is not working as expected. Even though console.log(e.key) shows the correct key being pressed (ArrowUp, ArrowDown, etc.), the tile does not move. Any assistance would be greatly appreciated!

Below is the index.js file containing the event listener code:

import Grid from "./grid.js";
import Tile from "./tile.js";

const gameBoard = document.getElementById('game-board');
const grid = new Grid(gameBoard);

grid.randomEmptyCell().tile = new Tile(gameBoard);
grid.randomEmptyCell().tile = new Tile(gameBoard);
setupInput();

function setupInput() {
  window.addEventListener("keydown", handleInput, { once: true });
}

async function handleInput(e) {
  console.log(e.key);
  switch (e.key) {
    case "ArrowUp":
      if(!canMoveUp()) {
        setupInput();
        return;
      }
      await moveUp()
      break
    case "ArrowDown":
      if(!canMoveDown()) {
        setupInput();
        return;
      }
      await moveDown()
      break
    case "ArrowLeft":
      if(!canMoveLeft()) {
        setupInput();
        return;
      }
      await moveLeft()
      break
    case "ArrowRight":
      if(!canMoveRight()) {
        setupInput();
        return;
      }
      await moveRight()
      break
    default:
      setupInput()
      return
  }

  grid.cells.forEach(cell => cell.merTiles());

  const newTile = new Tile(gameBoard);

  grid.randomEmptyCell().tile = newTile;

  if (!canMoveUp() && !canMoveDown() && !canMoveLeft() && !canMoveRight()) {
    newTile.waitForTransition(true).then(() => {
      alert("You lose!");
    });
  } return
  setupInput();
}

function moveUp() {
  return slideTiles(grid.cellsByColumn);
}

function moveDown() {
  return slideTiles(grid.cellsByColumn.map(column => [...column].reverse()));
}

function moveLeft() {
  return slideTiles(grid.cellsByRow);
}

function moveRight() {
  return slideTiles(grid.cellsByRow.map(row => [...row].reverse()));
}

function slideTiles(cells) {
  return Promise.all(
  cells.flatMap(group => {
    const promises = [];
    for (let i = 1; i < group.length; i++) {
      const cell = group[i];
      if (cell.tile == null) continue;
      let lastValidCell;
      for (let j = i - 1; j >= 0; j--) {
        const moveToCell = group[j];
        if (!moveToCell.canAccept(cell.tile)) break;
        lastValidCell = moveToCell;
      }
      if (lastValidCell != null) {
        promises.push(cell.tile.waitForTransition());
        if (lastValidCell.tile != null) {
          lastValidCell.mergeTile = cell.tile;
        } else {
          lastValidCell.tile = cell.tile;
        }
        cell.tile = null;
      }
    }
    return promises;
  }));
}

function canMoveUp() {
  return canMove(grid.cellsByColumn);
}

function canMoveDown() {
  return canMove(grid.cellsByColumn.map(column => [...column].reverse()));
}

function canMoveLeft() {
  return canMove(grid.cellsByRow);
}

function canMoveRight() {
  return canMove(grid.cellsByRow.map(row => [...row].reverse()));
}

function canMove(cells) {
  return cells.some(group => {
    return group.some((cell, index) => {
      if (index === 0) return false;
      if (cell.tile == null) return false;
      const moveToCell = group[index - 1];
      return moveToCell.canAccept(cell.tile);
    });
  });
}

Answer №1

Check out this MDN page for more information: EventTarget.addEventListener()

An important point to note is the boolean value that determines if the listener should only be triggered once after being added. Setting it to true will automatically remove the listener after it's invoked. If not specified, it defaults to false.

If you omit {once: true}, the listener may trigger multiple times.

Another thing to consider is the use of console.log(e.key) alongside e.keyCode in switch cases. According to MDN, keyCodes refer to actual codes. See more on key codes here: Code values for keyboard events

To align your switch case conditions, you can either switch to using e.key for the same values: Key values for keyboard events

Alternatively, consider updating the case values from text to keyCode for consistency.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What causes an error when jqXHR.abort() is invoked in the beforeSend function?

Attempting to interrupt ajax call with beforeSend in case of a specific condition. Upon executing jqXHR.abort() or return false, I encounter the following error message: TypeError: $.ajax(...).fail is not a function .fail(function (jqXHR, textStatus, er ...

Does .NET MVC provide the necessary separation of HTML/CSS/JS for my project?

Currently, I am collaborating with my ASP.NET development team in an effort to improve the quality of our HTML output. We are facing challenges due to ASP.NET's tendency to insert JavaScript directly into the page, creating dependencies on JS for form ...

Ways to identify the visible elements on a webpage using JavaScript

I'm working on a nextjs app , I am looking to dynamically update the active button in the navbar based on which section is currently visible on the page. The child elements of the page are structured like this: <div id="section1" > < ...

Using the Presentational - Container (or Smart - Dumb) component approach in conjunction with Vuex

When it comes to managing the Presentational - Container (or Smart - Dumb) component pattern with Vuex, what is your recommended approach? Should the Presentational (or Dumb) components emit events to the parent or call Vuex actions? Imagine a scenario w ...

What is the best way to find out if an array index is within a certain distance of another index?

I'm currently developing a circular carousel feature. With an array of n items, where n is greater than 6 in my current scenario, I need to identify all items within the array that are either less than or equal to 3 positions away from a specific inde ...

Updating the user interface in react-apollo following a delete mutation

After successfully executing a delete mutation in my React Apollo component, the UI of my app did not update as expected. Here is the code snippet for reference: const deleteRoom = async (roomId, client = apolloClient) => { const user = await getUser ...

Best Practices for Converting TypeScript to JavaScript

What is the recommended approach to converting this JavaScript code into TypeScript? JAVASCRIPT: function MyClass() { var self = this, var1 = "abc", var2 = "xyz"; // Public self.method1 = function () { return "somethin ...

exploring the depths of nested objects and utilizing the 'for in

My issue involves receiving a json response from an API that includes objects within objects. It looks something like this: {Object}->{results}->{manyObjects} When I execute the following code: var list = data.results.list; for(val in list){ ...

Error always occurs during validation when sending files through AJAX in Laravel

Currently, I am working on a form where I am attempting to send a file (PDF, DOC, DOCX) to my controller. Here is the structure of my form: <div class="modal-body"> {{-- alert if any error exist --}} <div ...

Which method proves to be quicker: storing data on a DOM element with a class attribute, or using jQuery data?

In my application, I have a render loop that constantly updates the appearance of several DOM elements based on data fetched from an external source. Each element needs to have presentational classes applied according to this data. For example: var anima ...

Removing a CSS class using JQuery

Within my website layout, I have a div that is dynamically included using PHP. This div is inserted in two different locations, each inside its own parent div. <div id="parent_div"> <div id="contact_details_div" class="contact_details_div sam ...

Transforming jQuery into Angular - Press Button to update choices in Dropdown List

I am looking to integrate some AngularJS features into a website that currently utilizes jQuery. Here is the issue I am facing: With jQuery, clicking a button triggers a dropdown item change. Please refer to the jsfiddle below for an example: $('# ...

How to extract column name from query result set using JavaScript in Snowflake database?

When querying in Snowflake with JavaScript inside a stored procedure, we typically receive a Result_set. How can the column names of the output result be retrieved using the JavaScript API? Please note that this inquiry is not about retrieving the values ...

What is preventing the darkBaseTheme from being applied in material-ui?

import React from 'react'; import ReactDOM from 'react-dom'; import darkBaseTheme from 'material-ui/styles/baseThemes/darkBaseTheme'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; import getMui ...

Performing multiple asynchronous tasks using RxJS by running Array.prototype.map in parallel batches or queues

Imagine having an array of variables, such as: [Sasha, Misha, Caitlyn, ...String] (string[]) with a sizable length of about 10k elements. If you want to run an asynchronous parallel task with these elements, but not all at once like Promise.all, rather in ...

An AJAX script for dynamically adding, modifying, and removing records from a database

How can I implement a functionality where by pressing "-" the vote is removed from the database, and when any other number is selected, the vote will be updated in the database with that value? The default value of the dropdown list is votacion.votCalific ...

Issue observed: React Map layer is not loading until mouseEnter event happens

The map is displayed with the color fill only when a mouse enter event occurs. How can I make it trigger on load instead? I am working with react-simple-maps, and the JSON data is successfully loading the map on mouse enter. You can find the source code ...

Tips for showcasing a drop-down menu using Jquery

I am currently utilizing jQuery to showcase a drop-down menu. It is successfully working for a single menu and displaying the appropriate drop-down. However, when I attempt to use more than one menu, it displays all of the drop-down menus simultaneously. I ...

Displaying and Concealing Table Rows using Javascript

I am working with an array of prices that are being displayed in a table using a foreach loop. The goal is to hide specific rows in the table based on certain conditions. The $status variable is set to "YES" if the price is => 30, and "NO" if the price ...

Error while compiling Q_PROPERTY

Current Environment : Qt 5.8 MSVC2015 64bit, Windows 7 64 bit. I have successfully called a C++ method from Java Script. However, I encountered an issue when trying to retrieve the return value of the C++ method in JavaScript. To address this, I attempt ...