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

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

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

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

Q&A

解決済

1回答

2808閲覧

【javascript】カレンダーのクリックした日付にクラスを付与したい

kii.32

総合スコア67

JavaScript

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

0グッド

1クリップ

投稿2021/10/02 10:52

編集2021/10/03 09:14

前提・実現したいこと

Js: カレンダーの日にちをたっぷしたらhtmlのinputに反映させたい。

こちらを参考にカレンダーを作成しました。

クリックしている日付がわかる様に、クリックしたtdにクラスを付与したいのですが、
クラス付与がうまくできずこちらで質問をさせていただきました。

該当のソースコード

<div class="main users-new"> <div class="container"> <input type="text" value="today" onselect="click_date" readonly> <div id="calendar"></div> </div> </div> <script> // カレンダー // 現在の年月の取得 var current = new Date(); var year = current.getFullYear(); var month = current.getMonth() + 1; // カレンダーの表示 var wrapper = document.getElementById('calendar'); add_calendar(wrapper, year, month); function handler(e) { if (e.target.innerText === "") return; const yearmonth = document.querySelector(".calendar-header__title").innerText; document.querySelector("input").value = yearmonth + e.target.innerText + "日"; } /** * 指定した年月のカレンダーを表示する * @param {object} wrapper - カレンダーを追加する親要素 * @param {number} year - 年の指定 * @param {number} month - 月の指定 */ function add_calendar(wrapper, year, month) { // 現在カレンダーが追加されている場合は一旦削除する wrapper.textContent = null; // カレンダーに表示する内容を取得 var headData = generate_calendar_header(wrapper, year, month); var bodyData = generate_month_calendar(year, month); // カレンダーの要素を追加 wrapper.appendChild(headData); wrapper.appendChild(bodyData); document.querySelectorAll("td").forEach(function (target) { // 引数targetにはdiv要素が1つずつ渡されている target.addEventListener('click', handler); }); let btnToggleclass = function (el) { el.classList.toggle('classname'); } btn.addEventListener('click', function () { btnToggleclass(box); }, false); } /** * 指定した年月のカレンダーのヘッダー要素を生成して返す * @param {object} wrapper - カレンダーを追加する親要素 * @param {number} year - 年の指定 * @param {number} month - 月の指定 */ function generate_calendar_header(wrapper, year, month) { // 前月と翌月を取得 var nextMonth = new Date(year, (month - 1)); nextMonth.setMonth(nextMonth.getMonth() + 1); var prevMonth = new Date(year, (month - 1)); prevMonth.setMonth(prevMonth.getMonth() - 1); // ヘッダー要素 var cHeader = document.createElement('div'); cHeader.className = 'calendar-header'; // 見出しの追加 var cTitle = document.createElement('div'); cTitle.className = 'calendar-header__title'; var cTitleText = document.createTextNode(year + '年' + month + '月'); cTitle.appendChild(cTitleText); cHeader.appendChild(cTitle); // 前月ボタンの追加 var cPrev = document.createElement('button'); cPrev.className = 'calendar-header__prev'; var cPrevText = document.createTextNode('prev'); cPrev.appendChild(cPrevText); // 前月ボタンをクリックした時のイベント設定 cPrev.addEventListener('click', function () { add_calendar(wrapper, prevMonth.getFullYear(), (prevMonth.getMonth() + 1)); }, false); cHeader.appendChild(cPrev); // 翌月ボタンの追加 var cNext = document.createElement('button'); cNext.className = 'calendar-header__next'; var cNextText = document.createTextNode('next'); cNext.appendChild(cNextText); // 翌月ボタンをクリックした時のイベント設定 cNext.addEventListener('click', function () { add_calendar(wrapper, nextMonth.getFullYear(), (nextMonth.getMonth() + 1)); }, false); cHeader.appendChild(cNext); return cHeader; } /** * 指定した年月のカレンダー要素を生成して返す * @param {number} year - 年の指定 * @param {number} month - 月の指定 */ function generate_month_calendar(year, month) { var weekdayData = ['日', '月', '火', '水', '木', '金', '土']; // カレンダーの情報を取得 var calendarData = get_month_calendar(year, month); var i = calendarData[0]['weekday']; // 初日の曜日を取得 // カレンダー上の初日より前を埋める while (i > 0) { i--; calendarData.unshift({ day: '', weekday: i }); } var i = calendarData[calendarData.length - 1]['weekday']; // 末日の曜日を取得 // カレンダー上の末日より後を埋める while (i < 6) { i++; calendarData.push({ day: '', weekday: i }); } // カレンダーの要素を生成 var cTable = document.createElement('table'); cTable.className = 'calendar-table'; var insertData = ''; // 曜日部分の生成 insertData += '<thead>'; insertData += '<tr>'; for (var i = 0; i < weekdayData.length; i++) { insertData += '<th>'; insertData += weekdayData[i]; insertData += '</th>'; } insertData += '</tr>'; insertData += '</thead>'; // 日付部分の生成 insertData += '<tbody>'; for (var i = 0; i < calendarData.length; i++) { if (calendarData[i]['weekday'] <= 0) { insertData += '<tr>'; } insertData += '<td>'; insertData += calendarData[i]['day']; insertData += '</td>'; if (calendarData[i]['weekday'] >= 6) { insertData += '</tr>'; } } insertData += '</tbody>'; cTable.innerHTML = insertData; return cTable; } /** * 指定した年月のカレンダー情報を返す * @param {number} year - 年の指定 * @param {number} month - 月の指定 */ function get_month_calendar(year, month) { var firstDate = new Date(year, (month - 1), 1); // 指定した年月の初日の情報 var lastDay = new Date(year, (firstDate.getMonth() + 1), 0).getDate(); // 指定した年月の末日 var weekday = firstDate.getDay(); // 指定した年月の初日の曜日 var calendarData = []; // カレンダーの情報を格納 var weekdayCount = weekday; // 曜日のカウント用 for (var i = 0; i < lastDay; i++) { calendarData[i] = { day: i + 1, weekday: weekdayCount } // 曜日のカウントが6(土曜日)まできたら0(日曜日)に戻す if (weekdayCount >= 6) { weekdayCount = 0; } else { weekdayCount++; } } return calendarData; } // こちらを追加 $(function () { $(".calendar-table td").on("click", function () { $(".calendar-table td").removeClass("active"); $(this).addClass("active"); }); }); </script>

