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

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

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

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

Q&A

解決済

2回答

6893閲覧

JavaScriptで年月日のプルダウンを動的に生成したい

tsuttsutsun

総合スコア1

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

1グッド

0クリップ

投稿2022/02/27 05:18

前提・実現したいこと

JavaScriptで年月日のプルダウンを自動生成し、選択された年月に応じた日のプルダウンを表示させたいです。
jQueryについてはまだ学習前のため、一旦は使わずに作成したいと思っています。

発生している問題・エラーメッセージ

最後の、Javascriptの「//年月が変更された場合に日のoptionを再取得」部分を追記すると、年または月のプルダウン選択後、ブラウザが動かなくなります。 デベロッパツールを利用してエラーがないか確認しましたが、エラー表示はありませんでした。

該当のソースコード

html

1<!DOCTYPE html> 2<html> 3<head> 4<meta charset="UTF-8" HTTP-EQUIV="Content-Script-Type" CONTENT="text/javascript"> 5<title>年月日プルダウン 作成サンプル</title> 6</head> 7<body> 8<select name="year" id="year"></select>9<select name=month" id="month"></select>10<select name="day" id="day"></select>11<script type="text/javascript" src="./js/ sample.js"></script> 12</body> 13</html>

javascript

1/** 2 * 年のオプションを作成する函数 3 */ 4function yearOption() { 5 6 //現在の日付けを取得 7 const now = new Date(); 8 9 //現在の年を取得 10 const nowYear = now.getFullYear(); 11 12 //現在から100年前を取得 13 const year100 = nowYear - 100; 14 15 //100年前から今年までループ 16 for (let i = year100; i <= nowYear; i++) { 17 18 //selectタグ取得 19 let select = document.getElementById("year"); 20 21 //option生成 22 let option = document.createElement("option"); 23 select.appendChild(option); 24 25 //optionのテキストとして年を代入 26 option.text = i; 27 } 28} 29 30/** 31 * 月のオプションを作成する函数 32 */ 33function monthOption() { 34 35 //1月から12月までループ 36 for (let i = 1; i <= 12; i++) { 37 38 //selectタグ取得 39 let select = document.getElementById("month"); 40 41 //option生成 42 let option = document.createElement("option"); 43 select.appendChild(option); 44 45 //optionのテキストとして月を代入 46 option.text = i; 47 } 48} 49 50/** 51 * 選択された年月の末日を取得する函数 52 */ 53function lastDay() { 54 let days; 55 let february; 56 let last; 57 let year = document.getElementById("year").value; 58 let month = document.getElementById("month").value; 59 60 //1月〜12月までの末日 61 let days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 62 63 //うるう年の2月の末日 64 february = 29; 65 66 //月が2月の場合 67 if (month == 2) { 68 69 //うるう年の場合 70 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { 71 72 //末日にうるう年2月の末日を代入 73 last = february; 74 75 //うるう年でない場合 76 } else { 77 78 //末日にその月の末日を代入 79 last = days[month - 1]; 80 } 81 82 //2月でない場合 83 } else { 84 85 //末日にその月の末日を代入 86 last = days[month - 1]; 87 } 88 89 //代入された末日を返す 90 return last; 91} 92 93/** 94 * 日のオプションを作成する関数 95 */ 96function dayOption() { 97 98 //日のoption要素 99 let children = day.children; 100 101 //日のoptionを削除 102 while (children.length) { 103 children[0].remove; 104 } 105 106 //年と月の値がある場合 107 if (year.value != "" && month.vaue != "") { 108 109 //末日を取得 110 let last_day = lastDay(); 111 112 //1日から末日までループ 113 for (let i = 1; i <= last_day; i++) { 114 115 //日のselectタグを取得 116 let select = document.getElementById("day"); 117 118 //option生成 119 let option = document.createElement("option"); 120 select.appendChild(option); 121 122 //optionに日を代入 123 option.text = i; 124 } 125 } 126} 127 128function birthdayOption() { 129 130 //年の取得 131 yearOption(); 132 133 //月の取得 134 monthOption(); 135 136 //日の取得 137 dayOption(); 138} 139 140//ウィンドウオブジェクトのロードが完了した場合に年月日の取得 141window.onLoad = birthdayOption(); 142 143//年月が変更された場合に日のoptionを再取得 144document.getElementById("year").onChange = dayOption(); 145document.getElementById("month").onChange = dayOption(); 146

試したこと

JavaScriptの読み込みと、オンロードで年月日のプルダウンの自動生成まではできている事が確認できています。
onChangeを追記する事でブラウザが動かなくなるため、ここが原因だと思って調べると、無限ループになっている可能性がある記述を見つけました。
が、なぜ動かなくなるのか、また、解決方法の見当がつかず、困っております。
お手数をおかけしますが、どなたかお力添えください!

arcxor👍を押しています

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

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

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

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

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

guest

回答2

0

コメントが適切に付けられていて構造的で非常にきれいなコードですね。しかしながら、ところどころで細かい記述ミスがあるようです。

CodePen で動作するコードを書いてみました。

なお、あなたのコーディングレベルであれば、jQueryを新たに覚えて用いる必要はないように思います。jQuery はネイティブのJavaScriptでDOMを操作するのが面倒だった2006年〜2013年頃のDOM操作用ライブラリです。使っても問題ありませんが、もはや使う必要がない可能性があります。

js

1/** 2 * 年のオプションを作成する函数 3 */ 4function yearOption() { 5 //現在の日付を取得 6 const now = new Date(); 7 8 //現在の年を取得 9 const nowYear = now.getFullYear(); 10 11 //現在から100年前を取得 12 const year100 = nowYear - 100; 13 14 //select要素取得 15 let select = document.getElementById("year"); 16 17 //100年前から今年までループ 18 for (let i = year100; i <= nowYear; i++) { 19 //option生成 20 let option = document.createElement("option"); 21 22 //optionのテキストとして年を代入 23 option.text = i; 24 25 //今年を選択済みにしておく 26 if (i === nowYear) option.selected = true; 27 28 select.appendChild(option); 29 } 30} 31 32/** 33 * 月のオプションを作成する函数 34 */ 35function monthOption() { 36 //select要素取得 37 let select = document.getElementById("month"); 38 39 //1月から12月までループ 40 for (let i = 1; i <= 12; i++) { 41 //option生成 42 let option = document.createElement("option"); 43 44 //optionのテキストとして月を代入 45 option.text = i; 46 47 select.appendChild(option); 48 } 49} 50 51/** 52 * 選択された年月の末日を取得する函数 53 */ 54function lastDay() { 55 let days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 56 let year = Number(document.getElementById("year").value); 57 let month = Number(document.getElementById("month").value); 58 let isLeapMonth = function (year, month) { 59 if (month !== 2) return false; 60 if (year % 400 === 0) return true; 61 if (year % 100 === 0) return false; 62 if (year % 4 === 0) return true; 63 return false; 64 }; 65 66 return days[month - 1] + (isLeapMonth(year, month) ? 1 : 0); 67} 68 69/** 70 * 日のオプションを作成する函数 71 */ 72function dayOption() { 73 //select要素取得 74 let select = document.getElementById("day"); 75 76 //日のoptionを削除 77 select.innerHTML = ''; 78 79 //年と月の値がない場合は何もしない 80 if (year.value === "" || month.value === "") return; 81 82 //末日を取得 83 let last_day = lastDay(); 84 85 //1日から末日までループ 86 for (let i = 1; i <= last_day; i++) { 87 //option生成 88 let option = document.createElement("option"); 89 90 //optionに日を代入 91 option.text = i; 92 93 select.appendChild(option); 94 } 95} 96 97function birthdayOption() { 98 //年の取得 99 yearOption(); 100 101 //月の取得 102 monthOption(); 103 104 //日の取得 105 dayOption(); 106} 107 108//ウィンドウオブジェクトのDOM構築が完了した場合に年月日の取得 109window.addEventListener('DOMContentLoaded', birthdayOption); 110 111//年月が変更された場合に日のoptionを再取得 112document.getElementById("year").addEventListener('change', dayOption); 113document.getElementById("month").addEventListener('change', dayOption);

投稿2022/02/27 10:01

arcxor

総合スコア2857

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

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

tsuttsutsun

2022/02/27 10:21

お褒めの言葉、ご指摘、ありがとうございます! 確かにケアレスミスが多い傾向にあるので、今後、より気をつけます。 記述していたコード以外にも、こんな使い方があるんだと大変勉強になりました! ありがとうございました!
guest

0

ベストアンサー

無限ループになっている可能性がある記述を見つけました。

どのあたりまで把握できているのかも具体的に記述すると回答がつきやすいかもしれませんね。

既存のコードを活かす形で修正してみました。
コメントに「**********」がある付近が修正箇所です。

js

1/** 2 * 年のオプションを作成する函数 3 */ 4 function yearOption() { 5 6 //現在の日付けを取得 7 const now = new Date(); 8 9 //現在の年を取得 10 const nowYear = now.getFullYear(); 11 12 //現在から100年前を取得 13 const year100 = nowYear - 100; 14 15 //100年前から今年までループ 16 for (let i = year100; i <= nowYear; i++) { 17 18 //selectタグ取得 19 let select = document.getElementById("year"); 20 21 //option生成 22 let option = document.createElement("option"); 23 select.appendChild(option); 24 25 //optionのテキストとして年を代入 26 option.text = i; 27 } 28} 29 30/** 31 * 月のオプションを作成する函数 32 */ 33function monthOption() { 34 35 //1月から12月までループ 36 for (let i = 1; i <= 12; i++) { 37 38 //selectタグ取得 39 let select = document.getElementById("month"); 40 41 //option生成 42 let option = document.createElement("option"); 43 select.appendChild(option); 44 45 //optionのテキストとして月を代入 46 option.text = i; 47 } 48} 49 50/** 51 * 選択された年月の末日を取得する函数 52 */ 53function lastDay() { 54 let days; 55 let february; 56 let last; 57 let year = document.getElementById("year").value; 58 let month = document.getElementById("month").value; 59 60 //1月〜12月までの末日 61 // let days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 62 // ********** 次のエラーのため二重に変数を定義するのではなく、再代入するように修正しました SyntaxError: Cannot declare a let variable twice: 'days'. 63 days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 64 65 //うるう年の2月の末日 66 february = 29; 67 68 //月が2月の場合 69 if (month == 2) { 70 71 //うるう年の場合 72 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { 73 74 //末日にうるう年2月の末日を代入 75 last = february; 76 77 //うるう年でない場合 78 } else { 79 80 //末日にその月の末日を代入 81 last = days[month - 1]; 82 } 83 84 //2月でない場合 85 } else { 86 87 //末日にその月の末日を代入 88 last = days[month - 1]; 89 } 90 91 //代入された末日を返す 92 return last; 93} 94 95/** 96 * 日のオプションを作成する関数 97 */ 98function dayOption() { 99 100 //日のoption要素 101 let children = day.children; 102 103 //日のoptionを削除 104 // while (children.length) { 105 // children[0].remove; 106 // } 107 // ********** 無限ループになるためforで後ろからremoveするように修正してみました 108 for (let i = children.length - 1; 0 <= i; i--) { 109 children[i].remove() 110 } 111 112 //年と月の値がある場合 113 if (year.value != "" && month.vaue != "") { 114 115 //末日を取得 116 let last_day = lastDay(); 117 118 //1日から末日までループ 119 for (let i = 1; i <= last_day; i++) { 120 121 //日のselectタグを取得 122 let select = document.getElementById("day"); 123 124 //option生成 125 let option = document.createElement("option"); 126 select.appendChild(option); 127 128 //optionに日を代入 129 option.text = i; 130 } 131 } 132} 133 134function birthdayOption() { 135 136 //年の取得 137 yearOption(); 138 139 //月の取得 140 monthOption(); 141 142 //日の取得 143 dayOption(); 144} 145 146//ウィンドウオブジェクトのロードが完了した場合に年月日の取得 147// window.onLoad = birthdayOption(); 148// ********** ()をつけるとその時点で関数が呼び出されてしまうため、()をつけずに関数自体を設定します 149window.onload = birthdayOption; 150 151//年月が変更された場合に日のoptionを再取得 152// document.getElementById("year").onChange = dayOption(); 153// document.getElementById("month").onChange = dayOption(); 154// ********** ()をつけるとその時点で関数が呼び出されてしまうため、()をつけずに関数自体を設定します 155document.getElementById("year").onchange = dayOption; 156document.getElementById("month").onchange = dayOption;

投稿2022/02/27 07:23

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tsuttsutsun

2022/02/27 10:14

修正・説明コメント含め、とてもわかりやく、ありがとうございます! 関数の使い方について、まだ理解が足りなかったようです。 また、質問時にどこまでわかっているかについても、次回より細かく記述させていただきます! 本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問