【问题标题】:How to count the number of checked elements and the number of total elements in a to-do-list如何计算待办事项列表中已检查元素的数量和总元素的数量
【发布时间】:2019-03-30 04:23:59
【问题描述】:

这是我的任务:

每次更新任务时(检查一下, 取消选中或添加)输出元素应更新为完成的数量 任务和任务数量。例如。如果您有 7 个任务并且完成了 3 个任务,则应为 '3/7 完成'。

在 Js 代码的第 3 部分,我创建了一个数组,其中包含由用户输入创建的 HTML 列表中的所有任务元素。在底部的第 5 部分,我创建了一个名为 taskAmount 的函数,我尝试使用一些 JavaScript 函数来查找待办事项列表中复选框的数量和元素的数量。然后我尝试返回这些值并将它们打印到控制台以检查它是否有效。最后,我想尝试创建一个类似于示例中所示的输出,但我认为一旦我首先获得我想要的值,我就可以自己做到这一点。

我没有收到错误,但我的功能似乎不起作用。我的猜测是我在 taskAmount 函数的前几行中犯了一个错误。

我的尝试:

tasks = [];

function addTask() {

  var li = document.createElement("li");

  // Adding checkbox
  var cbox = document.createElement('INPUT');
  cbox.setAttribute('type', 'checkbox');
  li.appendChild(cbox);
  cbox.setAttribute('id', 'box');

  // Adding thing to do
  var inputValue = document.getElementById("newTask").value;
  var task = document.createTextNode(inputValue);
  li.appendChild(task);

  if (inputValue === '') {
    alert("You must write something!");
  } else {
    var ullist = document.getElementById("list");
    ullist.insertBefore(li, ullist.childNodes[0]);
  }


  // Part 3
  tasks.push(newTask.value);

  document.getElementById("newTask").value = '';
}



// Prevent Default
document.getElementById("submit").addEventListener("click", function() {
  event.preventDefault()
});


// Part 4
function ifChecked() {
  var list1 = document.querySelector('ul');
  list1.addEventListener('click', function(ev) {
    if (ev.target.tagName === 'INPUT') {
      ev.target.parentElement.classList.toggle('checked');
    }
  }, false);
}
ifChecked();

// Part 5
function taskAmount() {
  var totalTasks;
  var checkedTasks;

  document.getElementById("submit").addEventListener('click', function() {
    var totalTasks = tasks.length;
    var checkedTasks = document.querySelectorAll('input[type="checkbox"]:checked').length;

    return (totalTasks);
    return (checkedTasks);
  })
  console.log(totalTasks);
  console.log(checkedTasks);
}
taskAmount();
body {
  width: 600px;
  margin: auto;
  background: #ffe699;
  font-family: garamond;
  font-size: 25px;
}

ul {
  list-style-type: none;
  padding: 0;
  border: 2px solid black;
}

ul li {
  padding-top: 15px;
  padding-bottom: 15px;
  font-weight: bold;
  transition: 0.3s;
}

fieldset {
  background: skyblue;
  border: 2px solid black;
}

ul li:nth-child(odd) {
  background-color: skyblue;
}

ul li:nth-child(even) {
  background-color: white;
}

ul li:hover {
  background-color: #55D;
}

#box {
  margin: 0px 20px 0px;
}

.checked {
  text-decoration: line-through;
}
HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title> To do list </title>
  <link rel="stylesheet" href="style.css">
</head>

<body>

  <h1> To do list </h1>

  <form class="" action="todo.html" method="post">
    <fieldset>
      <label> Add a task in the input field below </label> <br><br>
      <input id="newTask" type="text" placeholder="Type a task here" autofocus> <br><br>
      <input id="submit" onclick="addTask()" type="submit" value="Add task"><br><br>
      <output name="result"> </output>
    </fieldset>
  </form>

  <h2>List of things to do</h2>

  <ul id="list">
  </ul>


  <script src="todo.js">
  </script>
</body>

</html>

