I am puzzled as to why my script suddenly ceases to function

I am currently developing a basic etch-a-sketch program with two buttons. One button resets the screen, while the other creates a new screen where you can specify the number of pixels in the drawing area. The default size and reset functions are working properly. However, when I click the new button to set the number of pixels, the event listener stops functioning correctly, resulting in the mouseover effect not changing the background color of the divs anymore. Below is the code snippet:

const screen = document.querySelector('.screen')
const clearButton = document.querySelector('.clear-btn');
const newButton = document.querySelector('.new-btn');
var size = 64;

function createGrid(size) {
  document.styleSheets[0].cssRules[3].style["grid-template-columns"] = "repeat(" + size + ", 1fr)"
  document.styleSheets[0].cssRules[3].style["grid-template-rows"] = "repeat(" + size + ", 1fr)"
  console.log('createGrid');
  for (i = 0; i < size*size; i++) { 
    const grid = document.createElement('div');
    grid.classList.add('grid');
    grid.style.cssText = 'color: #cccccc; background: #cccccc; border: solid 1px lightgrey;';      
    screen.appendChild(grid);
  }
}

function reset() {
  var grid = document.getElementsByClassName('grid');
  Array.from(grid).forEach((tile) => {
    tile.style.backgroundColor = "#cccccc";
  });
}

function newSize(){
  let userResponse = prompt("Please enter size of canvas: ", "");
  size = parseInt(userResponse);
  remove();
  createGrid(size);
}


function remove(){
  while (screen.firstChild) {
    console.log(size);
    screen.removeChild(screen.firstChild);
  }
}

createGrid(size);

clearButton.addEventListener('click', reset);
newButton.addEventListener('click', newSize);

Answer №1

It's important to remember to add your event listener while creating the grid. If you remove the grid that had the original event listener attached and replace it with a new one, the new grid won't have any listeners attached:

function createGrid(size) {
  document.styleSheets[0].cssRules[3].style["grid-template-columns"] = "repeat(" + size + ", 1fr)"
  document.styleSheets[0].cssRules[3].style["grid-template-rows"] = "repeat(" + size + ", 1fr)"
  console.log('createGrid');
  for (i = 0; i < size*size; i++) { 
    const grid = document.createElement('div');
    grid.classList.add('grid');
    grid.style.cssText = 'color: #cccccc; background: #cccccc; border: solid 1px lightgrey;';      
    screen.appendChild(grid);

    // Add listener to grid cell
    grid.addEventListener('mouseover', (e) => {
       e.target.style.background = '#0d0d0d';
    })
  }
}

You may want to explore event delegation as well. This allows you to add a single listener on the container instead of attaching one to each cell individually.

Answer №2

The reason for this issue is due to the introduction of new divs. The listener was initially attached to the original HTMLNodes, and with the addition of new ones, they lack any listeners. To resolve this: - Remove the old listeners in the remove function - Attach new listeners in the newSize function

To streamline the code, move the last part (starting from

var grid = document.getElementsByClassName...
) into a separate function. Then, call this function at the end of the newSize function. For instance:

function attachListeners() {
  const grid = document.getElementsByClassName('grid');
  Array.from(grid).forEach(tile => {
    tile.addEventListener('mouseover', ...);
  });
};

Your updated newSize function will look like this:

function newSize(){
  let userResponse = prompt("Please enter size of canvas: ", "");
  size = parseInt(userResponse);
  remove();
  createGrid(size);
  attachListeners();
}

Incorporate the following section into the remove function:

function remove() {
  removeTileListeners();
  while (screen.firstChild) {        
    screen.removeChild(screen.firstChild);
  } 
}

I leave the task of implementing the removeListeners() method as an exercise for you :)

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

Is there a way to adjust the timepicker value directly using the keyboard input?

