What is the best way to delete HTML classes that were generated by a function?

Currently, I'm immersed in the Etch A Sketch project as part of my journey through The Odin Project. Using DOM manipulation, I successfully created a grid and displayed it on the screen. Now, my aim is to allow users to resize the grid by removing the existing one and replacing it with a new grid based on their input.

The challenge arises when I realize that the elements associated with the grid creation are not easily accessible due to scoping issues. I attempted to remove the vertical boxes using `verticalBoxes.remove()` within the `resizeGrid()` function, but it failed since this action wasn't in the global scope. My next approach involved removing the container within `resizeGrid()` and creating a new one, which led to declaration conflicts resulting from duplicate variables.

<!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>Etch A Sketch</title>
    <link rel="stylesheet" href="styles.css">
    <script src= "scripts.js" defer></script>
    
</head>
<body>
    <h1>Etch A Sketch</h1>
    <div id= "container"></div>
    <div id= "grid-size">
        <button type="confirm" id= "resize-button">Resize Grid</button>
    </div>
        
</body>
</html>
#container {
    margin: auto;    
    max-width: 500px;
    max-height: 500px;
}

h1 {
    text-align:center;
}

.row {
    display:flex;
    height: auto;
}

.column {
    flex: 1;
    width: 100%;
    aspect-ratio: 1;
    border: 1px solid black;
}

.resize-button {
    display: inline-block;
    width:50px;
    height:50px;    
}
let container = document.querySelector("#container");
const button = document.querySelector("#resize-button")
function createGrid(num) {

    for (let i = 0; i < num; i++) {

    let horizontalBoxes = document.createElement("div"); 
    container.appendChild(horizontalBoxes);
    horizontalBoxes.classList.add("row");

        for (let y = 0; y < num; y++) {

            let verticalBoxes = document.createElement("div"); 
            horizontalBoxes.appendChild(verticalBoxes); 
            verticalBoxes.classList.add("column");
            verticalBoxes.addEventListener('mouseover', colorChange);
            
        }
    }   
}

function colorChange () {
    this.style.backgroundColor = "black"
    }  

createGrid(16);

function resizeGrid(newSize) {
    newSize = prompt("What size would you like the grid to be? (1-100)");
    createGrid(newSize);
}
button.addEventListener('click', resizeGrid);


Answer №1

Is there a way to remove the elements linked to my grid without disrupting the loop?

To maintain the loop, clear the contents of container before adding new elements.

For different methods to accomplish this, refer to Remove all child elements of a DOM node in JavaScript.

The sample script demonstrated below utilizes

container.textContent = '';

let container = document.querySelector("#container");
const button = document.querySelector("#resize-button");

function resizeGrid() {
  let newSize = parseInt(prompt("What size would you like the grid to be? (1-100)"));
  if (0 < newSize && newSize < 101)
    createGrid(newSize);
}

button.addEventListener('click', resizeGrid);

function createGrid(num) {
  container.textContent = '';

  for (let i = 0; i < num; i++) {
    let horizontalBoxes = document.createElement("div");

    horizontalBoxes.classList.add("row");

    container.appendChild(horizontalBoxes);

    for (let y = 0; y < num; y++) {
      let verticalBoxes = document.createElement("div");

      verticalBoxes.classList.add("column");
      verticalBoxes.addEventListener('mouseover', colorChange);

      horizontalBoxes.appendChild(verticalBoxes);
    }
  }
}

function colorChange() {
  this.style.backgroundColor = "black"
}

createGrid(16);
#container {
    margin: auto;
    max-width: 500px;
    max-height: 500px;
}

h1 {
    text-align:center;
}

.row {
    display:flex;
    height: auto;
}

.column {
    flex: 1;
    width: 100%;
    aspect-ratio: 1;
    border: 1px solid black;
}

.resize-button {
    display: inline-block;
    width:50px;
    height:50px;
}
<!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>Etch A Sketch</title>
  <link rel="stylesheet" href="styles.css">
</head>

<body>
  <h1>Etch A Sketch</h1>
  <div id="container"></div>
  <div id="grid-size">
    <button type="confirm" id="resize-button">Resize Grid</button>
  </div>
</body>

</html>

Answer №2

Do you think that using replaceChildren() would be a perfect solution for your needs?

You can simply create new nodes and then use replaceChildren to add them all while removing the connection between the parent and the old child nodes.

By implementing this approach, I believe your createGrid() function would resemble the following:

function createGrid(num) {
    const newHorizontalBoxesList =[]
    
    for (let i = 0; i < num; i++) {
    let horizontalBox = document.createElement("div"); 
    newHorizontalBoxesList.push(horizontalBox)
    horizontalBox.classList.add("row");

        for (let y = 0; y < num; y++) {

            let verticalBox = document.createElement("div"); 
            horizontalBox.appendChild(verticalBox); 
            verticalBox.classList.add("column");
            verticalBox.addEventListener('mouseover', colorChange);
            
        }
    }
    container.replaceChildren(...newHorizontalBoxesList);
}

Keep in mind that replaceChildren() requires consecutive arguments rather than a single array of new children, which is why we are using spread syntax.

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

