notoriousRorious
notoriousRorious

Reputation: 134

JavaScript To Do List - Delete button is only appearing on the most recent item added

I am beginning to learn JavaScript and wanted to start a project to test myself. The classic to do list project.

I have created a function that basically pulls whatever text is in the input box and creates a new list item using that text. However, the delete button is only appearing on the most recent item in the list.

I can fix this by nesting the [var deleteButton = document.createElement('button');] (line 4) within the function, but when I do this the delete button no longer functions!

Any help at all would be really appreciated. (also, I know that is is not mobile responsive yet, I am planning to work on all of that after getting the functionality nailed).

Code:

$(document).ready(function() {
  var submitButton = $('#taskEntryButton');
  var taskEntry = $('#taskEntryField');
  var deleteButton = document.createElement('button');


  function submitFunction() {
    // get the input value and put it into a variable
    var newTaskContent = $('#taskEntryField').val();
    // create a new list item
    var newListItem = document.createElement('li');
    // create a new checkbox for the new list item
    var newCheckbox = document.createElement('INPUT');
    newCheckbox.setAttribute('type', 'checkbox');
    newListItem.appendChild(newCheckbox);
    newCheckbox.setAttribute('class', '.activeCheckBox');
    // create a new 'label' in the list item
    var label = document.createElement('label');
    label.innerText = newTaskContent;
    newCheckbox.after(label);
    // create a new div for the delete button
    var buttonHolder = document.createElement('div');
    buttonHolder.setAttribute('class', '.newButtonHolder');
    label.after(buttonHolder);
    // create the delete button
    deleteButton.setAttribute('class', '.delete');
    deleteButton.innerText = "Delete";
    buttonHolder.appendChild(deleteButton);
    // insert the new list item into the list (at the top)
    $('#activeTaskList').prepend(newListItem);
    // reset text box
    taskEntry.val("");
  };

  submitButton.click(submitFunction);

  // make function execute on enter
  taskEntry.keypress(function(event) {
    if (event.keyCode === 13) {
      // Cancel the default action, if needed
      event.preventDefault();
      submitFunction();
      // reset text box
      taskEntry.val("");
    }
  });

  // set up the delete button
  deleteButton.addEventListener("click", deleteItem);
  //delete function
  function deleteItem() {
    // grab list item (button -> div -> li)
    let item = this.parentNode.parentNode;
    // here i select the ul
    let parent = item.parentNode;
    //remove li from ul
    parent.removeChild(item);
  };

  // here i make the 2 tab buttons show the relevent tab
  var activeTabButton = document.getElementById('activeButton');
  var completedTabButton = document.getElementById('completedButton');
  var activeTab = document.getElementById('activeTasks');
  var completedTab = document.getElementById('completedTasks');

  activeTabButton.addEventListener("click", function() {
    if (activeTab.style.display !== "block") {
      activeTab.style.display = "block";
      completedTab.style.display = "none";
    };
  });

  completedTabButton.addEventListener("click", function() {
    if (completedTab.style.display !== "block") {
      completedTab.style.display = "block";
      activeTab.style.display = "none";
    };
  });


});
* {
  font-family: 'Karla', sans-serif;
}

body {
  background-color: rgb(226, 217, 198);
}

.wrapper {
  width: 100%;
  height: 100vh;
  display: flex;
}

#container {
  background-color: #ffe8aa;
  width: 30%;
  height: 650px;
  margin-left: auto;
  margin-right: auto;
  align-self: center;
  border-radius: 20px;
}

#header {
  height: 170px;
  background-color: rgb(255, 189, 113);
  display: flex;
  flex-direction: column;
  align-items: center;
  border-radius: 20px 20px 0px 0px;
}

.tabsButton {
  font-size: 1.2em;
  width: 150px;
  text-align: center;
  border-style: none;
  margin-left: 10px;
  margin-right: 10px;
}

#taskEntryContainer {
  margin-top: auto;
  margin-bottom: auto;
  display: flex;
}

#taskEntryField {
  font-size: 1.2em;
}

#taskEntryButton {
  margin-left: 50px;
  font-size: 1.2em;
}


/* Task Lists */

#mainSection {
  width: 100%;
}

#toDoListContainer {
  width: 100%;
  overflow: hidden;
  border-radius: 0px 0px 20px 20px;
}

.taskList {
  width: 100%;
  list-style: none;
  font-size: 1.5em;
}

.taskList li {
  width: 86%;
  display: flex;
  align-items: baseline;
  padding: 2%;
  box-sizing: border-box;
  border-radius: 10px;
  margin-bottom: 20px;
  background-color: #ffc038;
}

.taskList li label {
  margin-left: 30px;
  width: 75%;
}

.taskList button {
  border-style: none;
  background-color: #494949;
  font-size: 0.7em;
  color: white;
}


/* Active Tasks */

#activeTasks {
  display: block;
  z-index: 3;
}


/* Completed Tasks */