Is there a way to control the material-ui-time-picker input using the keyboard instead of clicking on the clock? This is my current code: import React, { Component } from "react"; import { TimePicker } from "material-ui-time-picker"; import { Input as Ti ...

Implementing a function to save a file to a nested directory in node.js

Currently, I'm utilizing node and express with the following directory structure: public img css js server.js Within server.js, I have the code snippet below for writing to a png file: fs.writeFile('testfile.png', imageData, func ...

Tips for populating individual arrays in AngularJS with data from a JSON:- Iterate through the JSON

I am attempting to extract each data from a JSON file and store it in a new array, as I want to create a graph. However, the process is not working as expected. Here is what I expect: f = { "FAKULTAS":"01/FKIP", "FAKULTAS":"02/FMIPA", "FAKULT ...

Managing image downloads from a Node.js server: Tips and Best Practices

Currently, I am in the process of learning node.js and recently encountered a scenario where I need to download an image from the server by clicking a button on the webpage. I have set up an endpoint that receives two parameters: - The name of the image ...

What are some methods to showcase JSON information using only JavaScript either from a local JSON file or a web server?

Hello, I am new to working with JSON and I am curious to know if it is possible to use only JavaScript (without any frameworks) to present all the data from a JSON file in a table format. Preferably, I would like to load the file locally, but if using a w ...

Verifying the absence of values in destructured variables

In my code, I have set up three constants based on an object. const {standing_bid_amt, min_increment, starting_price} = props.auction.auction; The problem arises when the object auction is empty, resulting in the constants being undefined. To address this ...

Steps for populating select HTML elements with server-side retrieved values1. Fetch the desired values from the server

I have a dropdown menu or select box in HTML. I need to populate this element with values retrieved from the server. The values are stored in an array on the server side. I want to extract these values and populate the dropdown menu. Using Struts 1.3 on ...

Node.js Error: (Headers already sent, cannot be modified)

My goal in the program is to utilize both res.send and render simultaneously with the same data. I have a Qt application that can receive the data from my Node JS, but it appears challenging to send and render the data on the webpage at the same time. - ...

"Troubleshooting: Unable to Trigger jQuery Click Event Using Class Selector

I have two separate lists with different classes, <li><a href='#' class="cls1" name="X">blah</a></li> <!-- Click to load a cls2 item --> <li><a href='#' class="cls1" name="Y">blah</a>< ...

Error in canvas-sketch: "THREE.ParametricGeometry has been relocated to /examples/jsm/geometries/ParametricGeometry.js"

I recently started using canvas-sketch to create some exciting Three.js content. For my Three.js template, I utilized the following command: canvas-sketch --new --template=three --open The version that got installed is 1.11.14 canvas-sketch -v When atte ...

Is it possible to refresh AdSense banner when the router changes?

Is there a way to reload the AdSense banner ads when the router changes? I've been encountering issues trying to re-add the script and HTML properly. Any guidance on how this should be done would be greatly appreciated... This is just a test for one ...

How to separate specific ranges within an array of numbers?

Scenario In a client application, there is a table where users can select specific rows. Each row is identified by an ID which needs to be included in the URL for editing purposes. The process of creating this string occurs every time a row is selected or ...

Add a container element resembling a div inside a table without implementing the table layout

I am working with a table that is rendered by DataTable, and I have the requirement to dynamically append new elements inside the table like this: The dark grey area represents the new DOM elements that need to be inserted dynamically. The first row cont ...

Printing a webpage directly without the need for a print preview

Is there a way to automatically print a web page using JavaScript? Specifically, I want the printing process to be initiated with one click, without having to go through a print preview. The page in question contains both text and images, and I require a ...

Issue with Boostrap collapse functionality not functioning correctly on live website, although it is working as intended in local environment

I am experiencing an issue with the collapsible navbar on my website. It is not closing smoothly as it should, despite being correctly implemented. The website is built using Bootstrap 4 and Jekyll, with a gulpfile for minifying and concatenating HTML, CSS ...

When attempting to perform conditional rendering in React using a stateless functional component, I encounter an error stating "Unexpected token, expected ,"

Here is the code snippet: 'use strict' import React from 'react' import { connect } from 'react-redux' import { Panel, Col, Row, Well, Button } from 'react-bootstrap' const Cart = ({ cart }) => { const cartI ...

Establishing a client cookie will help deter any attempts at re-registering

Due to the inability to run server-side code, I am limited in implementing a PHP session for a registration form. Instead, I have opted to utilize a client cookie to ensure that each person can only register once with a unique email address. After reading ...

Latest news on KnockoutJS enhancements

Is there a way to create an HTML markup with a GIF progress bar that appears when the page is loading? I want to use Ajax to fetch data, populate the markup, and then hide the GIF. How can I achieve this functionality using KnockoutJS? var Item = functi ...

Encountering an unhandled runtime error while importing the Client component into the server component: The JSON format is invalid, with the error message stating "undefined"

I've been attempting to create a basic counter component that increments the count of a state variable when a button is clicked. To achieve this, I created a separate file named Counter.tsx and placed it in the components folder at the root of my next ...

Retrieving all raw data in jqGrid: Issues with accessing nested objects

In my grid, the data is structured as follows: Within the rows (0,1,2 and 3 objects), there are additional objects. Of particular note is an object called 'datosPersonales' ('personalData') which contains sub-objects like nombre (name) ...