🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

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

Bootstrap

BootstrapはウェブサイトデザインやUIのWebアプリケーションを素早く 作成する可能なCSSフレームワークです。 Twitter風のデザインを作成することができます。

Q&A

解決済

1回答

739閲覧

JS ボタンクリック時に実行をさせたい

kanix2020

総合スコア6

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

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

Bootstrap

BootstrapはウェブサイトデザインやUIのWebアプリケーションを素早く 作成する可能なCSSフレームワークです。 Twitter風のデザインを作成することができます。

0グッド

0クリップ

投稿2021/02/20 02:53

編集2021/02/20 03:53

実現したいこと

ボタンをクリックした時にこのGIF動画(Gyazo)「Total」の部分に
計算結果が表示されるような処理を行いたいのですが、うまく行きません。
この場合どうしたら良いでしょうか。。。ご教授をお願いいたします。

(動画の対象部分となるhtmlは「#対象箇所」として括っています。)

該当のソースコード

JS

1window.addEventListener('load', () => { 2 document.getElementById("scorebtn").addEventListener('click', function(){ 3 4 const fxd_Input = document.getElementById("fx_d"); 5 fxd_Input.addEventListener("input", () => { 6 const input_fxd_Value = fxd_Input.value; 7 8 const fxe_Input = document.getElementById("fx_e"); 9 fxe_Input.addEventListener("input", () => { 10 const input_fxe_Value = fxe_Input.value; 11 12 const floor_total = document.getElementById("fx_total"); 13 floor_total.innerHTML = parseFloat(input_fxd_Value) + parseFloat(input_fxe_Value); 14 15 }) 16 }) 17 }) 18})

ruby

1<%= form_with local: true do |f| %> 2 <table class="table table-bordered m-4"> 3 <thead> 4 5 <tr> 6     #対象箇所1 7 <th scope="col"><button type="button" id="scorebtn" class="btn btn-primary w-10 mt-2">計算</button></th> 8     #対象箇所1 9 <th scope="col" colspan="2">FX</th> 10 <th scope="col" colspan="2">PH</th> 11 <th scope="col" colspan="2">Ri</th> 12 <th scope="col" colspan="2">Vo</th> 13 <th scope="col" colspan="2">PB</th> 14 <th scope="col" colspan="2">HB</th> 15 </tr> 16 </thead> 17 <% @athlete.each do |athlete| %> 18 <tbody> 19 20 <tr> 21 <th scope="row" rowspan="2"><%= athlete.name %></th> 22     #対象箇所2 23 <td><%= f.text_field :floor_score_d, class:"form-control", id:"fx_d", placeholder:"D-score" %></td> 24     #対象箇所2 25 <td rowspan="2" id="fx_total">Total</td> 26 <td><%= f.text_field :pommel_score_d, class:"form-control", id:"ph_d", placeholder:"D-score" %></td> 27 <td rowspan="2" id="ph_total">Total</td> 28 <td><%= f.text_field :rings_score_d, class:"form-control", id:"ri_d", placeholder:"D-score" %></td> 29 <td rowspan="2" id="ri_total">Total</td> 30 <td><%= f.text_field :vault_score_d, class:"form-control", id:"vo_d", placeholder:"D-score" %></td> 31 <td rowspan="2" id="vo_total">Total</td> 32 <td><%= f.text_field :parallel_score_d, class:"form-control", id:"pb_d", placeholder:"D-score" %></td> 33 <td rowspan="2" id="pb_total">Total</td> 34 <td><%= f.text_field :horizontal_score_d, class:"form-control", id:"hb_d", placeholder:"D-score" %></td> 35 <td rowspan="2" id="hb_total">Total</td> 36 </tr> 37 <tr> 38     #対象箇所3 39 <td><%= f.text_field :floor_score_e, class:"form-control", id:"fx_e", placeholder:"E-score" %></td> 40 #対象箇所3 41 <td><%= f.text_field :pommel_score_e, class:"form-control", id:"ph_e", placeholder:"E-score" %></td> 42 <td><%= f.text_field :rings_score_e, class:"form-control", id:"ri_e", placeholder:"E-score" %></td> 43 <td><%= f.text_field :vault_score_e, class:"form-control", id:"vo_e", placeholder:"E-score" %></td> 44 <td><%= f.text_field :parallel_score_e, class:"form-control", id:"pb_e", placeholder:"E-score" %></td> 45 <td><%= f.text_field :horizontal_score_e, class:"form-control", id:"hb_e", placeholder:"E-score" %></td> 46 </tr> 47 </tbody> 48 <% end %> 49 </table> 50<% end %> 51

言葉足らずな部分がありましたら申し訳ございません。
よろしくお願いします。

補足情報(FW/ツールのバージョンなど)

ブラウザ:Chrome
bootstrap:4.1.1
ruby:2.6.5
rails:6.0.0

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

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

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

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

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

m.ts10806

2021/02/20 03:24

画像ならリンクよりteratailの画像投稿機能を利用してください。 あと、addEventが入れ子になってますが、この意図は?
kanix2020

2021/02/20 03:57

ご指摘ありがとうございます。 画像ならリンクよりteratailの画像投稿機能を利用してください。 ⇨ 画像ではなくGyazoで撮影したGIF動画にさせていただいております。 addEventが入れ子になってますが、この意図は? ⇨addEventについて深く理解をしておらず、記載の方法でないといけないと言う先入観で書いておりました。  もう少しコードの1つ1つの意味を学習した上で再度質問しようかと思います。
guest

回答1

0

ベストアンサー

こんにちは。やりたい事の情報が添付gifから全て読み取れないので、推測して回答しますね。

FX,PH,RI,など複数の項目がありますが、計算ボタンをクリックすると項目毎にD-scoreとE-scoreの計算を行いTotalに出力するという要件とします。

その上で質問者さんのJavaScriptで直すべき所を箇条書きにします。

・addEventListenerを入れ子にしてしまっている。
これの何が良くないかというと最初の要素のイベントが発生しないと、次のイベントの監視を開始しないという所です。

・最後のinputイベントが発生したら計算を行って出力している
ボタンをクリックをしたら計算結果を表示したいのであれば、必要なイベントはクリックイベントのみです。

・要素をIDで取得してしまっている

JavaScript

1const fxd_Input = document.getElementById("fx_d"); 2const fxe_Input = document.getElementById("fx_e"); 3const floor_total = document.getElementById("fx_total");

上記のコードが見受けられますが、FX ~ HBまで6種類もあるので全て書くとなるとコード量が非常に多くなってしまいます。
FX ~ HBの共通の要素を見つけましょう。D-score入力要素とE-score入力要素とTotal出力要素があるかと思います。
共通の要素をクラスとして名前を付けてJavaScriptではIdではなくClassNameで取得するようにしましょう。
以下修正したHTMLですが、td構造だと3つの要素をグループ化しづらいので、tdからdivに変え、cssのgridを使ってセルの結合を表現しています。
※rubyは使わないので、htmlにして2列だけ抜粋しています。

HTML

1<tbody> 2 <tr> 3 <th scope="row">テスト1</th> 4 <td> 5 <div class="score-group grid-container"> 6 <div class="total grid-item"> 7 Total 8 <span class="output-score-total"></span> 9 </div> 10 <div class="d-score grid-item"> 11 <input 12 type="number" 13 step="0.1" 14 name="floor_score_d" 15 class="form_control input-socre-d" 16 placeholder="D-score" 17 /> 18 </div> 19 <div class="e-score grid-item"> 20 <input 21 type="number" 22 step="0.1" 23 name="floor_score_e" 24 class="form-control input-socre-e" 25 placeholder="E-score" 26 /> 27 </div> 28 </div> 29 </td> 30 <td> 31 <div class="score-group grid-container"> 32 <div class="total grid-item"> 33 Total 34 <span class="output-score-total"></span> 35 </div> 36 <div class="d-score grid-item"> 37 <input 38 type="number" 39 step="0.1" 40 name="pommel_score_d" 41 class="form_control input-socre-d" 42 placeholder="D-score" 43 /> 44 </div> 45 <div class="e-score grid-item"> 46 <input 47 type="number" 48 step="0.1" 49 name="pommel_score_e" 50 class="form-control input-socre-e" 51 placeholder="E-score" 52 /> 53 </div> 54 </div> 55 </td> 56 </tr> 57</tbody>

グルーピング用の.score-groupとE-score用の.input-socre-eとD-score用の.input-socre-dとTotal用の.output-score-totalを要素に加えたので、クラス名で処理を行なうようにJavaScriptも以下のように修正します。

JavaScript

1// 他のJSファイルの関数定義(以下のmain,calc関数)と被らないように即時関数でスコープを作る 2(function () { 3 // 全体の処理の起点となる関数 4 function main() { 5 // 使う要素を予め全て取得しておく 6 const scorebtn = document.getElementById("scorebtn"); 7 // 各列のD-score入力、E-score入力、Total出力の要素をグループ化して取得する 8 const scoreGroups = document.getElementsByClassName("score-group"); 9 // #scorebtnがクリックされたら処理を開始 10 scorebtn.addEventListener("click", () => { 11 // グループを一つずつ処理 12 for (const scoreGroup of scoreGroups) { 13 // グループ内の出力要素を取得 14 const output = scoreGroup.getElementsByClassName( 15 "output-score-total" 16 )[0]; 17 // グループ内のD-score入力要素を取得 18 const inputD = scoreGroup.getElementsByClassName("input-socre-d")[0]; 19 // グループ内のE-score入力要素を取得 20 const inputE = scoreGroup.getElementsByClassName("input-socre-e")[0]; 21 22 // 上記3つのいずれかの要素が取得出来なかったら、そのグループの計算は行わない 23 if (!output || !inputD || !inputE) continue; 24 25 // 計算を行なう(計算式がわからなかったので、calc関数を調整してください) 26 const result = calc(parseFloat(inputD.value), parseFloat(inputE.value)); 27 output.textContent = result; 28 } 29 }); 30 } 31 32 // 計算式 33 function calc(a, b) { 34 const result = a + b; 35 // 文字列が入力された場合はnullを返します。 36 // input要素をnumberにすれば必要ないと思います。 37 return isNaN(result) ? null : result; 38 } 39 40 // loadにすると画像などの読み込みも待ってしまうので、DOMの準備が出来たら開始するように変更しました。 41 document.addEventListener("DOMContentLoaded", main); 42})();

実際に動いているのをCodeSandBoxに上げましたので、触ってみたかったらご自由にどうぞ。
https://codesandbox.io/s/teratailcomquestions323650-kjuj8?file=/index.html

この問題はJavaScript初心者にはそこそこ難しいと感じました。めげずに頑張ってください〜

投稿2021/02/20 08:58

JSChallenge

総合スコア11

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

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

kanix2020

2021/02/21 02:11 編集

返事が遅くなり申し訳ございません。 説明不足なのにも関わらずかなり丁寧に教えていただきありがとうございます。 おっしゃる通り、推測して頂いた動きを行いたく存じます。 (体操競技の採点をWeb上で行えるようにしたいと思っておりまして、  FX=床  PH=あんば  Ri=吊輪  Vo=跳馬  PB=平行棒  HB=鉄棒 といった具合です。) 頂いたご回答を熟読させて頂き、実践したいと思います。 私も早く理解をし、教えられる側になれるよう、頑張ります!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問