skip to Main Content

I am fairly new at JavaScript and am creating a simple To Do list app, however, I am having trouble creating a JS function that crosses out the text/task of a particular div onClick.

Below is the code on what I have so far. I have attempted to use the strike() function in the crossOut() function in JS based on what I read online, however, it was unsuccessful.

function displayText() {
  let input = document.getElementById("textBar");
  let toDoContainer = document.getElementById("text");

  toDoContainer.innerHTML += "<div class='toDo' onclick='crossOut()'>" + input.value + "</div>";
  toDoContainer.innerHTML += "<br><br><br><br>";
  input.value = "";
}

function crossOut() {
  let toDoContainer = document.getElementById("text");
  toDoContainer.strike();
}
.toDo {
  cursor: pointer;
}
<div id="container">
  <div id="today">Today is:</div>
  <br>
  <div id="date"></div>

  <input type="text" placeholder="Enter task" id="textBar">
  <button type="submit" id="submit" onclick="displayText()">Add</button>

  <div id="text">
    <!--<div class="toDo" onclick="crossOut()">Design Text</div>-->
  </div>
</div>

2

Answers


    • Use text-decoration: line-through CSS property.
      I suggest to use a CSS class instead of setting the property directly.

    • Also you set the style for the all todo items, but you should strike through only the clicked one.
      To handle clicks on items listen clicks in the item’s container and Use event.target.closest('.toDo') to determine the current clicked todo item (if any).
      https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
      You need .closest() so you could add any child elements to a todo item in the future. In that case event.target could be a click child element but you want to change style of the parent todo item.
      Use ?. optional chaining operator so if you click outside a todo item the code wouldn’t break:
      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

    • AN IMPORTANT NOTE: NEVER USE innerHTML += …
      That overwrites any existing HTML, removes any existing event listeners, unnecessary triggers mutation observers and so on.

    • Also to avoid an item’s text to be interpreted as HTML rather than adding HTML, add a DIV element and set its textContent property to ensure that the input’s value added as text.

    • Avoid inline event handlers in HTML, they are kind of deprecated, not recommended: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these

    • You could disable the submit button to avoid entering empty items if the input is empty

    • You could autofocus the input after the submit is clicked for better UX

    • You could use the Enter key for adding items for better UX also

    const [todoContainer, input, submit] = ['text', 'textBar', 'submit'].map(id => document.getElementById(id));
    
    input.addEventListener('input', () => submit.disabled = !input.value.trim());
    input.addEventListener('keydown', event => event.key === 'Enter' && submit.click());
    
    submit.addEventListener('click', () => {
    
      const item = todoContainer.appendChild(document.createElement('div'));
      item.classList.add('toDo');
      item.textContent = input.value;
      input.value = '';
      submit.disabled = true;
      input.focus();
      
    });
    
    todoContainer.addEventListener('click', event => event.target.closest('.toDo')?.classList.toggle('done'));
    .toDo {
      background: lightgray;
      border-radius: 3px;
      padding: 5px 10px;
      cursor: pointer;
      margin: 5px 0;
    }
    
    .toDo.done{
      text-decoration: line-through;
    }
    <div id="container">
      <div id="today">Today is:</div>
      <br>
      <div id="date"></div>
    
      <input type="text" placeholder="Enter task" id="textBar">
      <button type="submit" disabled id="submit">Add</button>
    
      <div id="text">
      </div>
    </div>
    Login or Signup to reply.
  1. There’s a few issues in your code:

    • There’s no strike() method in JS. You need to use CSS to set the strikethrough on the text in the UI: text-decoration: line-through.
    • Toggle the CSS class containing that rule when the item is clicked.
    • Don’t use inline event handlers in your HTML – attach your events in JS unobtrusively.
    • If you wrap the input in a form and bind the handler to the submit event, then you can use the Return key to add each item, without clicking the mouse.

    With those changes made, here’s a full working example

    const form = document.querySelector('#create-task');
    const input = document.querySelector('#task-name');
    const list = document.querySelector('#task-list');
    
    form.addEventListener('submit', e => {
      e.preventDefault();
      const todoItemName = input.value.trim();
      list.appendChild(createTodoItem(todoItemName));
      input.value = '';
    }); 
    
    list.addEventListener('click', e => {
      if (e.target.classList.contains('todo-item')) {
        e.target.classList.toggle('strike');
      } 
    });
    
    const createTodoItem = value => {
      const div = document.createElement('div');
      div.classList.add('todo-item');
      div.textContent = value;
      return div;
    }
    .strike {
      text-decoration: line-through;
    }
    
    #task-list .todo-item {
      margin: 0 0 25px;
    }
    <div id="container">
      <div id="today">Today is:</div>
      <div id="date"></div>
    
      <form id="create-task">
        <input type="text" placeholder="Enter task" id="task-name">
        <button type="submit">Add</button>
      </form>
    
      <div id="task-list"></div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search