Updating the first item in a todo list using JavaScript without affecting the rest of the items

I'm currently working on developing a JavaScript todo list. Despite my limited experience with JavaScript, I have been facing a recurring issue for several days now. Every time I attempt to update the data in my todo list, it always updates the information of the first list item instead of the one I intended to modify. If anyone could provide a solution to this problem, I would greatly appreciate it.

Below is a snippet of my code:

window.addEventListener('load', () => {
  const form = document.querySelector("#form");
  const input_text = document.querySelector("#text");
  const list_ele = document.querySelector(".tasks");
  const add = document.querySelector(".add-task");

  form.addEventListener('submit', (e) => {

    e.preventDefault();
    let text = input_text.value;

    let task = document.createElement("div");
    task.classList.add("task");

    let task_content = document.createElement("div");
    task_content.classList.add("content");
    task.appendChild(task_content);

    let output = document.createElement("input");
    output.classList.add("task-added")
    output.value = text;
    output.type = "text";
    output.setAttribute("readonly", "readonly");

    task_content.appendChild(output);

    let actions = document.createElement("div");
    actions.classList.add("actions");
    task.appendChild(actions);

    let edit = document.createElement("button");
    edit.classList.add("edit");
    edit.innerHTML = "Edit";
    actions.appendChild(edit);

    let DELETE = document.createElement("button");
    DELETE.classList.add("delete");
    DELETE.innerHTML = "Delete";
    actions.appendChild(DELETE);
    if (add.value === "add-task")
      list_ele.appendChild(task);
    input_text.value = "";

    edit.addEventListener('click', (e) => {
      add.value = "Save";
      input_text.focus();
      input_text.value = output.value;
      add.addEventListener('click', () => {
        if (add.value === "Save") {
          let targets = e.target;
          targets.parentElement.previousElementSibling.firstElementChild.value = input_text.value;
          add.value = "add-task";
          input_text.value = "";
        }
      });
    });
  })
})
* {
  box-sizing: border-box;
}

body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background-color: rgba(255, 255, 255, 0.918);
}

header {
  display: flex;
  flex-direction: column;
  gap: 20px;
  justify-content: center;
  align-items: center;
}

#form {
  display: flex;
  gap: 5px;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

header h1 {
  color: orangered;
}

#form #text {
  padding: 10px;
  border-radius: 10px;
  background-color: orange;
  color: black;
  border: none;
  outline: none;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  -ms-border-radius: 10px;
  -o-border-radius: 10px;
}

#form .add-task {
  padding: 10px;
  border: none;
  outline: none;
  border-radius: 10px;
  color: black;
  background-color: orangered;
  cursor: pointer;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  -ms-border-radius: 10px;
  -o-border-radius: 10px;
}