The functionality of Protovis JavaScript is not supported within a dropdownlist's onchange event

I encountered an issue where one block of code works fine on its own, but when combined with another block, only one of them functions properly. The problem arises when I try to invoke a method from a dropdownlist using the onchange event, especially afte ...

The encoding of Node.js using npm

Looking to install the validate .json file below using npm: { "name": "node-todo", "version": "0.0.0", "description": "Simple todo application", "main": "server.js", "dependencies": { "express": "~3.4.4", "mongoose": "~ ...

The Console.log() function displays the current state and value of a promise object within the Q library

Whenever I attempt to print a promise object from Q, the result that I receive is as follows: var Q = require('q'); var defaultPromise = new Q(); console.log('defaultPromise', defaultPromise); defaultPromise { state: 'fulfilled& ...

Zooming on a webpage is causing problems

One issue I'm facing is with the elements on my page acting strange when I zoom in and out. Everything seems to be working fine except for a container div that should overlay a color over the image background. When I zoom in or switch to mobile view, ...

Extracting multiline value from a textarea using JavaScript

I'm trying to extract a multiline value from a textarea using JavaScript or jQuery and store it in a cookie. Below is the code snippet I am using: HTML: <textarea id="cont" cols="72" rows="15"> JavaScript: var txt = $('#cont').val( ...

method for sorting labels in Select element in ReactJS

Hey there, I'm facing an issue with the code snippet available here. I would really appreciate it if you could assist me in resolving this problem. This is the code: import React from "react"; import { Select } from "antd" ...

A step-by-step guide to thoroughly examining the form status in a React application, allowing for the activation of a previously disabled submit button

When I have an onChange event in React, the state is populated correctly. I disable the form button when a field is empty on submit, but I also want users to be able to go back and fill out those fields. The key issue is that if both fields have data, I wa ...

What is the best way to determine the left and top coordinates when resizing a draggable image within a container?

I am struggling to correctly scale the image and set the left (x) and top (y) positions. Here is the code from my template: <div id="container" :style="`height: ${height}px;width: ${size}px;overflow: hidden;position: relative;`"> ...

Radio buttons failing to transfer any data

I am experiencing an issue with setting values for radio buttons and using the $_POST variable to read the value, but the value being set is empty. <form style="text-align:left;margin-left:80px;" class="form-inline signup" role="form" method="post" act ...

Within the ng-repeat loop, every switch button undergoes a status change

Utilizing ng-repeat, I have implemented a feature to display multiple content with on/off buttons. However, when toggling the off button for a specific content, all button states are being changed instead of just the selected one. <div ng-repeat="setti ...

Using Jest functions as object properties results in undefined behavior

I am faced with a challenge in my class where I need to mock an object along with its properties intercept(context: ExecutionContext) { const response = contect.switchToHttp().getResponse() // the chain that needs to be mocked if (response.headersSent ...

What is the best way to use requests in python to enter text in a textarea, then scrape the html with bs4, all while the input remains hidden?

I'm working on a script that interacts with by sending a string and receiving one or all of the "fancy text" variations provided by the site. I am struggling to identify the input area within the HTML structure, especially since I aim to use requests ...

Ways to change the color of a button when it is clicked?

I am attempting to change the color of a button on another button click, but it doesn't seem to be working. function show_col(){ console.log("hello"); var path=localStorage.getItem(".physics_section #color1 button"); $(''+ ...

Unable to trap error using try-catch block within an asynchronous function

I'm attempting to integrate a try-catch block into an async function, but I am having trouble catching errors with status code 400 using the code below. const run = async () => { const response = await client.lists.addListMember(listId, { ema ...

Utilizing the useEffect hook with outdated information

As I was learning about react hooks, I encountered a perplexing issue that I can't quite grasp. My goal is to create a list of numbers that can be incremented and should always display in descending order. However, when I input a high number initially ...

What is the syntax for requesting a JSONArray in an Ajax call using jQuery?

After browsing through numerous resources like this, this, and this, I finally landed on this. The main objective is to iterate over the JSON data returned from an Ajax call, which is encoded using json_encode in PHP. When I inspect the object using cons ...

Why hasn't the string been properly encoded?

Consider the scenario below: string text = "this is an example of formatted \"string\""; When I display this as a plain string in my web API method: return Ok(text) it will output: this is an example of formatted "s ...

Retrieve the reference to the plugin object from the element where the plugin is currently active

Take a look at the code below. I've implemented a jquery plugin called myPlugin to modify the UI of #targetElement. var myPluginVar = $('#targetElement').myPlugin(); I have created a button and attached a click event listener to it. $(&ap ...

Javascript and iframes may encounter compatibility issues with browsers other than Internet Explorer

My HTML file includes an iframe and JavaScript that function correctly in IE Browser, but they do not work in other browsers such as Safari and Firefox. When using Safari, only the iframe box is displayed without showing the content inside it. I am curio ...

Array filtering functions similarly to marketplace filtering tools

In order to make the filter function like a marketplace filter, I want to only see items related to the selected brand and status. For example: partners = [ 0:{ year: "2022" badge_status: "badge-success" sale_date: "01/07/2022&quo ...