#completedTasks {
  display: none;
  z-index: 3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>To Do List</title>
  <link href="styles.css" rel="stylesheet">
  <script src="../jquery-3.5.1.js"></script>
  <script src="scripts.js"></script>

  <!-- Google Fonts -->
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Karla&display=swap" rel="stylesheet">

</head>

<body>
  <div class="wrapper">
    <div id="container">
      <div id="header">
        <div id="toDoTabs">
          <button class="tabsButton" id="activeButton">Active</button>
          <button class="tabsButton" id="completedButton">Completed</button>
        </div>
        <div id="taskEntryContainer">
          <input type="text" id="taskEntryField" input="" placeholder="Enter a new task...">
          <button id="taskEntryButton">Submit</button>
        </div>
      </div>
      <div id="mainSection">
        <div id="toDoListContainer">
          <div id="activeTasks">
            <ul class="taskList" id="activeTaskList">
            </ul>
          </div>
          <div id="completedTasks">
            <ul class="taskList" id="completedTaskList">
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

Upvotes: 3

Views: 936

Answers (2)

gaetanoM
gaetanoM

Reputation: 42054

You create the button outside the submitFunction function and use it more and more.

Move this line:

var deleteButton = document.createElement('button');

after:

// create the delete button

And, move also the event listener immediately after:

deleteButton.addEventListener("click", deleteItem);

Another solution is to create a clone of your button in your submitFunction using:

Node.cloneNode(): plain javascript

.clone(): using jQuery

The snippet:

$(document).ready(function() {
    var submitButton = $('#taskEntryButton');
    var taskEntry = $('#taskEntryField');



    function submitFunction() {
        // get the input value and put it into a variable
        var newTaskContent = $('#taskEntryField').val();
        // create a new list item
        var newListItem = document.createElement('li');
        // create a new checkbox for the new list item
        var newCheckbox = document.createElement('INPUT');
        newCheckbox.setAttribute('type', 'checkbox');
        newListItem.appendChild(newCheckbox);
        newCheckbox.setAttribute('class', '.activeCheckBox');
        // create a new 'label' in the list item
        var label = document.createElement('label');
        label.innerText = newTaskContent;
        newCheckbox.after(label);
        // create a new div for the delete button
        var buttonHolder = document.createElement('div');
        buttonHolder.setAttribute('class', '.newButtonHolder');
        label.after(buttonHolder);
        // create the delete button
        var deleteButton = document.createElement('button');  // MOVE HERE
        // set up the delete button
        deleteButton.addEventListener("click", deleteItem);
        
        deleteButton.setAttribute('class', '.delete');
        deleteButton.innerText = "Delete";
        buttonHolder.appendChild(deleteButton);
        // insert the new list item into the list (at the top)
        $('#activeTaskList').prepend(newListItem);
        // reset text box
        taskEntry.val("");
    };

    submitButton.click(submitFunction);

    // make function execute on enter
    taskEntry.keypress(function(event) {
        if (event.keyCode === 13) {
            // Cancel the default action, if needed
            event.preventDefault();
            submitFunction();
            // reset text box
            taskEntry.val("");
        }
    });

    
    //delete function
    function deleteItem() {
        // grab list item (button -> div -> li)
        let item = this.parentNode.parentNode;
        // here i select the ul
        let parent = item.parentNode;
        //remove li from ul
        parent.removeChild(item);
    };

    // here i make the 2 tab buttons show the relevent tab
    var activeTabButton = document.getElementById('activeButton');
    var completedTabButton = document.getElementById('completedButton');
    var activeTab = document.getElementById('activeTasks');
    var completedTab = document.getElementById('completedTasks');

    activeTabButton.addEventListener("click", function() {
        if (activeTab.style.display !== "block") {
            activeTab.style.display = "block";
            completedTab.style.display = "none";
        };
    });

    completedTabButton.addEventListener("click", function() {
        if (completedTab.style.display !== "block") {
            completedTab.style.display = "block";
            activeTab.style.display = "none";
        };
    });


});
* {
    font-family: 'Karla', sans-serif;
}

body {
    background-color: rgb(226, 217, 198);
}

.wrapper {
    width: 100%;
    height: 100vh;
    display: flex;
}

#container {
    background-color: #ffe8aa;
    width: 30%;
    height: 650px;
    margin-left: auto;
    margin-right: auto;
    align-self: center;
    border-radius: 20px;
}

#header {
    height: 170px;
    background-color: rgb(255, 189, 113);
    display: flex;
    flex-direction: column;
    align-items: center;
    border-radius: 20px 20px 0px 0px;
}

.tabsButton {
    font-size: 1.2em;
    width: 150px;
    text-align: center;
    border-style: none;
    margin-left: 10px;
    margin-right: 10px;
}

#taskEntryContainer {
    margin-top: auto;
    margin-bottom: auto;
    display: flex;
}

#taskEntryField {
    font-size: 1.2em;
}

#taskEntryButton {
    margin-left: 50px;
    font-size: 1.2em;
}


/* Task Lists */

#mainSection {
    width: 100%;
}

