2

I have created a function that completes a task when the user clicks the complete button, however, I am using a for loop to loop through the array so that it can mark it off.

Currently, what it is doing no matter what complete button I press, it marks off only the first task and not the one I want.

HTML

<!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">
    <link rel="stylesheet" href="../css/main.css">
    <script src="js/main.js" defer></script>
    <title>To Do Application</title>
</head>

<body>
    <div class="form">
        <input class ="user-input" type="text">
        <input class="date" type="date">
        <input class="time" type="time">
        <button onclick="addTask()" class="add" id="add">+</button>
    </div>

    <div class="list"></div>
    <!--
     <div class="task-content">
        <div class="task" data-id="${id}">
        <div class="new-task-created">${taskNew}</div>
        <label class="due-date">${taskDate}</label>
        <label class="due-time">${taskTime}</label>
    </div>

    <div class="atcion-buttons">
        <button onclick="editItem()" class="edit" data-id="${id}">Edit</button>
        <button onclick="deleteItem()" class="delete" data-id="${id}">Delete</button>
        <button onclick="completeItem()" class="complete" data-id="${id}">Complete</button>
    </div>
</div>
-->

</html>

JS

// variables object
const el = {
  form: document.querySelector(".form"),
  input: document.querySelector(".user-input"),
  list: document.querySelector(".list"),
  date: document.querySelector(".date"),
  time: document.querySelector(".time"),
};
//local storage key

const STORAGE_KEY = "tasks-storage-key";

//Create ID

const createId = () =>
  `${Math.floor(Math.random() * 10000)}${new Date().getTime()}`;

//variable of empty array that gets new task
let taskList = JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "[]");


function makeNewTask() {

  const data = {
    id: createId(),
    taskNew: el.input.value,
    taskDate: el.date.value,
    taskTime: el.time.value,
  };

  return data
}


//function that creates new tasks with date and time
function display() {
  const tasks = document.createElement("div");

  data = makeNewTask();

  tasks.innerHTML = `
       <div class="task-content">
        <div class="task" data-id="${data.id}">
        <div class="new-task-created">${data.taskNew}</div>
        <label class="due-date">${data.taskDate}</label>
        <label class="due-time">${data.taskTime}</label>
    </div>

    <div class="action-buttons">
        <button onclick="editItem()" class="edit" data-id="${data.id}">Edit</button>
        <button onclick="deleteItem()" class="delete" data-id="${data.id}">Delete</button>
        <button onclick="completeItem()" class="complete" data-id="${data.id}">Complete</button>
    </div>
</div>`;

  taskList.push(tasks);
  el.list.appendChild(tasks);
}

//event listner that listens for add button.
function addTask() {
  display();
}

//function that stores task list.
function storeList() {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(taskList));
}

//function that removes task from array with delete button.

function deleteItem() {
  let removeitem = document.querySelector(".task-content");
  removeitem.parentNode.removeChild(removeitem);
  localStorage.removeItem(STORAGE_KEY);
}

//function that removes stored task when deleted.

//function that that edits tasks with date and time.
function editItem(){

}

//function that that completes task.
function completeItem() {
  let taskItem = this.querySelector(".new-task-created");
  let dateItem = this.querySelector(".due-date");
  let timeItem = this.querySelector(".due-time");
  // style..
  taskItem.style.textDecoration = "line-through";
  dateItem.style.textDecoration = "line-through";
  timeItem.style.textDecoration = "line-through";
}

The end result, the complete button should mark off the task via its index and not just the top one.