【问题讨论】:

  • 在同一个函数中有两个返回值。执行将在第一个 return (totalTasks) 之后停止,并且永远不会到达第二个返回。
  • 我想统计检查的任务数。您写的内容不会返回真值或假值吗?不确定我是否正确理解了您的问题。
  • 是的,我认为这可能是原因。我想我从 Python 中回忆起,在同一个函数中不能有两个以上的返回值,但你仍然可以返回多个值,对吧?像这样:return(totalTask​​s, checkedTasks)?
  • 您遇到的一个问题是您的函数addTask() 创建了一个id 为box 的元素。如果您运行该函数两次或更多次,则您复制了 html 中不允许的 id。
  • @HankMoody 不,id 不是您的问题的原因,但可能是未来问题的原因。这就是为什么我评论它而不是发布答案。将其更改为类是解决它的有效方法。

标签: javascript html css


【解决方案1】:

删除 taskAmount() 函数中的事件处理程序并从添加任务中调用该函数修复了该问题。还使您的 id 对于生成的内容是唯一的。

tasks = [];
var idCount = 1;

function addTask() {

  var li = document.createElement("li");

  // Adding checkbox
  var cbox = document.createElement('INPUT');
  cbox.setAttribute('type', 'checkbox');
  cbox.addEventListener('change', taskAmount);
  li.appendChild(cbox);
  cbox.setAttribute('id', 'box' + idCount);
  idCount++;
  // Adding thing to do
  var inputValue = document.getElementById("newTask").value;
  var task = document.createTextNode(inputValue);
  li.appendChild(task);

  if (inputValue === '') {
    alert("You must write something!");
  } else {
    var ullist = document.getElementById("list");
    ullist.insertBefore(li, ullist.childNodes[0]);
  }


  // Part 3
  tasks.push(newTask.value);

  document.getElementById("newTask").value = '';
  taskAmount();
}



// Prevent Default
document.getElementById("submit").addEventListener("click", function() {
  event.preventDefault()
});


// Part 4
function ifChecked() {
  var list1 = document.querySelector('ul');
  list1.addEventListener('click', function(ev) {
    if (ev.target.tagName === 'INPUT') {
      ev.target.parentElement.classList.toggle('checked');
    }
  }, false);
}
ifChecked();

// Part 5
function taskAmount() {  
  var totalTasks = tasks.length;
  var checkedTasks = document.querySelectorAll('input[type="checkbox"]:checked').length;

  console.log(totalTasks);
  console.log(checkedTasks);
}
body {
  width: 600px;
  margin: auto;
  background: #ffe699;
  font-family: garamond;
  font-size: 25px;
}

ul {
  list-style-type: none;
  padding: 0;
  border: 2px solid black;
}

ul li {
  padding-top: 15px;
  padding-bottom: 15px;
  font-weight: bold;
  transition: 0.3s;
}

fieldset {
  background: skyblue;
  border: 2px solid black;
}

ul li:nth-child(odd) {
  background-color: skyblue;
}

ul li:nth-child(even) {
  background-color: white;
}

ul li:hover {
  background-color: #55D;
}

#box {
  margin: 0px 20px 0px;
}

.checked {
  text-decoration: line-through;
}
HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title> To do list </title>
  <link rel="stylesheet" href="style.css">
</head>

<body>

  <h1> To do list </h1>

  <form class="" action="todo.html" method="post">
    <fieldset>
      <label> Add a task in the input field below </label> <br><br>
      <input id="newTask" type="text" placeholder="Type a task here" autofocus> <br><br>
      <input id="submit" onclick="addTask()" type="submit" value="Add task"><br><br>
      <output name="result"> </output>
    </fieldset>
  </form>

  <h2>List of things to do</h2>

  <ul id="list">
  </ul>


  <script src="todo.js">
  </script>
</body>

</html>

【讨论】:

  • 谢谢!似乎它更新了元素的数量,但没有更新检查的任务数。
  • 没关系,我忘了勾选复选框。不过,它们仅在我提交后才更新,因此在您添加新的列表元素之前,它不会注册您已选中复选框。我该如何解决?我正在考虑在复选框中添加一个 onchange 函数
  • @HankMoody 您可以添加函数taskAmount() 用作复选框上onchangeoninput 事件的事件处理程序。然后它们将在检查时更新。请注意,每次添加新事件处理程序或使用事件委托时,都需要将事件处理程序添加到复选框。
  • 通过在创建事件处理程序时将事件处理程序添加到复选框来更新我的答案。 (cbox.addEventListener('change', taskAmount););
  • 有道理。非常感谢!
