Tips for preventing multiple looping when dealing with dynamically generated elements in pure Javascript

Currently, I am working on creating a basic to-do list purely using JavaScript. Although I have the option to use jQuery to achieve this task easily, I want to stick to plain JavaScript.

I have successfully developed a function that adds a line-through effect as text-decoration for completed tasks. This function targets dynamically added "li" elements using querySelectorAll and loops through the selection to attach an event listener that toggles the line-through effect on click.

To ensure this function works each time a new "li" element is added to the to-do list, I call it within the same loop. However, I noticed that as the number of "li" elements grows in the list, the loop executes multiple times triggering the event repeatedly.

The objective of achieving the line-through effect is fulfilled when the loop runs an odd number of times. Conversely, an even number of iterations fails to produce the desired outcome.

I am now hoping to find a solution to this dilemma by utilizing a for loop. If that is not feasible, I would appreciate any suggestions on the best approach to accomplishing the intended result solely using vanilla JavaScript.

const arrTask = [];
    
let insertTask = document.querySelector("input");
insertTask.addEventListener("keydown", e => {
  if(e.keyCode === 13){
    arrTask.push(insertTask.value);
    insertTask.value = "";
    listTasks()
    e.preventDefault();
  }
})

const getUlist = document.querySelector("ul");

function listTasks(){
  // Add task to the list
    let task = document.createElement("li");
    task.innerHTML = `${arrTask[arrTask.length-1]}<button class="btn btn-danger deletable"><i class="fa fa-trash"></i></button>`
    getUlist.appendChild(task);
    task.classList = "list-group-item list-group-item-action taskContainer d-flex justify-content-between align-items-center";
    markTasks();
    deleteButton();
}

function markTasks(){
  // Mark done tasks
  let listItem = document.querySelectorAll(".taskContainer");
  for(item of listItem){
    item.addEventListener("click", function(){
      this.classList.toggle("mark")
      console.log(this)
    })
  }
}

You can view my code here: https://codepen.io/minatogawa/pen/oNbOqXp?editors=0011

Answer №1

When making changes to the HTML DOM, it's important to focus on the actual objects involved. By keeping references to these objects, updating and deleting them becomes much simpler and eliminates the need for searching each time. This approach also leads to cleaner and more concise code.

Below is the revised code for your task list:

// Vanilla JavaScript
const taskList = [];

const toggleInputVisibility = () => {
  let addButton = document.querySelector(".fa-plus");
  let inputField = document.querySelector(".typeTask");
  addButton.addEventListener('click', () =>{
    inputField.classList.toggle("d-none");
  })
}
toggleInputVisibility();

let newTaskInput = document.querySelector("input");
newTaskInput.addEventListener("keydown", e => {
  if(e.keyCode === 13){
    addNewTask(newTaskInput.value);  
    newTaskInput.value = "";  
    e.preventDefault();  
  }
})

const todoList = document.querySelector("ul");  

function addNewTask(text) {
  let taskItem = document.createElement("li");  
  taskItem.innerHTML = `${text}<button class="btn btn-danger deletable"><i class="fa fa-trash"></i></button>`;  
  todoList.appendChild(taskItem);  

  taskItem.className = "list-group-item list-group-item-action taskContainer d-flex justify-content-between align-items-center";
  
  taskItem.addEventListener("click", function(){  
    this.classList.toggle("mark");  
  })

  taskItem.children[0].addEventListener('click', function(){  
      todoList.removeChild(taskItem)
    })
}

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 is the best way to calculate the total of multiple columns using JavaScript and jQuery?

I am looking to modify my table that has two different columns in order to calculate the sum of both. Currently, I can only add up one column using JavaScript, and duplicating the JS code with different value names for the second column is not ideal. How c ...

Testing for undefined using the 'should' syntax in Chai