#toDoListContainer {
    width: 100%;
    overflow: hidden;
    border-radius: 0px 0px 20px 20px;
}

.taskList {
    width: 100%;
    list-style: none;
    font-size: 1.5em;
}

.taskList li {
    width: 86%;
    display: flex;
    align-items: baseline;
    padding: 2%;
    box-sizing: border-box;
    border-radius: 10px;
    margin-bottom: 20px;
    background-color: #ffc038;
}

.taskList li label {
    margin-left: 30px;
    width: 75%;
}

.taskList button {
    border-style: none;
    background-color: #494949;
    font-size: 0.7em;
    color: white;
}


/* Active Tasks */

#activeTasks {
    display: block;
    z-index: 3;
}


/* Completed Tasks */

#completedTasks {
    display: none;
    z-index: 3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Karla&display=swap" rel="stylesheet">
<div class="wrapper">
    <div id="container">
        <div id="header">
            <div id="toDoTabs">
                <button class="tabsButton" id="activeButton">Active</button>
                <button class="tabsButton" id="completedButton">Completed</button>
            </div>
            <div id="taskEntryContainer">
                <input type="text" id="taskEntryField" input="" placeholder="Enter a new task...">
                <button id="taskEntryButton">Submit</button>
            </div>
        </div>
        <div id="mainSection">
            <div id="toDoListContainer">
                <div id="activeTasks">
                    <ul class="taskList" id="activeTaskList">
                    </ul>
                </div>
                <div id="completedTasks">
                    <ul class="taskList" id="completedTaskList">
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>

Upvotes: 1

dev.dmtrllv
dev.dmtrllv

Reputation: 71

You should indeed create the button inside the submit function and then add the click event handler to that button (also inside the submit function). Because you only created the button once, every time when you append that button to some element it will just "move" the element.

$(document).ready(function() {
      var submitButton = $('#taskEntryButton');
      var taskEntry = $('#taskEntryField');


      function submitFunction() {
        // get the input value and put it into a variable
        var newTaskContent = $('#taskEntryField').val();
        // create a new list item
        var newListItem = document.createElement('li');
        // create a new checkbox for the new list item
        var newCheckbox = document.createElement('INPUT');
        newCheckbox.setAttribute('type', 'checkbox');
        newListItem.appendChild(newCheckbox);
        newCheckbox.setAttribute('class', '.activeCheckBox');
        // create a new 'label' in the list item
        var label = document.createElement('label');
        label.innerText = newTaskContent;
        newCheckbox.after(label);
        // create a new div for the delete button
        var buttonHolder = document.createElement('div');
        buttonHolder.setAttribute('class', '.newButtonHolder');
        /**
        * NOTE HERE!!!
        **/
        var deleteButton = document.createElement("button");
        // set up the delete button
        deleteButton.addEventListener("click", deleteItem);
          //delete function
          function deleteItem() {
          // grab list item (button -> div -> li)
          let item = this.parentNode.parentNode;
          // here i select the ul
          let parent = item.parentNode;
          //remove li from ul
          parent.removeChild(item);
        };
        
        label.after(buttonHolder);
        // create the delete button
        deleteButton.setAttribute('class', '.delete');
        deleteButton.innerText = "Delete";
        buttonHolder.appendChild(deleteButton);
        // insert the new list item into the list (at the top)
        $('#activeTaskList').prepend(newListItem);
        // reset text box
        taskEntry.val("");
      };

      submitButton.click(submitFunction);

      // make function execute on enter
      taskEntry.keypress(function(event) {
        if (event.keyCode === 13) {
          // Cancel the default action, if needed
          event.preventDefault();
          submitFunction();
          // reset text box
          taskEntry.val("");
        }
      });

      

      // here i make the 2 tab buttons show the relevent tab
      var activeTabButton = document.getElementById('activeButton');
      var completedTabButton = document.getElementById('completedButton');
      var activeTab = document.getElementById('activeTasks');
      var completedTab = document.getElementById('completedTasks');

      activeTabButton.addEventListener("click", function() {
        if (activeTab.style.display !== "block") {
          activeTab.style.display = "block";
          completedTab.style.display = "none";
        };
      });

      completedTabButton.addEventListener("click", function() {
        if (completedTab.style.display !== "block") {
          completedTab.style.display = "block";
          activeTab.style.display = "none";
        };
      });


    });
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
  <div class="wrapper">
    <div id="container">
      <div id="header">
        <div id="toDoTabs">
          <button class="tabsButton" id="activeButton">Active</button>
          <button class="tabsButton" id="completedButton">Completed</button>
        </div>
        <div id="taskEntryContainer">
          <input type="text" id="taskEntryField" input="" placeholder="Enter a new task...">
          <button id="taskEntryButton">Submit</button>
        </div>
      </div>
      <div id="mainSection">
        <div id="toDoListContainer">
          <div id="activeTasks">
            <ul class="taskList" id="activeTaskList">
            </ul>
          </div>
          <div id="completedTasks">
            <ul class="taskList" id="completedTaskList">
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

Upvotes: 1

Related Questions