.tasks {
  display: flex;
  gap: 5px;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.task {
  padding: 20px;
  display: flex;
  background-color: orangered;
  gap: 10px;
  border-radius: 5px;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
}

.task .content .task-added {
  outline: none;
  border: none;
  color: black;
  padding: 10px;
  border-radius: 5px;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
}

.task .content .task-added:not(:read-only) {
  color: rgb(247, 2, 2);
}

.task .actions .edit {
  cursor: pointer;
  outline: none;
  background-color: black;
  border-radius: 5px;
  padding: 10px;
  border: none;
  color: orangered;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
}

.task .actions {
  display: flex;
  flex-direction: row;
  gap: 10px;
}

.task .actions .delete {
  cursor: pointer;
  background-color: black;
  outline: none;
  border-radius: 5px;
  padding: 10px;
  border: none;
  color: orangered;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
}
<header id="header">
  <h1>Todo-list</h1>
  <form id="form">
    <input type="text" id="text" required>
    <input type="submit" class="add-task" value="add-task">
  </form>

</header>
<section>
  <div class="tasks">
    <h2>Tasks</h2>
    <!--<div class="task">
            <div class="content">
                <input type="text" class="task-added" readonly>
            </div>
            <div class="actions">
                <input type="button" class="edit" value="Edit">
                <input type="button" class="delete" value="Delete">
            </div>
         </div>
         !-->
  </div>
</section>

Answer №1

After completing the editing process, it is important to remove the click event listener on the add/edit button. See the remarks in the revised code below:

edit.addEventListener('click', (e) => {
  add.value = "Save";
  input_text.focus();
  input_text.value = output.value;
  const onFinishHandler = () => { // <-------- store handler in a variable
    if (add.value === "Save") {
      output.value = input_text.value; // <------------ simplify node access
      add.value = "add-task";
      input_text.value = "";
      add.removeEventListener('click', onFinishHandler) // <------ disable listener through variable once done
    }
  };
  add.addEventListener('click', onFinishHandler);
})

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

My preference is for the flex box to expand in width (sideways) without increasing in height (up and down)

Is there a way for flex items to expand in width but only in height when necessary? I enjoy using flexbox, but I find it frustrating that all flex items in a row grow to the same height even when there isn't enough content to fill them, resulting in a ...

What is the conventional method for organizing forms in ASP.Net?

Here's my forms layout: <body> <p>Please note that this form is solely for illustrating the Required Field Validator and does not perform any actual function.</p> <form id="frmValidator" method="post" runat=" ...

Differentiating between parsing functions stored as strings in object literals/JSON syntax involves identifying each function's unique characteristics

While there is a similar question (here), the answers provided do not exactly address my query. The accepted answer included invalid JSON (forcing the use of eval()), which seems to be an impossible solution as far as I know. I intend to utilize code from ...

Having Trouble with the Bootstrap Responsive Menu Button Not Working

I'm struggling with the Bootstrap menu I created, as it's not collapsing or animating. Everything seems to be working fine except for the button that isn't functioning. <nav class="navbar navbar-expand-lg navbar-light bg-dark alb ...

Issues arise with animated content when viewed on browsers other than Chrome

After coding some jQuery, I noticed that the animation is working properly in Chrome but not in IE (version 11.0) or Firefox (32.0.3). Additionally, I found that if I omit 'opacity: 1;' from my animation class, the element will revert back to it ...

Element receives scrollbar upon reaching 100% width

I am intrigued as to why the overflow: auto; rule is causing a scrollbar to appear in this particular scenario CSS: textarea { width: 100%; margin:0; padding:0; } .span4 { width: 300px; } aside { overflow: auto; } html: <asid ...

Using javascript to generate fresh dictionaries

Struggling to translate a C# "function" into JavaScript - any advice or tips? Here is the C# snippet: var parameters = new Dictionary<string,string> { { "link", "http://mysite.com" }, { "name", "This is an test" } }; I believe I need to ut ...

Creating a barrier between objects in motion

I need assistance with creating a connection between two dynamic vertices in my project. The information for each vertex is stored within an object named object, containing the position data as a THREE.Vector3. To create the line connecting these vertices ...

Tips for dissecting complex JSONP structures with JavaScript

I have recently come across a valid jsonp structure that I am attempting to parse. However, I am struggling to figure out how to access the videos elements within it. Can anyone provide guidance on how to reference these elements (sources, thumb, title) in ...

I am not receiving the correct values when passing an array of objects as props

I am trying to create a progress bar using two components. Below is my chart component: import Bar from "./Bar"; const INIT_MONTH_EXPENSES = [ { label: "Jan", value: 0 }, { label: "Feb", value: 0 }, { label: "Mar&q ...

Issue with embedding Instagram on Safari browser

My challenge involves dynamically creating an Instagram feed using AJAX. After encountering rendering issues, I turned to research and stumbled upon the following helpful response: The solution proposed was to call this line of code... window.instgrm.Emb ...

add the current item in front of the last one

My goal is to determine if an element is the last one in the container div by checking the length of the next element with the class .item. If this next element exists, it means that I am not currently at the end of the container div. if($(this).next(&apo ...

Triggering the full-screen event for HTML video in Android using the WebKit

Having an issue with the android webkit drawing the video element. I am trying to detect when the video transitions to fullscreen mode upon clicking the fullscreen button located at the bottom right of the video element, but I am unable to do so. There doe ...

"Trouble with script: external JavaScript file failing to run

The issue lies in the fact that the specified external JavaScript file is not being executed: <script src="//www.google-analytics.com/cx/api.js?experiment=YOUR_EXPERIMENT_ID"></script> Even when I try to directly access the URL, it downloads ...

Stretching the Mantine Accordion Section

The Mantine accordion requires that its content be of type Accordion.Item, as indicated in the documentation for the children props. This means that even functions returning AccordionItem will not be recognized. Therefore, only AccordionItem(s) created in ...

Angular 6 seems to be having issues loading Bootstrap

I've run into an issue while trying to incorporate Bootstrap into Angular 6. I have already installed Bootstrap using npm install bootstrap and added it to angular.json, but it's still not functioning. Is there something else I should be doing? A ...

Eliminate the blank choice from X-editable Select

Lately, I've been dealing with AngularJS and X-editable and one thing that has been troubling me is the fact that the select option always includes an empty first child. Here's the HTML <span editable-select="curuser.roles" e-name="roles" ...

Is it possible to utilize a relative <a href="#foo">link and navigate to a specific anchor on the same page even when the <base> element is in use?

Suppose I have a page www.example1.com/foo/test.html that includes the code below: <head> <base href=http://www.example2.com/> </head> <body> <a href=#foo>foo</a> ... <a name=foo /> </body> When I click on " ...

Is it possible to prevent an iFrame from loading its src until a certain function is triggered?

Currently, my webpage has multiple iFrames that are being populated with sources dynamically. However, the page's performance is suffering due to all iframes loading simultaneously. To improve this, I want to delay the loading of these iframes until a ...

The CSS file is causing the footer to be cut off from the page and

My webpage is not scrolling properly when I add a lot of content, causing the footer to get cut off. I have tried various solutions found in other questions, but none have worked for me. Can anyone offer any suggestions or advice to fix this issue? html ...