Inspired by this tutorial on testing an AngularJS app with Chai, I am trying to add a test for an undefined value using the "should" style. However, I encountered a failure when attempting this: it ('cannot play outside the board', function() { ...

The appropriate method for declaring variables in a range-based for loop

This inquiry discussed the common, idiomatic application of the range-based for loop in C++11. for (auto& elem: container) { // perform actions on elem } However, there has been uncertainty regarding the type of reference to utilize. Input iterator ...

Angular 6 is showcasing dates in a quirky manner

In my Angular app, users can enter comments. The comments are displayed automatically with the date they were added. However, there is an odd behavior that I've noticed: When a user enters a comment, the time displayed is incorrect. (Check the ...

Utilizing ng-repeat in AngularJS to retrieve API data

I am new to AngularJS and I want to utilize ng-repeat to display my records in td elements under the record section. {"Root":[{"Record":["documents.php","OSHA_lockout_regulation.pdf","LOTO_Matrix_2016.docx","LOTO_Log_2016.pdf","Sample_LOTO_policy.pdf","iL ...

First tap on Ajax

I've been attempting to implement an ajax script to refresh the content of a div. The issue I'm facing is that on the initial click of the href where I call the function, it doesn't seem to respond. However, after that first click, everythin ...

I attempted to write an AngularJS code, however, it seems to be malfunctioning

Here is a snippet from my controller.js file: angular.module("ngcribs").controller("cribsController", function($scope) { $scope.message = "Hello, world!"; }); And here is a section of my index.html file: <!DOCTYPE html> <html lang="en"&g ...

redux form has encountered an error: the element type provided is not valid, a string is expected for built-in components

While working on my stepper code, I attempted to add a radio button. However, this addition resulted in the following error. I referenced this example before implementing it. Despite that, I am still encountering errors. Could you please advise me on how ...

Fixing blurry text on canvas caused by Arbor.js mouse event issues

Currently, I am utilizing arborjs in my project. The text within the canvas is created using fillText in html5. While everything functions correctly on a Retina display MacBook, the text appears blurry. To address this, I applied the following solution: v ...

What is the best way to send multiple PHP variables to an ajax function when clicked?

I'm encountering an issue while trying to pass variables to a function in my controller using AJAX. The error message at the bottom of the image is preventing the variables from being passed successfully. My setup involves the use of the CodeIgniter ...

Exploring the integration of query parameters in Postman using mongoose

In my code, I have a driver.js file that holds a driver schema, and a driverController.js file with REST methods including GET, POST, DELETE, and PUT. What I want to achieve is to send a GET request to http://localhost:3000/drivers?available=true This re ...

Influencing the movement of one div container using another dynamic div

Apologies for the unclear title. Check out a JsFiddle DEMO to see what I mean. My goal is to move the black container as soon as it touches the red container. I want to prevent the overlap between the two and adjust the position of the red container relat ...

Guide to utilizing various functions, with equations, within a specific scope in angularJS

myApp.controller('incomeController', ['$scope', function($scope) { $scope.pay = 0; $scope.hours = 0; $scope.tax=0.19297; $scope.total = function() { return $scope.pay * $scope.hours;} $scope.taxTotal ...

Optimal techniques for leveraging CSS within Mui and Reactjs

Just starting out with mui, I'm currently working on styling CSS for mui components like so <Typography variant="h5" sx={{ fontWeight: "bold", color: "#1a759f", display: "flex", ...

I am attempting to display a JSON array in an angular application

How can I display a JSON Array on the UI using AngularJS? I have the JSON array in the controller, and I'm attempting to retrieve it in the view. Below is the code snippet of what I have implemented. Please provide feedback on whether my approach is ...

Dynamic TextField sizing

I am currently facing an issue while displaying data on a webpage using TextField component from @material-ui. Each record of data has varying lengths, making most values appear unattractive (occupying only 10% of the textfield width). Even though I am ut ...

Troubles arising when trying to import a CSS file into a React Component without resorting to

https://i.sstatic.net/fNEuU.png After exploring the latest version of create-react-app, I discovered that there is no need to use the "npm run eject" command. When I tried that in the past, I struggled to locate the webpack.js file for modifications. htt ...

JavaScript requires a function to be passed as an argument

I've been struggling to make this particular JavaScript function work, but so far I haven't had any success. Every time I try to call the confirm dialog, I keep receiving an error saying "function expected." Could someone please point out what ...

Ways to display all image sources in React

I have an object containing product information, which includes answers with associated photos. I attempted to create a method that iterates through the images array and generates image tags with the source link, but for some reason, the images are not d ...

Navigating through object keys in YupTrying to iterate through the keys of an

Looking for the best approach to iterate through dynamically created forms using Yup? In my application, users can add an infinite number of small forms that only ask for a client's name (required), surname, and age. I have used Formik to create them ...