【解决方案2】:

totalTask​​s 和 checkedTasks 没有在函数外定义。当您单击时,我更新了代码以使 checkedTasks 更新

tasks = [];

function addTask() {

  var li = document.createElement("li");

  // Adding checkbox
  var cbox = document.createElement('INPUT');
  cbox.setAttribute('type', 'checkbox');
  li.appendChild(cbox);
  cbox.setAttribute('id', 'box');

  // Adding thing to do
  var inputValue = document.getElementById("newTask").value;
  var task = document.createTextNode(inputValue);
  li.appendChild(task);

  if (inputValue === '') {
    alert("You must write something!");
  } else {
    var ullist = document.getElementById("list");
    ullist.insertBefore(li, ullist.childNodes[0]);
  }


  // Part 3
  tasks.push(newTask.value);
  //console.log(tasks);
  document.getElementById("newTask").value = '';
}



// Prevent Default
document.getElementById("submit").addEventListener("click", function() {
  event.preventDefault()
});


// Part 4
function ifChecked() {
  var list1 = document.querySelector('ul');
  
  list1.addEventListener('click', function(ev) {
    
    if (ev.target.tagName === 'INPUT') {
      ev.target.parentElement.classList.toggle('checked');
      
      var checkedTasks = document.querySelectorAll('input[type="checkbox"]:checked').length;
      console.log(checkedTasks);
      
    }
  }, false);
  
  
  
}
ifChecked();

// Part 5
function taskAmount() {
  var totalTasks;
  var checkedTasks;

  document.getElementById("submit").addEventListener('click', function() {
    var totalTasks = tasks.length;
   // console.log(totalTasks)
    var checkedTasks = document.querySelectorAll('input[type="checkbox"]:checked').length;
    console.log(totalTasks);
 // console.log(checkedTasks);
    return (totalTasks);
    return (checkedTasks);
    
  })
 // console.log(totalTasks);
 // console.log(checkedTasks);
}
taskAmount();
body {
  width: 600px;
  margin: auto;
  background: #ffe699;
  font-family: garamond;
  font-size: 25px;
}

ul {
  list-style-type: none;
  padding: 0;
  border: 2px solid black;
}

ul li {
  padding-top: 15px;
  padding-bottom: 15px;
  font-weight: bold;
  transition: 0.3s;
}

fieldset {
  background: skyblue;
  border: 2px solid black;
}

ul li:nth-child(odd) {
  background-color: skyblue;
}

ul li:nth-child(even) {
  background-color: white;
}

ul li:hover {
  background-color: #55D;
}

#box {
  margin: 0px 20px 0px;
}

.checked {
  text-decoration: line-through;
}
HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title> To do list </title>
  <link rel="stylesheet" href="style.css">
</head>

<body>

  <h1> To do list </h1>

  <form class="" action="todo.html" method="post">
    <fieldset>
      <label> Add a task in the input field below </label> <br><br>
      <input id="newTask" type="text" placeholder="Type a task here" autofocus> <br><br>
      <input id="submit" onclick="addTask()" type="submit" value="Add task"><br><br>
      <output name="result"> </output>
    </fieldset>
  </form>

  <h2>List of things to do</h2>

  <ul id="list">
  </ul>


  <script src="todo.js">
  </script>
</body>

</html>

【讨论】:

  • 谢谢。有效,但不适用于复选框计数器。
  • 它也适用于复选框计数器,但可能不是您想要的方式。添加第二个项目,您会看到计数更新
  • 我更新了代码以在您选中或取消选中该框时更新 checkTasks
【解决方案3】:

我从您的 taskAmount() 函数返回了一个对象,并在点击提交后将其渲染到 html 中。我还摆脱了您的第二个提交事件处理程序。

tasks = [];
tasklist = [];
var checked = 0; 
var total = 0; 
  
