質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

4回答

653閲覧

繰り返し使う関数の書き方が分からない

syun1988

総合スコア4

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2022/12/04 02:03

前提

html

1<td class="score-p1"><input type="number"></td>

に値を入力したら

html

1<td id="sum-p1"></td>

へ計算結果を反映。

html

1<td class="score-p2"><input type="number"></td>

に値を入力したら

html

1<td id="sum-p2"></td>

へ計算結果を反映させたいです。

実現したいこと

現在、class="score-p1"に値を入力した際にid="sum-p1"に計算結果が反映されるJavaScriptは書けています。
今後、class="score-p2"、class="score-p3"………と列を増やしていく予定ですが、列を増やしたときのJavaScriptのスマートな書き方が分かりません。

該当のソースコード

html

1<table> 2 <tbody id="score"> 3 <tr> 4 <th>1</th> 5 <td class="score-p1"><input type="number"></td> 6 <td class="score-p2"><input type="number"></td> 7 </tr> 8 <tr> 9 <th>2</th> 10 <td class="score-p1"><input type="number"></td> 11 <td class="score-p2"><input type="number"></td> 12 </tr> 13 <tr> 14 <th>3</th> 15 <td class="score-p1"><input type="number"></td> 16 <td class="score-p2"><input type="number"></td> 17 </tr> 18 <tr> 19 <th>4</th> 20 <td class="score-p1"><input type="number"></td> 21 <td class="score-p2"><input type="number"></td> 22 </tr> 23 <tr> 24 <th>5</th> 25 <td class="score-p1"><input type="number"></td> 26 <td class="score-p2"><input type="number"></td> 27 </tr> 28 </tbody> 29 <tfoot> 30 <tr> 31 <th>合計</th> 32 <td id="sum-p1"></td> 33 <td id="sum-p2"></td> 34 </tr> 35 </tfoot> 36</table>

以下はclass="score-p1"に数値を入力したときid="sum-p1"に結果が反映されるJavaScriptです。

js

