How to delete a DOM element from an array after you've clicked on it?

I was making a simple to-do list. You submit itens from an input and they go to the To-DO section. When you click over them they go to the 'Done' section. And when you click on them again, they vanish forever. It was all working fine.

But I realized the doneItens array kept growing in length, which I wanted to optimize. So I came up with this line of code

        doneItens.splice(i, 1);

which goes inside an onclick event, which you can see in the code inside the deleteDone function.

That gives the error, though,

Error:{
  "message": "Uncaught TypeError: doneItens.splice is not a function"

If I put it outside and below the onclick event it also doesn't work. How can I do it?

var input = document.getElementById('play');
var toDo = document.getElementsByTagName('ol')[0];
var done = document.getElementById('done');

function handleSubmit(event) {
    event.preventDefault();
    const newItem = document.createElement('li');
    newItem.setAttribute('class', 'item');
    newItem.append(input.value);
    toDo.append(newItem);
    input.value='';

    deleteItem();
}

function deleteItem() {
    const toBeDone = document.getElementsByClassName('item');
    for(let i = 0; i < toBeDone.length; i++) {
        toBeDone[i].onclick = () => {
            appendItemDone(toBeDone[i]);
            toBeDone[i].style.display = 'none';
            deleteDone();
        } 
    }   
}

function appendItemDone(item) {
        const newDone = document.createElement('li');
        newDone.setAttribute('class', 'feito')
        newDone.append(item.innerText);
        done.append(newDone);

}

function deleteDone() {
    const doneItens = document.getElementsByClassName('feito');
    console.log('done length', doneItens.length)
    for (let i = 0; i < doneItens.length; i++) {
        doneItens[i].onclick = () => {
            doneItens[i].style.display = 'none';
            doneItens.splice(i, 1);
        }
    }
}
<div id='flex'>
        <form class='form' onsubmit='handleSubmit(event)'>
            <input placeholder='New item' type='text' id='play'>
            <button>Send</button>
        </form>
        <div id='left'> 
            <h1 id='todo' >To-do:</h1>
            <p class='instruction'><i>(Click over to mark as done)</i></p>
            <ol id='here'></ol>
        </div>
    
        <div id='right'>
            <h1>Done:</h1>
      <p class='instruction'><i>(Click over to delete it)</i></p>
            <p id='placeholder'></p>
            <ol id='done'></ol>
        </div>
    </div>

Solution 1:

With the use of JavaScript DOM API such as Node.removeChild(), Element.remove() and Node.parentNode, your task can be solved with this code:

const input = document.getElementById('play');
const todo = document.getElementById('todo');
const done = document.getElementById('done');

function handleSubmit(event) {
  event.preventDefault();

  // create new "todo" item
  const newTodo = document.createElement('li');
  newTodo.textContent = input.value;
  todo.append(newTodo);

  // clean the input field
  input.value = '';

  // listen to "click" event on the created item to move it to "done" section
  newTodo.addEventListener('click', moveToDone);
}

function moveToDone(event) {
  // remove "click"-listener to prevent event listener leaks
  event.target.removeEventListener('click', moveToDone);

  // move clicked todo-element to "done" section
  const newDone = event.target.parentNode.removeChild(event.target);
  done.append(newDone);

  // listen to "click" event on the moved item to then completely delete it
  newDone.addEventListener('click', removeFromDone);

  debugElementsLeak();
}

function removeFromDone(event) {
  // remove "click"-listener to prevent event listener leaks
  event.target.removeEventListener('click', removeFromDone);

  // complete remove clicked element from the DOM
  event.target.remove();

  debugElementsLeak();
}

function debugElementsLeak() {
  const todoCount = todo.childElementCount;
  const doneCount = done.childElementCount;
  console.log({ todoCount, doneCount });
}
<div id="flex">
  <form class="form" onsubmit="handleSubmit(event)">
    <input placeholder="New item" type="text" id="play">
    <button>Add item</button>
  </form>

  <div id="left">
    <h1>To-do:</h1>
    <p class="instruction"><em>(Click over to mark as done)</em></p>
    <ol id="todo"></ol>
  </div>

  <div id="right">
    <h1>Done:</h1>
    <p class="instruction"><em>(Click over to delete it)</em></p>
    <p id="placeholder"></p>
    <ol id="done"></ol>
  </div>
</div>

Solution 2:

You'll want to use splice, and then rather than use hidden, 'refresh' the done element by adding all elements in the spliced array.

I've commented my code where I've made changes and why

var input = document.getElementById('play');
var toDo = document.getElementsByTagName('ol')[0];
var done = document.getElementById('done');

function handleSubmit(event) {
    event.preventDefault();
    const newItem = document.createElement('li');
    newItem.setAttribute('class', 'item');
    newItem.append(input.value);
    toDo.append(newItem);
    input.value='';

    deleteItem();
}

function deleteItem() {
    const toBeDone = document.getElementsByClassName('item');
    for(let i = 0; i < toBeDone.length; i++) {
        toBeDone[i].onclick = () => {
            appendItemDone(toBeDone[i].cloneNode(true));
            toBeDone[i].style.display = 'none';
            deleteDone();
        } 
    }   
}

function appendItemDone(item) {
        const newDone = document.createElement('li');
        newDone.setAttribute('class', 'feito')
        newDone.append(item.innerText);
        done.append(newDone);

}

function deleteDone() {
    var doneItens = document.getElementsByClassName('feito');
    for (let i = 0; i < doneItens.length; i++) {
        doneItens[i].onclick = () => {
            var splicedArray = spliceFromArray(doneItens,doneItens[i]);// NEW BIT -CALL NEW SPLICE FUNCTION
            done.innerHTML=""; // NEW BIT - SET OVERALL DONE TO BLANK ON DELETE
            for(var index in  splicedArray){// NEW BIT - fOR EACH RETURNED ELEMENT IN THE SPLICE, ADD IT TO THE OVERALL DONE ELEMENT
              done.appendChild(splicedArray[index]); 
            }

            
        }
    }
}
function spliceFromArray(arrayInput,element){// NEW BIT - SPLICE FUNCTION THAT RETURNS SPLICED ARRAY
  var array = Array.from(arrayInput);
  var index = array.indexOf(element);
  if(index!=-1){
    if(array.length==1 && index == 0){
      array = [];
    }
    else{
      array.splice(index,1);
    }
  }
  return array;
  
}
<div id='flex'>
        <form class='form' onsubmit='handleSubmit(event)'>
            <input placeholder='New item' type='text' id='play'>
            <button>Send</button>
        </form>
        <div id='left'> 
            <h1 id='todo' >To-do:</h1>
            <p class='instruction'><i>(Click over to mark as done)</i></p>
            <ol id='here'></ol>
        </div>
    
        <div id='right'>
            <h1>Done:</h1>
      <p class='instruction'><i>(Click over to delete it)</i></p>
            <p id='placeholder'></p>
            <ol id='done'></ol>
        </div>
    </div>