英文:
how to call a js function into seperate div blocks to update a number
问题
我正在尝试创建一个成就追踪器,当你点击复选框时,它将更新该部分中已完成的数量。但是,按照我目前的实现方式,该数字仅在一个div块中更新。
HTML
<div class="card-body">
<div class="heading">
<h2>Endings</h2>
<p><span id="achievement-complete">0</span> / 2</p>
</div>
<ul>
<li id="achievement_7_0">
<div class="card-content">
<input type="checkbox" id="item_7_0" class="sum" value="1" />
<label class='strikethrough' for="item_7_0">
Ending 1
</label>
</div>
</li>
<li id="achievement_7_1">
<div class="card-content">
<input type="checkbox" id="item_7_1" class="sum" value="1" />
<label class='strikethrough' for="item_7_1">
Ending 2
</label>
</div>
</li>
</ul>
</div>
<div class="card-body">
<div class="heading">
<h2>All Achievements</h2>
<p><span id="achievement-complete">0</span> / 1</p>
</div>
<ul>
<li id="achievement_8_0">
<div class="card-content">
<input type="checkbox" id="item_8_0" class="sum" value="1" />
<label class='strikethrough' for="item_8_0">
All Achievements
</label>
</div>
</li>
</ul>
</div>
Javascript
var input = document.getElementsByClassName('sum'),
total = document.getElementById('achievement-complete');
for (var i = 0; i < input.length; i++) {
input[i].onchange = function () {
var add = this.value * (this.checked ? 1 : -1);
total.innerHTML = parseFloat(total.innerHTML) + add;
// console.log(add);
}
}
这里我想在每个class为"card-body"的div块中调用一个JavaScript函数,并更新具有class为"achievement-complete"的span标签,以显示新的已完成成就总数。
英文:
I am trying to create an achievement tracker that when you click a checkbox it will update a number on how many you have completed in that section. But how I have it implemented now the number only updates on one of the div blocks.
HTML
<div class="card-body">
<div class="heading">
<h2>Endings</h2>
<p><span id="achievement-complete">0</span> / 2</p>
</div>
<ul>
<li id="achievement_7_0">
<div class="card-content">
<input type="checkbox" id="item_7_0" class="sum" value="1" />
<label class='strikethrough' for="item_7_0">
Ending 1
</label>
</div>
</li>
<li id="achievement_7_1">
<div class="card-content">
<input type="checkbox" id="item_7_1" class="sum" value="1" />
<label class='strikethrough' for="item_7_1">
Ending 2
</label>
</div>
</li>
</ul>
</div>
<div class="card-body">
<div class="heading">
<h2>All Achievements</h2>
<p><span id="achievement-complete">0</span> / 1</p>
</div>
<ul>
<li id="achievement_8_0">
<div class="card-content">
<input type="checkbox" id="item_8_0" class="sum" value="1" />
<label class='strikethrough' for="item_8_0">
All Achievements
</label>
</div>
</li>
</ul>
</div>
Javascript
var input = document.getElementsByClassName('sum'),
total = document.getElementById('achievement-complete');
for (var i = 0; i < input.length; i++) {
input[i].onchange = function () {
var add = this.value * (this.checked ? 1 : -1);
total.innerHTML = parseFloat(total.innerHTML) + add
// console.log(add);
}
}
Here I would like it to call a js function in each div block with class="card-body" and update the span with class="achievement-complete" with the new total of achievements completed.
答案1
得分: 1
如果您将您的标记包装在一个容器元素中,您可以使用 事件代理 来捕获从其子元素“冒泡”到 DOM 中的事件。只需附加一个侦听器到该容器,而不是附加多个侦听器到多个元素。
然后,您可以从触发事件的元素获取 checked
状态,找到具有 card-body
类的 closest
元素,然后使用它来找到具有 achievement-complete
类的子元素(注意:这是对您的标记的更改,您之前使用了 id
- 在页面中,id 必须是唯一的)。
然后,获取该元素的文本,将其强制转换为整数,并进行更新 - 如果 checked
状态为 true
,则添加一个,如果为 false
,则减去一个。
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
// 缓存容器元素并向其添加侦听器
const container = document.querySelector('.container');
container.addEventListener('click', handleClick);
function handleClick(e) {
// 检查触发事件的元素是否是复选框
if (e.target.matches('[type="checkbox"]')) {
// 从复选框中解构出 checked 属性
const { checked } = e.target;
// 找到具有 'card-body' 类的最接近元素
const card = e.target.closest('.card-body');
// 使用它来找到局部 "achievement" 元素
const achievement = card.querySelector('.achievement-complete');
// 获取并将其文本强制转换为整数
let total = Number(achievement.textContent);
// 使用新的总数更新文本内容
achievement.textContent = checked ? total += 1 : total -= 1;
}
}
<!-- language: lang-html -->
<section class="container">
<section class="card-body">
<h2>Endings</h2>
<p><span class="achievement-complete">0</span> / 2</p>
<ul>
<li id="achievement_7_0">
<input type="checkbox" id="item_7_0" class="sum" value="1" />
<label class='strikethrough' for="item_7_0">
Ending 1
</label>
</li>
<li id="achievement_7_1">
<input type="checkbox" id="item_7_1" class="sum" value="1" />
<label class='strikethrough' for="item_7_1">
Ending 2
</label>
</li>
</ul>
</section>
<section class="card-body">
<h2>All Achievements</h2>
<p><span class="achievement-complete">0</span> / 1</p>
<ul>
<li id="achievement_8_0">
<input type="checkbox" id="item_8_0" class="sum" value="1" />
<label class='strikethrough' for="item_8_0">
All Achievements
</label>
</li>
</ul>
</section>
</section>
<!-- end snippet -->
附加文档:
英文:
If you wrap your markup in a container element you can use event delegation to capture event from its child elements as they "bubble up" the DOM. Just attach one listener to that container rather than many listeners to many elements.
Then you can get the checked
status from the element that fired the event, find the closest
element with a card-body
class, and use that to find the its child element with the achievement-complete
class (note: this is a change to your markup where you've used id
- ids must be unique in a page).
Then grab that element's text, coerce it to an integer, and update it - adding one if the checked
status is true
, and subtracting one if it's false
.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
// Cache container element and add a listener to it
const container = document.querySelector('.container');
container.addEventListener('click', handleClick);
function handleClick(e) {
// Check that the element that fired the event
// is a checkbox
if (e.target.matches('[type="checkbox"]')) {
// Destructure the checked attribute from the checkbox
const { checked } = e.target;
// Find the closest element with a `card-body` class
const card = e.target.closest('.card-body');
// Use that to find the local "achievement" element
const achievement = card.querySelector('.achievement-complete');
// Get and coerce its total to an integer
let total = Number(achievement.textContent);
// Update the text content with an new total
achievement.textContent = checked ? total += 1 : total -= 1;
}
}
<!-- language: lang-html -->
<section class="container">
<section class="card-body">
<h2>Endings</h2>
<p><span class="achievement-complete">0</span> / 2</p>
<ul>
<li id="achievement_7_0">
<input type="checkbox" id="item_7_0" class="sum" value="1" />
<label class='strikethrough' for="item_7_0">
Ending 1
</label>
</li>
<li id="achievement_7_1">
<input type="checkbox" id="item_7_1" class="sum" value="1" />
<label class='strikethrough' for="item_7_1">
Ending 2
</label>
</li>
</ul>
</section>
<section class="card-body">
<h2>All Achievements</h2>
<p><span class="achievement-complete">0</span> / 1</p>
<ul>
<li id="achievement_8_0">
<input type="checkbox" id="item_8_0" class="sum" value="1" />
<label class='strikethrough' for="item_8_0">
All Achievements
</label>
</li>
</ul>
</section>
</section>
<!-- end snippet -->
Additional documentation
答案2
得分: 0
这段代码翻译如下:
它对我有效。
var inputs = document.getElementsByClassName('sum');
for (var i = 0; i < inputs.length; i++) {
inputs[i].onchange = function () {
var cardBody = this.closest('.card-body');
var total = cardBody.querySelector('.achievement-complete');
var checkboxes = cardBody.querySelectorAll('.sum');
var count = 0;
for (var j = 0; j < checkboxes.length; j++) {
count += checkboxes[j].checked ? 1 : 0;
}
total.innerHTML = count;
}
}
英文:
It works for me.
var inputs = document.getElementsByClassName('sum');
for (var i = 0; i < inputs.length; i++) {
inputs[i].onchange = function () {
var cardBody = this.closest('.card-body');
var total = cardBody.querySelector('.achievement-complete');
var checkboxes = cardBody.querySelectorAll('.sum');
var count = 0;
for (var j = 0; j < checkboxes.length; j++) {
count += checkboxes[j].checked ? 1 : 0;
}
total.innerHTML = count;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论