function addTask() {

  var li = document.createElement("li");


  // Adding checkbox
  var cbox = document.createElement('INPUT');
  cbox.setAttribute('type', 'checkbox');
  li.appendChild(cbox);
  cbox.setAttribute('id', 'box');

  // Adding thing to do
  var inputValue = document.getElementById("newTask").value;
  var task = document.createTextNode(inputValue);
  li.appendChild(task);

  if (inputValue === '') {
    alert("You must write something!");
  } else {
    var ullist = document.getElementById("list");
    ullist.insertBefore(li, ullist.childNodes[0]);
  }


  // Part 3
  tasks.push(newTask.value);

  document.getElementById("newTask").value = '';
}




// Prevent Default
document.getElementById("submit").addEventListener("click", function() {
  event.preventDefault()
  document.getElementById("finished_tasks").innerHTML = taskAmount().checked + "/" +      taskAmount().total;
});


// Part 4
  var list1 = document.querySelector('ul');
  var finished = document.getElementById("finished_tasks"); 
  list1.addEventListener('click', function(ev) {
   
    if(ev.target.tagName === 'INPUT'){
     ev.target.parentElement.classList.toggle('checked');
      document.getElementById("finished_tasks").innerHTML = taskAmount().checked + "/" +           taskAmount().total;
    }
  }, false);



// Part 5
function taskAmount() {
  var totalTasks;
  var checkedTasks;

  var totalTasks = tasks.length;
  var checkedTasks = document.querySelectorAll('input[type="checkbox"]:checked').length;
  tasklist = ({
    checked: checkedTasks,
    total: totalTasks
  });

  return tasklist;
}
body {
  width: 600px;
  margin: auto;
  background: #ffe699;
  font-family: garamond;
  font-size: 25px;
}

ul {
  list-style-type: none;
  padding: 0;
  border: 2px solid black;
}

ul li {
  padding-top: 15px;
  padding-bottom: 15px;
  font-weight: bold;
  transition: 0.3s;
}

fieldset {
  background: skyblue;
  border: 2px solid black;
}

ul li:nth-child(odd) {
  background-color: skyblue;
}

ul li:nth-child(even) {
  background-color: white;
}

ul li:hover {
  background-color: #55D;
}

#box {
  margin: 0px 20px 0px;
}

.checked {
  text-decoration: line-through;
}
HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title> To do list </title>
  <link rel="stylesheet" href="style.css">
</head>

<body>

  <h1> To do list </h1>

  <form class="" action="todo.html" method="post">
    <fieldset>
      <label> Add a task in the input field below </label> <br><br>
      <input id="newTask" type="text" placeholder="Type a task here" autofocus> <br><br>
      <input id="submit" onclick="addTask()" type="submit" value="Add task"><br><br>
      <output name="result"> </output>
    </fieldset>
  </form>

  <h2>List of things to do</h2>

  <ul id="list">
  </ul>
  <div id="finished_tasks"></div>


  <script src="todo.js">
  </script>
</body>

</html>

【讨论】:

  • 不错!复选框计数器虽然没有更新,但我想我现在知道该做什么了。
  • 现在,计数器的更新是基于提交事件,而不是复选框被更改的事件。
  • 你去。一个小小的改变,你就开始做生意了。
  • 谢谢!如果我可能会问,为什么你有这个两次: document.getElementById("output").innerHTML = taskAmount().checked + "/" + taskAmount().total;
  • 我发现没有它就不行,但我不明白为什么你需要两者
【解决方案4】:

好吧,您的代码中还有更多奇怪的东西。首先,您在 taskAmount 函数的范围内定义了变量 totalTask​​s 和 checkedTasks ,但是您在 click 处理函数中重新定义了它们。如果您想将值保留在整个 taskAmount 函数中,则不应存在关键字 var。

也只会执行点击处理函数的第一个返回值,但这并不重要,因为你不使用返回值。

所以试试这样:

function taskAmount() {
  var totalTasks;
  var checkedTasks;

  document.getElementById("submit").addEventListener('click', function() {
    totalTasks = tasks.length;
    checkedTasks = document.querySelectorAll('input[type="checkbox"]:checked').length;
  })
  console.log(totalTasks);
  console.log(checkedTasks);
}

【讨论】:

    猜你喜欢
    • 2021-03-09
    • 2010-10-10
    • 2011-03-09
    • 1970-01-01
    • 2014-11-05
    • 2019-07-10
    • 1970-01-01
    • 2021-03-27
    • 1970-01-01
    相关资源
    最近更新 更多