如何在不同的
块中调用一个JavaScript函数以更新数字。

huangapple go评论74阅读模式
英文:

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

&lt;div class=&quot;card-body&quot;&gt;
&lt;div class=&quot;heading&quot;&gt;
&lt;h2&gt;Endings&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;achievement-complete&quot;&gt;0&lt;/span&gt; / 2&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li id=&quot;achievement_7_0&quot;&gt;
&lt;div class=&quot;card-content&quot;&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;item_7_0&quot; class=&quot;sum&quot; value=&quot;1&quot; /&gt;
&lt;label class=&#39;strikethrough&#39; for=&quot;item_7_0&quot;&gt;
Ending 1
&lt;/label&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li id=&quot;achievement_7_1&quot;&gt;
&lt;div class=&quot;card-content&quot;&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;item_7_1&quot; class=&quot;sum&quot; value=&quot;1&quot; /&gt;
&lt;label class=&#39;strikethrough&#39; for=&quot;item_7_1&quot;&gt;
Ending 2 
&lt;/label&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;card-body&quot;&gt;
&lt;div class=&quot;heading&quot;&gt;
&lt;h2&gt;All Achievements&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;achievement-complete&quot;&gt;0&lt;/span&gt; / 1&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li id=&quot;achievement_8_0&quot;&gt;
&lt;div class=&quot;card-content&quot;&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;item_8_0&quot; class=&quot;sum&quot; value=&quot;1&quot; /&gt;
&lt;label class=&#39;strikethrough&#39; for=&quot;item_8_0&quot;&gt;
All Achievements
&lt;/label&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

Javascript

var input = document.getElementsByClassName(&#39;sum&#39;),
total = document.getElementById(&#39;achievement-complete&#39;);
for (var i = 0; i &lt; 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(&#39;.container&#39;);
container.addEventListener(&#39;click&#39;, handleClick);
function handleClick(e) {
// Check that the element that fired the event
// is a checkbox
if (e.target.matches(&#39;[type=&quot;checkbox&quot;]&#39;)) {
// 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(&#39;.card-body&#39;);
// Use that to find the local &quot;achievement&quot; element
const achievement = card.querySelector(&#39;.achievement-complete&#39;);
// 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 -->

&lt;section class=&quot;container&quot;&gt;
&lt;section class=&quot;card-body&quot;&gt;
&lt;h2&gt;Endings&lt;/h2&gt;
&lt;p&gt;&lt;span class=&quot;achievement-complete&quot;&gt;0&lt;/span&gt; / 2&lt;/p&gt;
&lt;ul&gt;
&lt;li id=&quot;achievement_7_0&quot;&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;item_7_0&quot; class=&quot;sum&quot; value=&quot;1&quot; /&gt;
&lt;label class=&#39;strikethrough&#39; for=&quot;item_7_0&quot;&gt;
Ending 1
&lt;/label&gt;
&lt;/li&gt;
&lt;li id=&quot;achievement_7_1&quot;&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;item_7_1&quot; class=&quot;sum&quot; value=&quot;1&quot; /&gt;
&lt;label class=&#39;strikethrough&#39; for=&quot;item_7_1&quot;&gt;
Ending 2 
&lt;/label&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section class=&quot;card-body&quot;&gt;
&lt;h2&gt;All Achievements&lt;/h2&gt;
&lt;p&gt;&lt;span class=&quot;achievement-complete&quot;&gt;0&lt;/span&gt; / 1&lt;/p&gt;
&lt;ul&gt;
&lt;li id=&quot;achievement_8_0&quot;&gt;
&lt;input type=&quot;checkbox&quot; id=&quot;item_8_0&quot; class=&quot;sum&quot; value=&quot;1&quot; /&gt;
&lt;label class=&#39;strikethrough&#39; for=&quot;item_8_0&quot;&gt;
All Achievements
&lt;/label&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;

<!-- 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(&#39;sum&#39;);
for (var i = 0; i &lt; inputs.length; i++) {
inputs[i].onchange = function () {
var cardBody = this.closest(&#39;.card-body&#39;);
var total = cardBody.querySelector(&#39;.achievement-complete&#39;);
var checkboxes = cardBody.querySelectorAll(&#39;.sum&#39;);
var count = 0;
for (var j = 0; j &lt; checkboxes.length; j++) {
count += checkboxes[j].checked ? 1 : 0;
}
total.innerHTML = count;
}
}

huangapple
  • 本文由 发表于 2023年2月27日 03:23:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75574469.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定