Sheldon
  • 155
  • 1
  • 9
  • Does this answer your question? [What do querySelectorAll and getElementsBy\* methods return?](https://stackoverflow.com/questions/10693845/what-do-queryselectorall-and-getelementsby-methods-return) – Heretic Monkey Jun 28 '22 at 18:39
  • Immediately evident is that you do not use `i` in your loop to index anything, nor do you modify the value of `taskItem`. `document.querySelector` [returns the first Element](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) that matches the selector. So you are modifying the first one on every iteration of the loop. See also [`Document.querySelectorAll`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) – Wyck Jun 28 '22 at 18:39
  • Please add you complete code, ```makeNewTask();``` function is missing. – Nexo Jun 28 '22 at 19:09
  • Updated to my full code – Sheldon Jun 28 '22 at 19:13

1 Answers1

0

// variables object
const el = {
    form: document.querySelector(".form"),
    input: document.querySelector(".user-input"),
    list: document.querySelector(".list"),
    date: document.querySelector(".date"),
    time: document.querySelector(".time"),
  };
  //local storage key
  
  const STORAGE_KEY = "tasks-storage-key";
  
  //Create ID
  
  const createId = () =>
    `${Math.floor(Math.random() * 10000)}${new Date().getTime()}`;
  
  //variable of empty array that gets new task
  let taskList = JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "[]");
  
  
  function makeNewTask() {
  
    const data = {
      id: createId(),
      taskNew: el.input.value,
      taskDate: el.date.value,
      taskTime: el.time.value,
    };
  
    return data
  }
  
  
  //function that creates new tasks with date and time
  function display() {
    const tasks = document.createElement("div");
  
    data = makeNewTask();
  
    tasks.innerHTML = `
         <div class="task-content">
          <div class="task" data-id="${data.id}">
          <div class="new-task-created">${data.taskNew}</div>
          <label class="due-date">${data.taskDate}</label>
          <label class="due-time">${data.taskTime}</label>
      </div>
  
      <div class="action-buttons">
          <button onclick="editItem(event)" class="edit" data-id="${data.id}">Edit</button>
          <button onclick="deleteItem(event)" class="delete" data-id="${data.id}">Delete</button>
          <button onclick="completeItem(event)" class="complete" data-id="${data.id}">Complete</button>
      </div>
  </div>`;
  
    taskList.push(tasks);
    el.list.appendChild(tasks);
  }
  
  //event listner that listens for add button.
  function addTask() {
    display();
  }
  
  //function that stores task list.
  function storeList() {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(taskList));
  }
  
  //function that removes task from array with delete button.
  
  function deleteItem() {
    let removeitem = document.querySelector(".task-content");
    removeitem.parentNode.removeChild(removeitem);
    localStorage.removeItem(STORAGE_KEY);
  }
  
  //function that removes stored task when deleted.
  
  //function that that edits tasks with date and time.
  function editItem(){
  
  }
  
  //function that that completes task.
  function completeItem(event) {
    const element = event.target.closest('.task-content')
    console.log(element)
    let taskItem = element.querySelector(".new-task-created");
    let dateItem = element.querySelector(".due-date");
    let timeItem = element.querySelector(".due-time");
    // style..
    taskItem.style.textDecoration = "line-through";
    dateItem.style.textDecoration = "line-through";
    timeItem.style.textDecoration = "line-through";
  }
<!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">
    <link rel="stylesheet" href="../css/main.css">
    <script src="js/main.js" defer></script>
    <title>To Do Application</title>
</head>

<body>
    <div class="form">
        <input class ="user-input" type="text">
        <input class="date" type="date">
        <input class="time" type="time">
        <button onclick="addTask()" class="add" id="add">+</button>
    </div>

    <div class="list"></div>
    <!--
     <div class="task-content">
        <div class="task" data-id="${id}">
        <div class="new-task-created">${taskNew}</div>
        <label class="due-date">${taskDate}</label>
        <label class="due-time">${taskTime}</label>
    </div>

    <div class="atcion-buttons">
        <button onclick="editItem()" class="edit" data-id="${id}">Edit</button>
        <button onclick="deleteItem()" class="delete" data-id="${id}">Delete</button>
        <button onclick="completeItem()" class="complete" data-id="${id}">Complete</button>
    </div>
</div>
-->
</body>

</html>
Mina
  • 14,386
  • 3
  • 13
  • 26
  • Hi Mina, Thank you for that, so what would be the best approach to get each task to be completed when the complete button is pressed? – Sheldon Jun 28 '22 at 18:26
  • Hey Sheldon, You are welcome, instead of use "document", use "this" which refers to the target element, I just updated my answer, please check again, I wish that worked for you. – Mina Jun 28 '22 at 18:30
  • And I don't think you need the loop below, as you want to complete one task. – Mina Jun 28 '22 at 18:34
  • Hmm... How does `document.querySelector` "use querySelector on the target element"? – Heretic Monkey Jun 28 '22 at 18:40
  • "document.querySelector" will search on the element on all document elements, but "this.querySelector" will search on the element inside "this" which is the element that fired the event. – Mina Jun 28 '22 at 18:52
  • I am a bit confused on the ```this.querySelector``` if you look at your updated answer I do not see the ```this.querySelector``` been used in your answer, so i am not sure when ```this.querySelector``` should be used – Sheldon Jun 28 '22 at 19:01
  • I'm sorry, May I missed clicking save edits button, I just update it. – Mina Jun 28 '22 at 19:02
  • Thank you, but that does not seem to work, I get an error in the dev console saying that ```let taskItem = this.querySelector(".new-task-created");``` is giving an error ```Uncaught TypeError: this.querySelector is not a function``` – Sheldon Jun 28 '22 at 19:20
  • I updated my OP with my full code in it – Sheldon Jun 28 '22 at 19:21
  • Would you please provide the HTML code too? – Mina Jun 28 '22 at 19:23
  • updated code with HTML – Sheldon Jun 28 '22 at 19:28
  • I just update the answer, and it works, please check. – Mina Jun 28 '22 at 19:50