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

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

詳細はこちら
JavaScript

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

HTML

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

Q&A

解決済

3回答

1394閲覧

Javascriptを使ってカレンダーアプリを作る

Tlexxxxxx

総合スコア15

JavaScript

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

HTML

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

0グッド

0クリップ

投稿2020/12/29 08:35

編集2020/12/29 08:48

前提

Javascriptの基本を学んだので、何か作ってみたいと思い、
現在J簡単なカレンダーアプリを作っています!
今月分のカレンダーは表示することができました!

イメージ説明
こんな感じに↑

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

そして次は、ボタンを押すことで「先月」「来月」のカレンダーも表示させたいと思っています。
コードを書いてみたのですが、ボタンを押しても反応がなく(画面が変わらない)、エラーも出ないのでどこがおかしいのか、分からず、悩んでいます。

該当のソースコード

HTML

1 <section class="month"> 2 <div class="month__items"> 3  4   <!-- 先月ボタン --> 5 <span class="month__item monthPrev"> 6 <i id="prev" class="fas fa-chevron-left"></i> 7 </span><!-- /.month__item monthPrev --> 8 9 <h2 id="month" class="month__item monthNow"> 10 </h2><!-- /.month__item monthNow --> 11 12   <!-- 来月ボタン --> 13 <span class="month__item monthNext"> 14 <i id="next" class="fas fa-chevron-right"></i> 15 </span><!-- /.month__item monthNext--> 16 17 </div><!-- /.month__items --> 18 </section><!-- /.month --> 19 20 <!-- カレンダー表示 --> 21 <section class="calendar"> 22 <table class="table"> 23 </table><!-- /. table --> 24 </section><!-- /.calendar -->

JS

1'use strict'; 2 3const today = new Date(); 4const currentYear = today.getFullYear(); 5const currentMonth = today.getMonth(); 6const weeks = [ 7 'Sun', 8 'Mon', 9 'Tue', 10 'Wed', 11 'Thu', 12 'Fri', 13 'Sat' 14]; 15const months = [ 16 'January', 17 'February', 18 'March', 19 'April', 20 'May', 21 'June', 22 'July', 23 'August', 24 'September', 25 'October', 26 'November', 27 'December', 28]; 29let dayCount = 1 // 日にちのカウント 30let calendarHtml = '' // HTMLを組み立てる変数 31 32 33const showCalendar = () => { 34 35 //月初めの日付を取得 36 const startDate = new Date(currentYear, currentMonth, 1) 37 const startDay = startDate.getDay() 38 39 //月末の日付を取得 40 const endDate = new Date(currentYear, currentMonth - 1, 0) 41 const endDay = endDate.getDate() 42 43 //前月の日付を取得 44 const lastMonthEndDate = new Date(currentYear, currentMonth, 0) 45 const lastMonthEndDay = lastMonthEndDate.getDate() 46 47 48 //現在の月を表示 49 const month = document.getElementById('month'); 50 month.innerHTML = months[currentMonth]; 51 52 53 // 曜日の行を作成 54 calendarHtml += '<table>' 55 calendarHtml += '<thead>' 56 calendarHtml += '<tr class="tbody__weeks">' 57 for (let i = 0; i < weeks.length; i++) { 58 calendarHtml += '<th class="tbody__week">' + weeks[i] + '</th>' 59 } 60 calendarHtml += '</tr>' 61 calendarHtml += '</thead>' 62 63 64 //日にちを作成 65 calendarHtml += '<tbody class="tbody">' 66 for (let w = 0; w < 6; w++) { 67 calendarHtml += '<tr class="tbody__days">' 68 69 for (let d = 0; d < 7; d++) { 70 if (w == 0 && d < startDay) { 71 let num = lastMonthEndDay - startDay + d + 1 72 calendarHtml += '<td class="tbody__day -next">' + num + '</td>' 73 74 } else if (dayCount > endDay) { 75 let num = dayCount - endDay 76 calendarHtml += '<td class="tbody__day -next">' + num + '</td>' 77 dayCount++ 78 79 } else { 80 calendarHtml += '<td class="tbody__day">' + dayCount + '</td>' 81 dayCount++ 82 } 83 } 84 calendarHtml += '</tr>' 85 } 86 calendarHtml += '</tbody>'; 87 calendarHtml += '</table>'; 88 89 const calendar = document.querySelector('.calendar') 90 calendar.innerHTML = calendarHtml; 91}; 92 93 94//先月を表示 95const prev = document.querySelector('.monthPrev i'); 96prev.addEventListener('click', () => { 97 today.setMonth(currentMonth - 1); 98 showCalendar(); 99}); 100 101//来月を表示 102const next = document.querySelector('.monthNext i'); 103next.addEventListener('click', () => { 104 today.setMonth(currentMonth + 1); 105 showCalendar(); 106}); 107 108showCalendar(); 109

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

