0

I have recently started learning Javascript and I am currently building a program where you can add TODOs and then complete them. However, I am not able to use the addEventlistener() method.

The idea is that when you click done!, one of the TODOs disappears and the number of unchecked TODOs decreases by 1. However, when I try to add a button to complete a TODO, the button doesn't work. I have tried changing many things but the result is the same, the addEventlistener does not seem to call the done() function.

What should I do???

const classNames = {
  TODO_ITEM: 'todo-container',
  TODO_CHECKBOX: 'todo-checkbox',
  TODO_TEXT: 'todo-text',
  TODO_DELETE: 'todo-delete',
}
let uncheckedItems = 0
let itemNumber = 0
const list = document.getElementById('todo-list')
const itemCountSpan = document.getElementById('item-count')
const uncheckedCountSpan = document.getElementById('unchecked-count')

var button = document.createElement('button')
button.innerHTML = 'Done!'


// 3. Add event handler


button.addEventListener("click", done)

function done() {
  uncheckedItems -= 1
  uncheckedCountSpan = uncheckedItems
}

function newTodo() {
  increment()
  newItem()
}


function increment() { // this function increases the number of total TODOs and of unchecked TODOs
  itemNumber += 1
  uncheckedItems += 1
  itemCountSpan.innerHTML = itemNumber
  uncheckedCountSpan.innerHTML = uncheckedItems
}

function newItem() {
  list.innerHTML += classNames.TODO_TEXT
  list.appendChild(button)
  list.innerHTML += "<br>"

}
* {
  box-sizing: border-box;
}

html,
body {
  background-color: #eee;
  margin: 0;
  padding: 0;
}

ul {
  margin: 0;
  padding: 0;
  list-style-type: none;
}

.center {
  align-self: center;
}

.flow-right {
  display: flex;
  justify-content: space-around;
}

.container {
  max-width: 800px;
  margin: 0 auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  background-color: white;
  height: 100vh;
}

.title,
.controls,
.button {
  flex: none;
}

.button {
  padding: 10px 20px;
}

.todo-list {
  flex: 1 1 0;
  margin-top: 20px;
  padding: 20px;
  overflow-y: auto;
  margin-left: 20%;
}

.todo-delete {
  margin: 10px;
}

.todo-checkbox {
  margin: 10px;
}

.todo-container {
  padding: 20px;
  border-bottom: 1px solid #333;
}

.todo-container:first-of-type {
  border-top: 1px solid #333;
}

button {
  float: right;
  margin-right: 0%;
}
<html>

<head>
  <title>TODO App</title>
  <link rel="stylesheet" type="text/css" href="./styles.css" />
</head>

<body>
  <div class="container center">
    <h1 class="center title">My TODO App</h1>
    <div class="flow-right controls">
      <span>Item count: <span id="item-count">0</span></span>
      <span>Unchecked count: <span id="unchecked-count">0</span></span>
    </div>

    <button class="button center" onClick="newTodo()">New TODO</button>
    <ul id="todo-list" class="todo-list"></ul>
  </div>
  <script src="./script.js"></script>
</body>

</html>
Alexoort
  • 3
  • 2

2 Answers2

-1

did you add your button to DOM ? I see that you listen click on button which created but not appended to DOM.

Try todoList.prepend(button)

Max Ivanov
  • 133
  • 1
  • 9
-1

You should delegate

Here I also append a LI for the todo and remove the button when done

And I create a button per LI

There was some funky CSS going on so I added

.todo-list li { padding:3px }

Working example

const classNames = {
  TODO_ITEM: 'todo-container',
  TODO_CHECKBOX: 'todo-checkbox',
  TODO_TEXT: 'todo-text',
  TODO_DELETE: 'todo-delete',
}
let uncheckedItems = 0
let itemNumber = 0
const list = document.getElementById('todo-list')
const itemCountSpan = document.getElementById('item-count')
const uncheckedCountSpan = document.getElementById('unchecked-count')



list.addEventListener("click", function(e) {
  const tgt = e.target;
  const parent = tgt.parentNode;
  if (tgt.classList.contains("done")) {
    uncheckedItems -= 1
    uncheckedCountSpan.innerHTML = uncheckedItems;
    tgt.remove()
    parent.innerHTML = '<s>' + parent.textContent + '</s>'
  }
})



document.getElementById("newtodo").addEventListener("click", function() {
  increment()
  newItem()
})


function increment() { // this function increases the number of total TODOs and of unchecked TODOs
  itemNumber += 1
  uncheckedItems += 1
  itemCountSpan.innerHTML = itemNumber
  uncheckedCountSpan.innerHTML = uncheckedItems
}

function newItem() {
  var button = document.createElement('button');
  button.classList.add("done");
  button.innerHTML = 'Done!'

  let li = document.createElement("li");
  li.innerHTML += classNames.TODO_TEXT
  li.appendChild(button)
  list.appendChild(li)
}
* {
  box-sizing: border-box;
}

html,
body {
  background-color: #eee;
  margin: 0;
  padding: 0;
}

ul {
  margin: 0;
  padding: 0;
  list-style-type: none;
}

.center {
  align-self: center;
}

.flow-right {
  display: flex;
  justify-content: space-around;
}

.container {
  max-width: 800px;
  margin: 0 auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  background-color: white;
  height: 100vh;
}

.title,
.controls,
.button {
  flex: none;
}

.button {
  padding: 10px 20px;
}

.todo-list {
  flex: 1 1 0;
  margin-top: 20px;
  padding: 20px;
  overflow-y: auto;
  margin-left: 20%;
}

.todo-delete {
  margin: 10px;
}

.todo-checkbox {
  margin: 10px;
}

.todo-container {
  padding: 20px;
  border-bottom: 1px solid #333;
}

.todo-container:first-of-type {
  border-top: 1px solid #333;
}

.todo-list li { padding:3px }

button {
  float: right;
  margin-right: 0%;
}
<html>

<head>
  <title>TODO App</title>
  <link rel="stylesheet" type="text/css" href="./styles.css" />
</head>

<body>
  <div class="container center">
    <h1 class="center title">My TODO App</h1>
    <div class="flow-right controls">
      <span>Item count: <span id="item-count">0</span></span>
      <span>Unchecked count: <span id="unchecked-count">0</span></span>
    </div>

    <button class="button center" id="newtodo">New TODO</button>
    <ul id="todo-list" class="todo-list"></ul>
  </div>
  <script src="./script.js"></script>
</body>

</html>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • Thank you for your help! I was wondering what I did wrong in my code, and if there is an easier way to solve the problem than the one you used... – Alexoort Apr 08 '20 at 08:46
  • Solve which problem? My event handling is strongly recommended- it is ONE handler for all clicks in a dynamic list – mplungjan Apr 08 '20 at 09:39
  • Why the downvote? It is baffling when ppl vote down without any comments. It is just a slap in the face instead of something to learn from – mplungjan Apr 08 '20 at 13:11