- 締切済み
コードの意味(どのようなイベント発生など)を調べて
https://jsfiddle.net/jun68ykt/p2uj40xn/43/は、面積を入力で坪数の計算と坪単価の計算するjavascriptでしたが、要望で価格(○○.○○万円)÷坪数(○○.○○坪)=坪単価で計算するjavascriptに直す為にそのコードをどのように直すかをやる前にソースコードを理解しないと出来ないと思い、調べながら、修正していました。 昨日、修正したいと要望があって、htmlとjavascriptを修正しています。 で、自分で調べて、1つ1つ修正していますが、インターネットで調べても分からないことがありまして、ここで質問しさせてください。 分からないことがいくつかがあります。 (1) var row = e.target.parentNode.parentNode;の「parentNode.parentNode」をインターネットで調べたら、「【JavaScript】(基礎)親要素・子要素の取得まとめ(2)」が出ました。 parentNodeを2つ付けるということは、祖先要素を取得するようなものだということで、htmlを見ますと、 <input>要素から見ると、<td>要素は親要素で、<tr>要素は祖先要素ということで、合っているでしょうか? (2) var pos = e.target.className.split(/\s/)[0];の「className.split」をインターネットで調べたら、「かもメモ」が出ました。 先日、修正したいと要望があって、htmlとjavascriptを修正しています。 で、自分で調べて、1つ1つ修正していますが、インターネットで調べても分からないことがありまして、ここで質問しさせてください。 分からないことがいくつかがあります。 (1) var row = e.target.parentNode.parentNode;の「parentNode.parentNode」をインターネットで調べたら、「【JavaScript】(基礎)親要素・子要素の取得まとめ(2)」が出ました。 parentNodeを2つ付けるということは、祖先要素を取得するようなものだということで、htmlを見ますと、 <input>要素から見ると、<td>要素は親要素で、<tr>要素は祖先要素ということで、合っているでしょうか? (2) var pos = e.target.className.split(/\s/)[0];の「className.split」をインターネットで調べたら、「かもメモ」が出ました。 「className.split」は、class名を取得するときに使うそうですが、「(/\s/)[0]」って、どういうことですか? それをインターネットで調べたら、これが出ました。 https://stackoverflow.com/questions/28127794/difference-between-split-s-and-split しかし、上記のサイトは、(/\s+/)のことを 『1つの空白文字(タブ、改行、改行、垂直タブ、フォームフィード)を1回と無制限の時間で一致させます。』 ↑ Match a single whitespacecharacter (tab, line feed, carriage return, vertical tab, form feed) between one and unlimmited times. でも、 (/\s/)のことは載っていませんでした。 [0]は、どいうことかな? あと、『1つの空白文字(タブ、改行、改行、垂直タブ、フォームフィード)を1回と無制限の時間で一致させます。』を読んでもどういうことか?は分かりませんでした。 (3) switch(pos)は、条件分岐するものですが、switch(pos) { }の中身が難しくてどういう働きするのか?の分析ができませんでした。 頑張って調べても分からないことがありましたので、すみませんが、よろしくお願いします。
- みんなの回答 (9)
- 専門家の回答
みんなの回答
- babu_baboo
- ベストアンサー率51% (268/525)
ちょっとぉ >おそらく「質問の範囲が広すぎる」が根本的な問題です。 私の示したスクリプトは無駄に長く書いているだけで ショートコーディングしたら数行(1行?)ですみます。 たったそれくらいを質問者が理解できないはずがないではないでしょう! 今に立派なプログラマーに成長するに違いない! 本当はエスパーじゃないことを白状しますが。
- think49
- ベストアンサー率59% (285/482)
おそらく「質問の範囲が広すぎる」が根本的な問題です。 https://ja.stackoverflow.com/help/mcve 回答されても理解できないのは前提となる基礎知識が大きく欠けているからです。 JavaScriptとDOMについて基礎的なAPIを全て頭に叩き込んでから、本課題に取り組んでください。 自分の力量を大きく超える課題に取り組んでも時間を浪費するだけです。 https://developer.mozilla.org/ja/docs/Learn/JavaScript https://developer.mozilla.org/ja/docs/DOM --- 二次被害が広まらないよう書いておきますが、amaryllis_watchさんが出しているコードは IE, Android(Google Chrome)が動作要件に入っています。 https://teratail.com/questions/144292 > amaryllis 2018/09/03 13:30 > jun68yktさん、気づいた点があります。 > 1つめは、IE系ブラウザに対応してない。 > 2つめは、AndroidでGoogle Chromeのブラウザで小数点入力が出来ない(坪単位入力欄)。 ちなみに、この質問はteratailのamaryllis名義で質問されている内容と同一なので、これから回答する方はマルチポスト先で同じ内容が回答されていないか確認した方が良いです。 https://teratail.com/users/amaryllis#question Re: amaryllis_watch さん
- babu_baboo
- ベストアンサー率51% (268/525)
後出しジャンケンには付き合っていられません。 何か要望を満たすと、次は。。。その繰り返しとなります 私はエスパーなのでわかります。 いまさらIEといわれても、なにそれ? 今更ですが質問のタイトルの意義もすでに違っています。 締め切って質問内容を的確に表現したタイトルで質問しなおしなさい。 良い質問には良い答えが返ってきます。 これは質問ではなく結局丸投げです。 最低です。
- babu_baboo
- ベストアンサー率51% (268/525)
最初に示したコードが一切使われていないのね 入力に対してエラーがあった場合の処理は無視。 全角空白は半角にでもちかんしてね <!DOCTYPE html> <meta charset="UTF-8"> <html lang="ja"> <title>?</title> <style> #T, #T td, #T th { border: solid 1px #000; border-collapse: collapse; } #T th { background-color: #aaa; } #T td { padding: 5px; } #T tr td:last-of-type { width : 150px; } #T input { font-size: 16px; width: 100px; } #T input[readonly] { background: #eee; } #T tr td:last-of-type input { text-align: right; } input.error { background-color: #d14; } </style> <body> <table id="T"> <tr> <th>区画名 <th>面積 <th>坪数 <th>価格 <th>坪単価 <tr> <td><input> <td><input> m2 <td><input readonly> 坪 <td><input> 万円 <td><input readonly> 円 <tr> <td><input> <td><input> m2 <td><input readonly> 坪 <td><input> 万円 <td><input readonly> 円 <tr> <td><input> <td><input> m2 <td><input readonly> 坪 <td><input> 万円 <td><input readonly> 円 </table> <script> const table = document.querySelector ('#T'), getNum = e => parseFloat (e.value), handler = (event) => { let inp = event.target, tr = inp.parentNode.parentNode, inps = tr.querySelectorAll ('input, output'), tubo = getNum (inps[1]) / 0.3025, tanka = getNum (inps[3])*10000 / tubo; inps[2].value = isNaN (tubo) ? '' : tubo.toFixed (2); inps[4].value = isNaN (tanka) ? '': tanka.toFixed (2); } table.addEventListener ('input', handler, false); </script>
- babu_baboo
- ベストアンサー率51% (268/525)
丸投げだと嫌だ!
補足
htmlが <table> <tr> <th>区画名</th> <th>面積</th> <th>坪数</th> <th>価格</th> <th>坪単価</th> </tr> <tr> <td><input type="text" name="se01_a" class="se_a" value=""></td> <td><input type="text" name="se01_b" value="" class="se_b"> m2</td> <td><input type="text" name="se01_c" value="" class="se_c tsubo"> 坪</td> <td><input type="text" name="se01_d" value="" class="se_d kingaku"> 万円</td> <td class="result"><span class="tubotan"></span></td> </tr> <tr> 上記の同じコードを5セット~10セット </tr> </table> にして、javascriptは、 var inputs = document.getElementsByTagName('input'); for (var i=0; i < inputs.length; i ++ ) { inputs[i].addEventListener('input', inputHandler); } function inputHandler(e) { var value = 0; var row = e.target.parentNode.parentNode; var pos = e.target.className.split(/\s/)[0]; switch(pos) { case 'se_b': e.target.value = e.target.value.replace(/[^0-9.]/,''); if (/^[0-9]*(\.[0-9]*)?$/.test(e.target.value)) { value = Number(e.target.value); e.target.className = e.target.className.replace(' error',''); price({ se_b: value, row }); } else { if (e.target.className.indexOf('error') < 0) e.target.className += ' error'; row.getElementsByClassName('tsubo')[0].innerHTML = ''; row.getElementsByClassName('kingaku')[0].innerHTML = ''; } break; case 'se_c': value = Number(e.target.value.replace(/[^0-9]/g,'')); e.target.value = value > 0 ? value.toLocaleString('ja-JP') : ''; price({ se_c: value, row }); break; case 'se_d': value = Number(e.target.value.replace(/[^0-9]/g,'')); e.target.value = value > 0 ? value.toLocaleString('ja-JP') : ''; price({ se_d: value, row }); break; default: break; } } function price({se_b, se_c, se_d, row }) { if (!row) return; var se01bNode = row.getElementsByClassName('se_b')[0]; var se01cNode = row.getElementsByClassName('se_c')[0]; var se01dNode = row.getElementsByClassName('se_d')[0]; se_b = (se_b >= 0 ? se_b : Number(se01bNode.value)); se_c = (se_c >= 0 ? se_c : Number(se01cNode.value.replace(/[^0-9]/g,''))); se_d = (se_d >= 0 ? se_d : Number(se01dNode.value)); var tsubo = se_b * 0.3025; var kingaku = tsubo * se_c; var tsubotan = se_d / se_c; tsubo = Math.floor(tsubo * 10.0) / 10.0; // 少数点第2位以下を切り捨て var tsuboNode = row.getElementsByClassName('tsubo')[0]; var kingakuNode = row.getElementsByClassName('kingaku')[0]; var tsubotanNode = row.getElementsByClassName('tsubotan')[0]; tsuboNode.innerHTML = (tsubo > 0 ? `${tsubo}` : ''); kingakuNode.innerHTML = (kingaku > 0 ? `${kingaku.toLocaleString('ja-JP')}` : ""); tsubotanNode.innerHTML = (tsubotanNode > 0 ? `${tsubotanNode}` : ''); } にしてみたけど全然ダメです。 リアルタイムに計算されてない。 あと、se_cの坪数に小数点入力ができない。 私はjavascriptに詳しくなく、あのままのコードに追加や関数の一部に変更くらいしかできずにしています。 本当は、se_bとse_cとse_dは通常入力で「se_d / se_c」で計算したのを<span class="tubotan"></span>に表示するコードにしたかったが、できなかった。
- babu_baboo
- ベストアンサー率51% (268/525)
ちょっとだけ解説 イベントは親要素(document)で監視する。今回は #T イベントが発生したらそのイベントが発生した要素を取得する input要素なのだからちょっと省いて、親の親 tr を取得 その tr 要素の子の中から input要素を抜き出す input要素の番号を指定しながら計算する 結果を書き出す input要素に個別にイベントを貼りつけるなんてあほらしい classの指定もマジソレ必要?ってかんじ。
補足
https://jsfiddle.net/jun68ykt/p2uj40xn/43/は、他の人に作ってもらったんで、それを自分なりに変えようとしても、難しくてとても出来ませんでした。 変えても自動計算で表示も出来ない。 どれかが悪いのかも分からない。 申し訳ございませんが、どのようなコードにするかを教えて頂けませんでしょうか。
- babu_baboo
- ベストアンサー率51% (268/525)
ゴメン。私の書いたものはあきらめて!
- babu_baboo
- ベストアンサー率51% (268/525)
ずいぶん面倒なコードですね。簡単にしてみました。 <!DOCTYPE html> <meta charset="UTF-8"> <html lang="ja"> <title>?</title> <style> #T input {text-align: right; } #T tr td:first-of-type input { color: red; } #T tr td:nth-of-type(2) input { color: blue; } #T tr td:nth-of-type(3) input { color: green; } </style> <body> <table id="T"> <tr> <th>金額(円) <th>坪数 <th>坪単価(円/坪) <tr> <td><input> <td><input> <td><input readonly> <tr> <td><input> <td><input> <td><input readonly> </table> <script> const table = document.querySelector ('#T'), getNum = e => parseFloat (e.value), handler = (event) => { let inp = event.target, tr = inp.parentNode.parentNode, inps = tr.querySelectorAll ('input'), tubotanka = getNum (inps[0]) / getNum (inps[1]), rst = isNaN (tubotanka) ? 'error' : tubotanka.toFixed (2) + ' 円'; inps[2].value = rst; } table.addEventListener ('input', handler, false); </script>
補足
babu_babooさん、回答をありがとうございます。 訳あって、同じようなのを5~10セット作る必要があって、 javascritでは、「row」を使っています。 そして、質問した「価格(○○.○○万円)÷坪数(○○.○○坪)=坪単価で計算するjavascriptに直す」ためにjavascriptを直す際、そのコードはどういった動きやイベント発生などを調べて直していますが、私の知識では、ハードルが高くて、まだ直せていません。 https://jsfiddle.net/jun68ykt/p2uj40xn/43/では、 <tr> <th></th> <th>平米数(m2)</th> <th class="result">坪数</th> <th>坪単価(円/坪)</th> <th class="result">金額(円)</th> </tr> <tr> <td><input type="text" class="se_a" value=""></td> <td><input type="text" value="" class="se_b"></td> <td class="result"><span class="tsubo"></span></td> <td><input type="text" value="" class="se_c"></td> <td class="result"><span class="kingaku"></span></td> </tr> ↑ それを <tr> <th>区画名</th> <th>面積</th> <th>坪数</th> <th>価格</th> <th>坪単価</th> </tr> <tr> <td><input type="text" class="se_a" value=""></td> <td><input type="text" value="" class="se_b"> m2</td> <td><input type="text" value="" class="se_c"> 坪</td> <td><input type="text" value="" class="se_d"> 万円</td> <td class="result"><span class="tubotan"></span></td> </tr> に変更する。 javascriptで計算は、「tubotan = se01_d * se_c」にして、 「.getElementsByClassName('tubotan')」で <span class="tubotan"></span>に表示させる方法に変えるんです。 そのためにどうすれば、どこをどのように変えるか?をインターネットで調べていた。
- t_ohta
- ベストアンサー率38% (5238/13706)
(1) 貴方の理解で間違いないと思います。 (2) プログラムで文字列の一部を取得したりするのに『正規表現』と言うモノを使用します。 正規表現は多くの言語で使用される仕組みなので正規表現で検索して勉強してみましょう。 (3) switch分は if (pos == 1) { 処理A; } else if (pos == 2) { 処理B; } else if (pos == 3) { 処理C; } else { 処理D; } を switch (pos) { case 1: 処理A; break; case 2: 処理B; break; case 3: 処理C; break; default: 処理D; } と置き換えたモノです。
補足
ありがとうございます。 スマホでテストしてみました。 正常に働きましたが、会社のPCは、IE系ブラウザを使用しているので、IE系ブラウザでテストしたら、面積のinputに入力すると「×」が表示され、リアルタイム計算出来ません。 Google chromeは未確認です。