1window.addEventListener('DOMContentLoaded', () => { 2 3score.addEventListener('input', () => { 4 // 要素を取得 5 const score = document.getElementById('score'); 6 const scoreElements = score.querySelectorAll('.score-p1 input'); 7 var price = 0; 8 9 // 取得した要素を反復処理 10 for (let i = 0; i < scoreElements.length; i += 1) { 11 const element = scoreElements[i]; 12 if (!isNaN(element.valueAsNumber)) 13 price += element.valueAsNumber; 14 } 15 16 document.getElementById('sum-p1').innerText = price; 17}); 18 19})

class="score-p2"、class="score-p3"………と列を増やしたときにどういう書き方をすべきかご教示いただけたらと思います。
どうぞよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

あえてp1、p2の入力をわけて考える必要はないですね
常に入力があるごとに計算してください

javascript

1document.addEventListener('input', ()=>{ 2 ['p1','p2'].forEach(x=>{ 3 const v=[...document.querySelectorAll(`.score-${x} [type=number]`)].reduce((x,y)=>x+Number(y.value),0); 4 document.querySelector(`#sum-${x}`).textContent=v; 5 }); 6});

投稿2022/12/05 02:47

yambejp

総合スコア114915

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

<td class="score-p1"><td id="sum-p1"> ではなくて、<td class="score" data-group="p1"> <td class="sum" data-group="p1"> のように役割とグループを分けると多少すっきりするかと思います。

js

1score.addEventListener('input', e => { 2 const group = e.target.closest('.score').dataset.group; 3 const score = document.getElementById('score'); 4 const scoreElements = score.querySelectorAll(`.score[data-group="${group}"] input`); 5 document.querySelector(`.sum[data-group="${group}"]`).textContent = 6 [...scoreElements].map(input => isNaN(input.valueAsNumber) ? 0 : input.valueAsNumber).reduce((a, c) => a + c); 7});

投稿2022/12/05 00:21

int32_t

総合スコア20927

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサーまで出ちゃったのですが、目を見張るようなスマートなコードを見ることなく終わってしまったので、全然スマートじゃない汚いのを置いときます。class属性は基本的にCSSから参照されるので、見た目に関係ないところで使わない方がいい気がします。

JavaScript

1window.addEventListener('DOMContentLoaded', () => { 2 const score = document.getElementById('score'); 3 const suminfos = Array.from(document.querySelectorAll('td[id^="sum-"]')) 4 .reduce((m, e)=>{ 5 const id = e.id.substring(4); 6 m[id] = { 7 "elem": e, 8 "scores": Array.from(score.querySelectorAll(`td.score-${id} input`)) 9 }; 10 return m; 11 }, {}); 12 const handler = (ev) => { 13 const classList = Array.from(ev.currentTarget.parentElement.classList); 14 const id = classList.filter(e => e.match(/^score-/))[0].substring(6); 15 const suminfo = suminfos[id]; 16 suminfo.elem.textContent = suminfo.scores.reduce((s, v)=>{ 17 return s + (v.valueAsNumber ? v.valueAsNumber : 0); 18 }, 0); 19 }; 20 Object.entries(suminfos).forEach(([id, info]) => { 21 info.scores.forEach(e => { 22 e.addEventListener('input', handler); 23 }) 24 }); 25}); 26

他の回答も出てきてくれたのでコンセプトだけ書いておきます。

このコードのコンセプトは速度です(まだ速く出来ると思いますが)。イベント発生時DOMにqueryをかけることなく、適応的に計算結果を反映しています。

投稿2022/12/04 13:35

編集2022/12/05 03:32
dameo

総合スコア943

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

すっごく力技っぽくなっていますけど,こんな感じでどうですか?

js

1window.addEventListener('DOMContentLoaded', () => { 2 score.addEventListener('input', () => { 3 // 要素を取得 4 const score = document.getElementById('score'); 5 6 for (let a = 1; a <= 2; a ++) { // classname をここで切り替えていく 7 let scoreElements = score.querySelectorAll('.score-p' + String(a) + ' input'); 8 var price = 0; 9 10 // 取得した要素を反復処理 11 for (let i = 0; i < scoreElements.length; i += 1) { 12 const element = scoreElements[i]; 13 if (!isNaN(element.valueAsNumber)) 14 price += element.valueAsNumber; 15 } 16 17 document.getElementById('sum-p' + String(a)).innerText = price; 18 } 19 }); 20});

ただ,今後列を増やしていく上で現状のソースコードがスマートかと言われるとう〜んってなられているのではないでしょうか?

よろしければ,以下のソースコードも試してみてください.(こっちもスマートか言われる微妙ですが…)

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <script src="./main.js"></script> 7</head> 8<body> 9 <main role="main"> 10 <div id="__"></div> 11 </main> 12</body> 13</html>

js

1// main.js 2 3/** 4 * Tableを作る 5 * @param {Number} rowNum 行数 6 * @param {Number} score-p の数 7 */ 8class Score { 9 constructor(rowNum, pNum) { 10 this.rowNum = rowNum; 11 this.pNum = pNum; 12 this.TABLE = document.createElement('table'); 13 14 this.setTbody(); 15 this.setTfoot(); 16 } 17 18 setTbody() { 19 let tbody = document.createElement('tbody'); 20 this.priceArray = new Array(); 21 22 for (let i = 0; i < this.rowNum; i ++) { 23 let tr = document.createElement('tr'); 24 let th = document.createElement('th'); 25 th.innerText = String(i + 1); 26 tr.appendChild(th); 27 28 this.priceArray[i] = new Array(); 29 30 for (let j = 0; j < this.pNum; j ++) { 31 let td = document.createElement('td'); 32 td.className = "score-p" + String(j + 1); 33 34 let input = document.createElement('input'); 35 input.type = "number"; 36 37 td.appendChild(input); 38 tr.appendChild(td); 39 40 this.priceArray[i][j] = 0; 41 42 // 値が入力されたら加算処理 43 input.addEventListener('input', (e) => { 44 this.priceArray[i][j] = Number(e.target.value); 45 this.add(j); 46 }) 47 } 48 tbody.appendChild(tr); 49 50 } 51 52 this.TABLE.appendChild(tbody); 53 } 54 55 setTfoot() { 56 let tfoot = document.createElement('tfoot'); 57 let tr = document.createElement('tr'); 58 let th = document.createElement("th"); 59 th.innerText = "合計"; 60 tr.appendChild(th); 61 62 for (let j = 0; j < this.pNum; j ++) { 63 let td = document.createElement('td'); 64 td.id = "sum-p" + String(j + 1); 65 tr.appendChild(td); 66 } 67 68 tfoot.appendChild(tr); 69 this.TABLE.appendChild(tfoot); 70 } 71 72 add(pNum) { 73 let price = 0; 74 for (let i = 0; i < this.rowNum; i ++) { 75 price += this.priceArray[i][pNum]; 76 } 77 78 document.getElementById("sum-p" + String(pNum + 1)).innerText = price; 79 } 80} 81 82 83window.onload = () => { 84 const SCORE = new Score(5, 3); 85 document.getElementById('__').appendChild(SCORE.TABLE); 86 87 console.log(SCORE); 88}

投稿2022/12/04 08:15

m0605

総合スコア14

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

syun1988

2022/12/04 13:21

ご回答ありがとうございました! 前者のコードで思い通りの挙動になりました。 お陰様で悩んでいた箇所が解決できました。 後者のコードはもっと自分がレベルアップしてから試してみたいと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問