試したこと

下記を追加してみたのですが、うまくいかず。。
有識者の方がいらっしゃいましたら、ご教授いただけますと幸いです。

// こちらを追加 const btn = document.querySelector('.calendar-table td'); btn.addEventListener('click', (e) => { e.target.classList.toggle('active'); });

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

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

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

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

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

m.ts10806

2021/10/02 11:15

>下記を追加してみたのですが どこに追加したのでしょうか。 エラー等は出てませんか?
kii.32

2021/10/02 11:22

追加は<script>内の一番下に追加していたのですが、 下記エラーが出ておりました。。! Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') at add_calendar (script.js?ver=1.0.0:285) at window.onload (script.js?ver=1.0.0:251)
m.ts10806

2021/10/02 11:55

込のコードを提示してください
guest

回答1

0

ベストアンサー

html上にあらわれてない要素は参照できないので、htmlに追記後、イベント付与してください。

投稿2021/10/02 11:55

m.ts10806

総合スコア80875

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

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

kii.32

2021/10/02 12:34

ありがとうございます。 addEventListenerが実行された時に.calendar-table tdが存在していないためエラーということですよね。。 HTMLより下かつscript内でも一番したに、追記をしているのにエラーが出てしまうのは何故なのでしょうか?
m.ts10806

2021/10/02 21:20

onload は全部読み込み後に動きます。 つまり、 const btn = document.querySelector('.calendar-table td'); を通った時には要素は存在しない状態です。
kii.32

2021/10/03 05:08

ありがとうございます。読み込み後なのですね。 読み込み後にbtn.addEventListenerを利用できればと思い、 onloadの中に下記の様に追記をしてみました。 エラーは消えたのですが、クラスの付与がされませんでした。 どこかコードが間違っておりますでしょうか。 window.onload = function () { // 現在の年月の取得 var current = new Date(); var year = current.getFullYear(); var month = current.getMonth() + 1; // カレンダーの表示 var wrapper = document.getElementById('calendar'); add_calendar(wrapper, year, month); // こちらを追加 const btn = document.querySelector('.calendar-table td'); btn.addEventListener('click', (e) => { e.target.classList.toggle('active'); }); }
m.ts10806

2021/10/03 05:17

querySelectorで取得される要素は1つだけだからだと思います。 tdは複数あるものですし、Allで取得してループしそれぞれにイベント付与する必要があるのではと。
m.ts10806

2021/10/03 05:20

ただ、現在のコードでもエラー出てませんか? btn is not defined add_calendar内のbtn変数がどこにも定義されず使われてます。
kii.32

2021/10/03 09:16

すみません。エラー出ておりました。 onloadを外し、下記に変更することで、解決いたしました。 本文のコードにも編集をしております。 $(function () { $(".calendar-table td").on("click", function () { $(".calendar-table td").removeClass("active"); $(this).addClass("active"); }); }); この度は、ご回答いただきましてありがとうございました。 おかげで解決することができました。感謝いたします。
m.ts10806

2021/10/03 09:37

onload外す必要ないような。 それに、動的に作る要素ならdocumentから見た方が良いです。 $(document).on("click",".calendar-table td", function () { ※ただjQueryの記法とそうでない記法が混ざるのは可読性の面であまりよくないのでご注意を。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問