どういった考え方をすればよいのか教えていただきたいです。
よろしくお願いいたします

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

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

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

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

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

fumu7

2020/12/29 08:40

「うまくいかず」という説明だけでは何が起きているのか想像できません。 もっと具体的に説明してください。
Tlexxxxxx

2020/12/29 08:45

ご指摘ありがとうございます。修正いたしました。
tanat

2020/12/29 09:48

現在のソースについては理解できていますか?
Tlexxxxxx

2020/12/29 10:08

できています。
guest

回答3

0

ベストアンサー

1.関数 showCalendar の中に以下の変数を内部で定義します
currentYear, currentMonth, dayCount, calendarHtml
初期化も忘れずに。
2.関数 showCalendar の呼び出す際の引数に DateObject を渡すようにしましょう
3.テーブル要素には caption があります。その部分に<div class="month__items">の中を移しましょう
4.innerHTML を使わずに dom で挑戦しましょう

なんとなく書いてみました。

js

1<!DOCTYPE html> 2<meta charset="utf-8"> 3<title></title> 4<style> 5table { 6 margin: 1em 0; 7} 8thead td { 9 font-weight: bold; 10} 11thead td, tbody td { 12 text-align: center; 13 border: 1px transparent solid; 14} 15tbody td:hover:not(.pDay):not(.nDay) { 16 border: 1px #f80 solid; 17} 18tr td:first-of-type { 19 color: red; 20} 21tr td:last-of-type { 22 color:#099; 23} 24thead td { padding: 0 .5ex;} 25caption label { 26 padding: 0 .5ex; 27 font-size: large; 28 font-weight: bold; 29} 30caption button { 31 background: transparent; 32 border-style: none; 33 font-size: large; 34 padding: 0; 35} 36caption .hide { 37 display: none; 38} 39tbody td.pDay, tbody td.nDay { 40 color: silver; 41 font-size: small; 42 vertical-align: top; 43} 44tbody td.nDay { 45 color: silver; 46 font-size: small; 47 vertical-align: bottom; 48} 49</style> 50 51<body> 52<table></table> 53<table></table> 54<table></table> 55 56<script> 57 58class Calendar { 59 60 constructor (table, date, option = { }) { 61 this.table = table; 62 this.date = date; 63 this.option = Object.assign ({ }, this.constructor.defaultOption (), option); 64 this.view (); 65 } 66 67 68 view () { 69 const 70 {table, option, constructor: c } = this, 71 {remove, getYMD, setNo, splice, toTBody, append} = c.tools (); 72 73 let 74 tbody = document.createElement ('tbody'), 75 [y, m] = getYMD (this.current),//日付 76 [,, pd, pw] = getYMD (new Date (y, m, 0)),//先月末日 77 [,, nd, nw] = getYMD (new Date (y, m + 1, 0)),//今月末日 78 pn = (pw + 1) % 7,//先月の繰越す日数 79 nn = 6 - nw,//来月の取入れ日数 80 days = [ 81 ...setNo (pn, pd - pn + 1),//連番(先月末) 82 ...setNo (nd),//連番(今月) 83 ...setNo (nn)//連番(翌月) 84 ]; 85 86 remove (table.children);//子要素を削除 87 append (table.createCaption (), option.caption);//キャプションをDOMで展開 88 toTBody (table.createTHead (), option.weekName);//週名を展開 89 toTBody (table.appendChild (tbody), [...splice (days, 7)]);//7日で区切る 90 91 [...table.querySelectorAll ('caption label')] 92 .forEach ((e, i)=> e.textContent = [y, option.monthName[m]][i]); 93 94 let es = [...table.querySelectorAll ('tbody td')]; 95 if (pn) es.slice (0, pn).forEach (e=> e.classList.add ('pDay')); 96 if (nn) es.slice (-nn).forEach (e=> e.classList.add ('nDay')); 97 98 return this; 99 } 100 101 102 offsetMonth (n = 0) { 103 this.current.setMonth (this.current.getMonth () + n); 104 this.view (); 105 return this; 106 } 107 108 109 set date (dt) { 110 const {getYMD} = this.constructor.tools (); 111 let [y, m] = getYMD (dt); 112 this.current = new Date (y, m, 1); 113 this._date = dt; 114 } 115 116 117 getDate (td) { 118 const {zp, getYMD} = this.constructor.tools (); 119 let 120 [y, m, _, w] = getYMD (this.current), 121 d = Number (td.textContent), 122 ymd = [y, m+1, d], 123 str = ymd.map ((a,b)=>zp(a,[4,2,2][b])).join ('-'); 124 return [new Date (y, m, d), str, ...ymd, w]; 125 } 126 127 128 event (td) { 129 if (td) { 130 let 131 cbFunc = this.option.cbFunc, 132 args = this.getDate (td); 133 if ('function' === typeof cbFunc) 134 cbFunc.apply (this, args); 135 if (this.option.clipboard) 136 navigator.clipboard.writeText (args[1]).then(()=> console.log (args)); 137 } 138 } 139 140 141 handleEvent (event) { 142 let 143 e = event.target, 144 c = e.closest ('caption'), 145 n = e.nodeName; 146 147 if ('BUTTON' === n && c) { 148 let btNo = [...c.querySelectorAll('button')].indexOf (e); 149 return this.offsetMonth ([-12, -1, 1, 12][btNo]); 150 } 151 else if ('TD' === n && e.closest ('tbody')) 152 this.event (e); 153 } 154 155 156 static tools () { 157 return { 158 zp: (a,b=2)=>String(a).padStart(b,'0'), 159 remove: a=>[...a].map(a=>a.remove()), 160 getYMD: a=>['FullYear','Month','Date','Day'].map(b=>a['get'+b]()), 161 setNo: function*(a,b=1,c=1,d=0){for(;d<a;d+=c)yield b+d}, 162 splice: function*(a,b=1){while(a.length)yield a.splice(0,b)}, 163 append: ((f=(a,b,c,{tag:T,child:C,...O}=b)=>Array.isArray(b)?b.reduce((a,b)=>f(a,b),a):(Object.assign(a.appendChild(c=document.createElement(T)),O),C&&f(c,C),a))=>f)(), 164 toTBody: (a,ary)=>{ 165 const 166 reg = /^(#?)(?:[(\d+)?(?:\,(\d+)?)?])?\s*(?:(.+)\s)*\s*(?:([+-]?(?:[1-9][0-9]{0,2}(?:\,?[0-9]{3})*)?(?:0?(?:.\d*))?)|(.+))?$/, 167 setAttr = (a,b,O=Object)=>O.assign(a,O.fromEntries(O.entries(b).filter(c=>'undefined'!==typeof c[1]))); 168 169 for (let row of ary) { 170 let tr = a.insertRow (); 171 for (let cell of row) { 172 let 173 [,thd, colSpan, rowSpan, className, num, text] = reg.exec (cell), 174 td = tr.appendChild (document.createElement (thd ? 'th': 'td')), 175 attr = {colSpan, rowSpan, className, textContent: text || num || ''}; 176 setAttr (td, attr); 177 tr.appendChild (td); 178 } 179 } 180 } 181 }; 182 } 183 184 185 static defaultOption () { 186 return { 187 weekName: [['Sun','Mon','Tue','Wed','Thu','Fri','Sat']], 188 monthName: ['January','February','March','April','May','June','July','August','September','October','November','December'], 189 caption: [ 190 { tag: 'button', type: 'button', textContent: '⏪', className: 'hide' }, 191 { tag: 'button', type: 'button', textContent: '<' }, 192 { tag: 'label', className: 'hide' }, 193 { tag: 'label'}, 194 { tag: 'button', type: 'button', textContent: '>'}, 195 { tag: 'button', type: 'button', textContent: '⏩', className: 'hide' } 196 ], 197 cbFunc: null, 198 clipboard: true, 199 }; 200 } 201 202 203 static create (table = document.createElement ('table'), date = new Date, option = { }) { 204 const calendar = new this (table, date, option); 205 table.addEventListener ('click', calendar, false); 206 return calendar; 207 } 208} 209 210 211const 212 TABLE = document.querySelectorAll ('table'), 213 [a, b, c] = Array.from (TABLE, t=> Calendar.create (t)); 214 215b.offsetMonth (+1); 216c.offsetMonth (+2); 217 218</script>

投稿2020/12/29 10:18

編集2021/01/02 02:52
babu_babu_baboo

総合スコア616

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

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

Tlexxxxxx

2020/12/29 10:20

丁寧にありがとうございます! 今からやってみます。
guest

0

面倒であればdatepickerとか使うと楽ですね

HTML

1<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 2<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" /> 3<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> 4<script> 5$(function() { 6 $("#datepicker").datepicker(); 7}); 8</script> 9<div id="datepicker"/></div>

投稿2020/12/29 09:05

yambejp

総合スコア116661

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

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

Tlexxxxxx

2020/12/29 09:11

ありがとうございます! しかし、今回は勉強のため自分で書いてみます!
guest

0

currentYear currentMonth が更新されていないからでは?
(その他もろもろ初期化していないので確認してみましょう)

投稿2020/12/29 08:40

kei344

総合スコア69596

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

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

Tlexxxxxx

2020/12/29 09:18

まだJavascriptについての知識が乏しく、更新のやり方、もしくは考え方を教えていただけないでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問