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

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

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

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

4回答

1177閲覧

プルダウンを切り替えると表の切り替えではなく追加がされてしまい困っています。

moe_ko

総合スコア5

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2021/06/17 01:52

前提・実現したいこと

プルダウン(年月)の切り替えで、表の中身(年月に対応する日付と曜日)を切り替えたいです。
現在、プルダウンを切り替えるたびに、下にどんどん日付と曜日が追加される形になってしまっています……。
何かご存じの方、いらっしゃればお教えいただけると助かります。

該当のソースコード

JavaScript

1$(function() { 2 var date = new Date(); 3 var year = date.getFullYear(); 4 var weekday = [ "日", "月", "火", "水", "木", "金", "土" ]; 5 6 // 選択された年月日を取得 7 var selected_year = document.getElementById("id_year"); 8 var selected_month = document.getElementById("id_month"); 9 let selected_dayCount = 1; // 日にちのカウント 10 let calendarHtml = ''; // HTMLを組み立てる変数 11 12 // プルダウン 13 $(function() { 14 /*ループ処理*/ 15 optionLoop = function(start, end, id) { 16 var i, opt; 17 opt = null; 18 for (i = end; i >= start ; i--) { 19 if (i === date) { 20 opt += "<option value='" + i + "' selected>" + i + "</option>"; 21 } else { 22 opt += "<option value='" + i + "'>" + i + "</option>"; 23 } 24 } 25 return document.getElementById(id).innerHTML = opt; 26 }; 27 28 /*関数設定*/ 29 optionLoop(1990, year, 'id_year'); 30 optionLoop(1, 12, 'id_month'); 31 }); 32 33 34 // カレンダー 35 calendarHtml += '<table>'; 36 37 // 見出し 38 calendarHtml += '<tr>'+'<th>'+"日"+'</th>' 39 +'<th>'+"曜日"+'</th>' 40 +'<th>'+"開始"+'</th>' 41 +'<th>'+"終了"+'</th>' 42 +'<th>'+"休憩(h)"+'</th>' 43 +'<th>'+"勤務時間(h)"+'</th>' 44 +'<th>'+"出欠"+'</th>' 45 +'</tr>'; 46 47 // 日付 48 document.getElementById("id_hyoji").onclick = function() { 49 // ここに#buttonをクリックしたら発生させる処理を記述する 50 }; 51 // ???????? 52 53 $('#id_year,#id_month').change(function() { 54 55 selected_year = $('#id_year').val(); 56 selected_month = $('#id_month').val(); 57 58 //選択月初日 59 var selected_startDate = new Date( selected_year, selected_month - 1, 1); 60 //月の最後の日 61 var selected_endDate = new Date(selected_year, selected_month, 0); 62 // 月の末日 63 var selected_endDayCount = selected_endDate.getDate(); 64 // 月の最初の日の曜日を取得 65 var selected_startDay = selected_startDate.getDay(); 66 let selected_weekCount = selected_startDay; // 曜日のカウント 67 68 for (let i = 0; i < selected_endDayCount; ++i) { 69 // 日付の生成 70 calendarHtml += '<tr>'+ '<td>' + selected_dayCount + '</td>'; 71 if(selected_dayCount>=selected_endDayCount){ 72 selected_dayCount = 1; 73 }else{ 74 selected_dayCount++; 75 } 76 // 曜日の生成 77 calendarHtml += '<td>' + weekday[selected_weekCount] + '</td>'+ '</tr>'; 78 if(selected_weekCount >= 6) { 79 selected_weekCount = 0; 80 } else { 81 selected_weekCount++; 82 } 83 } 84 calendarHtml += '</table>'; 85 document.querySelector('#calendar').innerHTML = calendarHtml; 86 }) 87}); 88

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3 <head> 4 <script 5 src="https://code.jquery.com/jquery-3.4.1.slim.min.js" 6 integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=" 7 crossorigin="anonymous"></script> 8 <meta charset="utf-8"> 9 <link rel="stylesheet" href="css/itiran.css"> 10 11 <title>勤怠管理システム</title> 12 </head> 13 14 <body> 15 <div class="honbun"> 16 <div class="top"> 17 <h1>勤怠一覧</h1> 18 </div> 19 <div class="select"> 20 21 <select class="cl_year" id="id_year"> 22 </select> 23 <a href="#" class="moji"> 2425 </a> 26 <select class="cl_month" id="id_month" name="name_month"> 27 </select> 28 <a href="#" class="moji"> 2930 </a> 31 32 <a href="#" class="hyoji"> 33 <input type="button" value="表示" id="id_hyoji"/> 34 <div id="view_hyoji"></div> 35 </a> 36 37 <table class="tableAll"> 38 <tr> 39 <th>実労働時間(h)</th> 40 <td>h</td> 41 <th>残業時間(h)</th> 42 <td>h</td> 43 <th>休憩時間(h)</th> 44 <td>h</td> 45 </tr> 46 </table> 47 </a> 48 49 <a href="#" class="logout">ログアウト</a> 50 </div> 51 52 <table> 53 <div id="calendar"></div> 54 </table> 55 56 <script type="text/javascript" src="itiran.short.js"></script> 57 </body> 58 </html>

試したこと

break;を入れてみる、内容のリセットやクリアなどで検索してみましたが、うまく該当しそうなものが引っかからず、何を変更すればいいのかもわかりません……。

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

何か不足している情報などございましたらご指摘いただけると助かります。
どうぞよろしくお願いいたします。

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

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

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

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

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

guest

回答4

0

今のコードはあまり修正しないという方向でご回答させていただきます。もっと良いコードをとは思いましたが、質問の範囲外になってしまうので。

さて、セレクトボックス(プルダウン)を切り変えると、どんどん追加される現象ですが、これはcalendarHtmlにどんどん組み立てるHTMLの文字列が追記されていくからです。

具体的には

javascript

1 2$(function() { 3 /* 中略 */ 4 5 let calendarHtml = ''; // HTMLを組み立てる変数 6

冒頭で変数宣言したcalendarHTMLが

javascript

1 2 // カレンダー 3 calendarHtml += '<table>'; 4 5 // 見出し 6 calendarHtml += '<tr>'+'<th>'+"日"+'</th>' 7 +'<th>'+"曜日"+'</th>' 8 +'<th>'+"開始"+'</th>' 9 +'<th>'+"終了"+'</th>' 10 +'<th>'+"休憩(h)"+'</th>' 11 +'<th>'+"勤務時間(h)"+'</th>' 12 +'<th>'+"出欠"+'</th>' 13 +'</tr>'; 14

カレンダーの見出しの文字列を追加していて、ここまでは良いのですが、問題はここからで

javascript

1 // セレクトボックスの切り替えイベントの度に起こる 2 3 $('#id_year,#id_month').change(function() { 4 5 /* 中略 */ 6 7 for (let i = 0; i < selected_endDayCount; ++i) { 8 // 日付の生成 9 calendarHtml += '<tr>'+ '<td>' + selected_dayCount + '</td>'; 10 if(selected_dayCount>=selected_endDayCount){ 11 selected_dayCount = 1; 12 }else{ 13 selected_dayCount++; 14 } 15 // 曜日の生成 16 calendarHtml += '<td>' + weekday[selected_weekCount] + '</td>'+ '</tr>'; 17 if(selected_weekCount >= 6) { 18 selected_weekCount = 0; 19 } else { 20 selected_weekCount++; 21 } 22 } 23 calendarHtml += '</table>'; 24 document.querySelector('#calendar').innerHTML = calendarHtml; 25 }) 26

このところで、calendarHTMLに、セレクトボックスで選んだ内容に従って日付と曜日の追加をしています。ですが、困ったことに、プルダウンを選択するたびに、繰り返しこのところが実行されますが、
「古い内容」が残っているので、どんどん日付と曜日が追加される形になってしまいます。

さて、この状況を簡単に解決するには、画面を更新のすべきタイミングで、古い内容を消去する必要があるでしょう。古い内容、つまりCalendarHTMLの変数をどこかで空の文字列にして、もう一度文字列を作り直せばいいのです。

そうして、空にしたcalendarHTMLに、HTMLの文字列を作りなおせばいいのです。大変そうに聞こえますが、Webページを開いたときに、一度やってることをもう一度やれば良いだけなのです。

さて実際にやってみましょう。

まず、画面の更新のすべきタイミングで古い内容を消去しましょう。更新すべきタイミングは、セレクタが変更されたとき。そして、消去は先程もいいましたが、空文字列を入れるだけです。

$('#id_year,#id_month').change(function() { calendarHTML = "" // 一度calendarHTMLをリセット!

しかし、このイベントの前にカレンダーの見出しの文字列を追加しています。文字列をつくりなおすには、見出しの文字列も必要です。

なので、そのまま、リセット後にコードをコピペをしてもいいですが....

javascript

1 $('#id_year,#id_month').change(function() { 2 3 calendarHTML = "" // 一度calendarHTMLをリセット! 4 // カレンダー 5 calendarHtml += '<table>'; 6 7 // 見出し 8 calendarHtml += '<tr>'+'<th>'+"日"+'</th>' 9 +'<th>'+"曜日"+'</th>' 10 +'<th>'+"開始"+'</th>' 11 +'<th>'+"終了"+'</th>' 12 +'<th>'+"休憩(h)"+'</th>' 13 +'<th>'+"勤務時間(h)"+'</th>' 14 +'<th>'+"出欠"+'</th>' 15 +'</tr>';

これでも十分に動くと思いますが、せっかくなので、ちょっとだけ良くします。

このコードはセレクトボックスの変更されても、毎回変える必要がない文字列です。毎回変える必要がないのに、毎回変える度に、この文字列をつくっているのはなんか無駄な感じもしませんか? 変更する部分だけを書き変えれば良いだけですよね?

なので、一旦変更するべきでない文字列を一旦別の変数に持っておいて、それをcalendarHTMLを組み立てるときに利用しましょう。また、「変更するべきでない」つまり「変わらない」ので、定数がつかえます!!!

javascript

1 let calendarHtml = ''; // HTMLを組み立てる変数 2 3 // カレンダーの見出しを作る変数(更新するイベントの外で持ってることに注目!!) 4 const calendarHeadHtml = '<table>' 5 + '<tr>'+'<th>'+"日"+'</th>' 6 +'<th>'+"曜日"+'</th>' 7 +'<th>'+"開始"+'</th>' 8 +'<th>'+"終了"+'</th>' 9 +'<th>'+"休憩(h)"+'</th>' 10 +'<th>'+"勤務時間(h)"+'</th>' 11 +'<th>'+"出欠"+'</th>' 12 +'</tr>'; 13 14 $('#id_year,#id_month').change(function() { 15 16 calendarHTML = calendarHeadHTML // カレンダーの見出しのデータにリセット!!!

空文字列を代入するかわりに、calendarHeadHtmlを突っこんでます。

さて、もう一点だけ、イベントの外で、calendarHTMLを宣言していますが、こうなるほcalendarHTMLは、変更イベントのみで使うので、イベントの中で宣言してあげましょう。

javascript

1 2 // カレンダーの見出しを作る変数(更新するイベントの外で持ってることに注目!!) 3 const calendarHeadHtml = '<table>' 4 + '<tr>'+'<th>'+"日"+'</th>' 5 +'<th>'+"曜日"+'</th>' 6 +'<th>'+"開始"+'</th>' 7 +'<th>'+"終了"+'</th>' 8 +'<th>'+"休憩(h)"+'</th>' 9 +'<th>'+"勤務時間(h)"+'</th>' 10 +'<th>'+"出欠"+'</th>' 11 +'</tr>'; 12 13 $('#id_year,#id_month').change(function() { 14 15 let calendarHTML = calendarHeadHTML; // カレンダーの見出しのデータにリセット!!! イベントの外でやる必要はないね!!!

このようにしたおかげで、たとえば「letは変更するべき変数」「constは変更するべきではない変数」みたいな区別がついたりしたり、こうすることによって、letを局所的にできたりすることができました。

このように「変更するべき一部分だけを書き変える」ということは非常に重要なことでして、効率的になったりすることが多々あります。ただ通常は記述が複雑になったりすることもありますのでその辺はトレードオフでしょう。

すいません、ついつい余計なことも書いちゃって、長くなりましたが。以上です。問題まずは解決することを望みます。

投稿2021/06/17 03:16

nobkz

総合スコア320

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

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

moe_ko

2021/06/17 03:55

ご回答ありがとうございます。 ご丁寧に本当にありがとうございます。 とても勉強になりました。 ご提示いただいたコード、とてもわかりやすいです。 参考に自分のコードを見直します。 本当にありがとうございました。
guest

0

HTMLの構文でErrorが結構出ているようなので、それも解消することをお勧めします^^;
https://validator.w3.org/#validate_by_input

それはさておき、htmlがどんどん追加されていく理由は、calendarHtmlの中がリセットされてないからだと考えます。プルダウンのonChange後にcalendarHtmlを空にしてあげると、悩みは解決しますかね?

javascript

1$('#id_year,#id_month').change(function() { 2 calendarHtml = '' 3 〜省略〜 4}

投稿2021/06/17 02:49

runnynose

総合スコア497

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

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

moe_ko

2021/06/17 03:15

ご回答ありがとうございます。 URL、拝見させていただきました。 こんな便利なものがあるのですね……。 色々と調べて追加していくうちによくわからなくなってくることも多いのですごくありがたいです。 また、ご指摘いただいたコードでも(HTMLの構文エラーのせいなのか、装飾が反映されませんでしたが)解決できました。 今回は、先にコメントいただいた方をベストアンサーに選ばせていただきました。申し訳ありません。 すごく勉強になりました。ありがとうございます。
runnynose

2021/06/17 10:18

ベストアンサー欲しかったです><笑 質問欄にあるHTMLみると閉じがおかしい部分があったりしました。 Dom構造がおかしいとJSにも影響するので、そこも注視することをお勧めします!
guest

0

ベストアンサー

こんにちは。
スコープの問題だと思いますので、イベントリスナの中に閉じ込めてやるといいかと思います。

以下のようにするとどうでしょうか?

js

1 2 const calendarHtml2 = calendarHtml; // 追加 3 4 $('#id_year,#id_month').change(function () { 5 6 let calendarHtml = calendarHtml2; // 追加 7

投稿2021/06/17 02:37

Lhankor_Mhy

総合スコア36117

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

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

moe_ko

2021/06/17 03:05

ありがとうございます。 希望通りの動きをしてくれました。 利害が及ばず申し訳ないのですが、これは、何をなおしてあげたことになるのでしょうか……? もし、お時間が許せばお教えいただけると嬉しいです。
Lhankor_Mhy

2021/06/17 03:25 編集

まず、前提知識なのですが、変数にはスコープという有効範囲があります。 大雑把に言うと、let や const は 宣言が含まれる {} の中でしか有効ではないのです。 ご提示の問題は、他の回答でも指摘されていますが、calendarHtml の値が共有されているため、追記される形になっているのが原因です。 これは、 let calendarHtml が、changeイベントをまたぐような大きな有効範囲を持っているために起きています。 そこで、 let calendarHtml を、changeイベントの中に書いてやれば、その有効範囲をchangeイベントの中に閉じ込めることができるので、イベントの処理が終わればその値が消えるようになるため、値を共有することがなくなり、問題に対する解決方法になる、というわけです。 一方で、th などで書かれた列項目は使いまわすため、changeイベントをまたぐような大きな有効範囲のままにしたいので、changeイベントの外で宣言したままで共有しています。 (本来、const calendarHtml2 = calendarHtml は必要のないコードなのですが、let calendarHtml = calendarHtml のような同名のスコープの違う変数の代入はできないので、別名の変数を用意しています)
moe_ko

2021/06/17 03:30

なるほど。そういうことだったのですね。 初歩的な質問にもかかわらず、ご丁寧にわかりやすくご説明いただきありがとうございます。
Lhankor_Mhy

2021/06/17 08:13

お役に立てたようで何よりです。
guest

0

まず助言ですが、コード全体のインデントをちゃんと整えましょう。

で、あなたのコードでcalendarHtmlという変数を使っている文を抜き出すと、こうです。

JavaScript

1$(function() { 2 let calendarHtml = ''; // HTMLを組み立てる変数 3 // カレンダー 4 calendarHtml += '<table>'; 5 6 // 見出し 7 calendarHtml += '<tr>'+'<th>'+"日"+'</th>' 8 +'<th>'+"曜日"+'</th>' 9 +'<th>'+"開始"+'</th>' 10 +'<th>'+"終了"+'</th>' 11 +'<th>'+"休憩(h)"+'</th>' 12 +'<th>'+"勤務時間(h)"+'</th>' 13 +'<th>'+"出欠"+'</th>' 14 +'</tr>'; 15 16 $('#id_year,#id_month').change(function() { 17 for (let i = 0; i < selected_endDayCount; ++i) { 18 calendarHtml += '<tr>'+ '<td>' + selected_dayCount + '</td>'; 19 calendarHtml += '<td>' + weekday[selected_weekCount] + '</td>'+ '</tr>'; 20 calendarHtml += '</table>'; 21 document.querySelector('#calendar').innerHTML = calendarHtml; 22 }) 23});

自分で何をやっているのか、わかっていますか?

まずcalendarHtmlに見出しが入れていますが、ただ入れただけで、documentには追加したりはしていませんね。そして入れた値も<table>を閉じるところまではできておらず未完成の状態です。

そして年か月が変更された時に実行される関数内で、calendarHtmlに1か月分のデータを追加して</table>で閉じてdocumentに追加しています。1回目に年か月が変更されたときに、ここでやっとcalendarHtmlの中身が完成して表示されているわけです。

で、次にまた年か月が変更されて、この関数が実行されたら、calendarHtmlの値はどうなって、それがdocumentに反映されて、どうなりますか?

と、私がコードを解析して説明しましたが、あなたの書いたコードですよ。

投稿2021/06/17 02:23

itagagaki

総合スコア8402

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問