ガントチャートとして使えるようにするためにカレンダーをポップアップ表示させる方法を考えます。
Contents
カレンダーを表示させる
まず普通にカレンダーを表示させます。そのためのクラスを作成します。
コンストラクタではカレンダーが何年何月を表示しているのかを示す部分とカレンダー本体を表示する要素を引数として受け取ります。
HTMLで以下のようにすればカレンダーが表示されるようにしたいのです。
index.html
1 2 3 4 5 6 7 8 9 10 11 12 |
<body> <h1 id="calendar-header"></h1> <div id="calendar"></div> <script> let calendarHeader = document.getElementById('calendar-header'); let calendar = document.getElementById('calendar'); let popupCalendar = new Calendar(calendarHeader, calendar); let showDate = new Date(today.getFullYear(), today.getMonth(), 1); popupCalendar.ShowCalendar(showDate); </script> </body> |
カレンダーの初期化
Calendarクラスのコンストラクタを示します。
mini-calendar.js
1 2 3 4 5 6 7 8 |
class Calendar{ constructor(elementHeader, elementCalendar){ this.ElementHeader = elementHeader; this.ElementCalendar = elementCalendar; this.week = ["日", "月", "火", "水", "木", "金", "土"]; } } |
カレンダーの生成と表示
ShowCalendar関数が実行されたらヘッダー部分に何年何月かを表示してカレンダー本体を表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Calendar{ ShowCalendar(date) { let year = date.getFullYear(); let month = date.getMonth(); this.ElementHeader.innerHTML = year + "年 " + (month + 1) + "月"; this.ElementHeader.style.textAlign = 'center'; this.ElementHeader.style.fontSize = '24px'; this.ElementHeader.style.width = '100%'; this.ElementHeader.style.margin = '1rem 0 0'; this.CreateCalendar(year, month); // 後述 } } |
CreateCalendar関数はカレンダー本体をつくりこれを表示します。ただ同じオブジェクトでCreateCalendar関数が実行されると前に表示されていたカレンダーが消されずにその下にカレンダーが表示されてしまうので、前のカレンダーが存在するときは消去してから処理を行ないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
class Calendar{ CreateCalendar(year, month) { // 古いカレンダーがあるかもしれない const old = document.getElementById('calendar-inner'); if(old != null) old.remove(); // tableタグを追加。さらに曜日表示部分と日付表示部分を追加する。 let tableElement = document.createElement('table'); tableElement.setAttribute('id','calendar-inner'); tableElement.style.outline = '1px solid #000000'; tableElement.style.borderCollapse = 'collapse'; tableElement.style.width = '100%'; this.ElementCalendar.appendChild(tableElement); // 曜日表示部分を追加する。 let trElement0 = document.createElement('tr'); tableElement.appendChild(trElement0); for (var i = 0; i < this.week.length; i++) { let thElement = document.createElement('th'); thElement.innerHTML = this.week[i]; thElement.style.paddingTop = '10px'; thElement.style.paddingBottom = '10px'; thElement.style.textAlign = 'center'; thElement.style.fontWeight = 'bold'; trElement0.appendChild(thElement); } // 日付表示部分を追加する。 let count = 0; // その月の最初の日と最後の日を取得する let startDayOfWeek = new Date(year, month, 1).getDay(); let endDate = new Date(year, month + 1, 0).getDate(); // 最後の日 let lastMonthEndDate = new Date(year, month, 0).getDate(); // カレンダーは何行? let row = Math.ceil((startDayOfWeek + endDate) / this.week.length); for (var i = 0; i < row; i++) { let trElement = document.createElement('tr'); tableElement.appendChild(trElement); for (var j = 0; j < this.week.length; j++) { let tdElement = document.createElement('td'); tdElement.style.paddingTop = '10px'; tdElement.style.paddingBottom = '10px'; tdElement.style.textAlign = 'center'; tdElement.style.fontWeight = 'bold'; trElement.appendChild(tdElement); if (i == 0 && j < startDayOfWeek) { // その月の最初の日よりも前の部分は灰色で表示する tdElement.innerHTML=(lastMonthEndDate - startDayOfWeek + j + 1); tdElement.style.color = '#ccc'; } else if (count >= endDate) { // その月の最後の日よりも後の部分は灰色で表示する count++; tdElement.innerHTML=(count - endDate); tdElement.style.color = '#ccc'; } else { count++; tdElement.innerHTML = count; // 日付部分がクリックされたときにどの部分なのかわかるように // data-date = "2021-01-01" のようなタグを入れる tdElement.dataset.date = this.GetDateText(year, month, count); // class = "date"も追加 tdElement.setAttribute('class','date'); // 本日部分は背景色をかえて表示 // それ以外は白地に黒。ただし土日は色を変える if(year == today.getFullYear() && month == (today.getMonth()) && count == today.getDate()){ tdElement.style.color = '#ffffff'; tdElement.style.backgroundColor = '#D66070'; tdElement.style.fontWeight = 'bold'; } else { if(j==0) tdElement.style.color = '#ff0000'; // 日曜日 if(j==6) tdElement.style.color = '#0000ff'; // 土曜日 } // クリック可能であることを示すためにカーソルを変える tdElement.style.cursor = 'pointer'; } } } } GetDateText(year, month, count){ return `${year}-${this.ZeroPadding(month+1, 2)}-${this.ZeroPadding(count, 2)}` } ZeroPadding(num,length){ return ('0000000000' + num).slice(-length); } } |
カレンダーをポップアップ表示させる
カレンダーをポップアップ表示させるには非表示の状態で作成しておき、表示させるときに表示状態にします。表示させるボタンを押されたら表示し、×や日付をクリックしたらカレンダーを非表示にします。
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<body> <div id="popup-calendar"> <div id="close-btn">×</div> <div id="next-prev-button"> <button id="prev" onclick="Prev()">前月</button> <button id="next" onclick="Next()">次月</button> </div> <h1 id="calendar-header"></h1> <div id="calendar"></div> </div> <script> let popupCalendar = null; let popupCalElement = document.getElementById('popup-calendar'); const today = new Date(); let showDate = new Date(today.getFullYear(), today.getMonth(), 1); let curDateElement = null; InitPopupCalendar(); // 後述 </script> </body> |
ポップアップカレンダーの初期化
ポップアップカレンダーを初期化するための処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
function InitPopupCalendar(){ // 常に同じ位置に表示されるようにposition = 'fixed'を設定する popupCalElement.style.position = 'fixed'; popupCalElement.style.top = '0px'; popupCalElement.style.visibility = 'hidden'; // 最初は非表示 popupCalElement.style.width = '280px'; // 幅は280pxとする // 「前月」「次月」ボタンのスタイルを設定する let prevElement = document.getElementById('prev'); let nextElement = document.getElementById('next'); prevElement.style.float = 'left'; nextElement.style.float = 'right'; InitPrevNextBotton(prevElement); InitPrevNextBotton(nextElement); SettingClosebtn(); // ×がクリックされたときの動作を定義 SettingClickDay(); // 日付をクリックされたときの動作を定義 // Calendarクラスのインスタンスをつくる let calendarHeader = document.getElementById('calendar-header'); let calendar = document.getElementById('calendar'); popupCalendar = new Calendar(calendarHeader, calendar); } // 「前月」「次月」ボタンのスタイルを設定する function InitPrevNextBotton(element){ element.style.cursor = 'pointer'; element.style.background = '#B78D4A'; element.style.color = '#ffffff'; element.style.border = '1px solid #B78D4A'; element.style.borderRadius = '4px'; element.style.padding = '0.5rem 1rem'; element.style.margin = '1rem 0'; element.style.fontSize = '1rem'; } |
クリックされたときの動作の定義
×がクリックされたときの動作を定義します。
1 2 3 4 5 6 7 |
function SettingClosebtn(){ let closebtn = document.getElementById('close-btn'); closebtn.style.cursor = 'pointer'; closebtn.addEventListener('click', function(e){ HideCalendar(); }); } |
ポップアップカレンダーを非表示にします。
1 2 3 4 |
function HideCalendar(){ popupCalElement.style.visibility = 'hidden'; curDateElement = null; } |
日付をクリックされたときの動作を定義します。
1 2 3 4 5 6 7 8 |
function SettingClickDay(){ popupCalElement.addEventListener('click', function(e){ if(e.target.classList.contains("date")){ // e.target.dataset.dateを調べれば 「2021-01-01」のような形で取得できる HideCalendar(); } }); } |
カレンダーの「前月」「次月」がクリックされたときにカレンダーを切り替えます。
1 2 3 4 5 6 7 8 9 |
function Prev(){ showDate.setMonth(showDate.getMonth() - 1); popupCalendar.ShowCalendar(showDate); } function Next(){ showDate.setMonth(showDate.getMonth() + 1); popupCalendar.ShowCalendar(showDate); } |
カレンダーを実際に表示させる
カレンダーを表示させます。
1 2 3 4 5 6 7 8 9 |
let curDateElement = null; // あとで必要になる function ShowPopupCalendar(dateElement){ popupCalElement.style.visibility = 'visible'; popupCalElement.style.backgroundColor = '#ffffff'; showDate = new Date(today.getFullYear(), today.getMonth(), 1); popupCalendar.ShowCalendar(showDate); curDateElement = dateElement; } |
日付部分がクリックされたら相当する文字列を取得する
これで日付部分がクリックされたらその日にちに相当する文字列を取得できるようになります。以下のようなHTMLがあれば「クリック」と書かれている部分をクリックするとポップアップカレンダーが表示され、日を選択するとその部分が「クリック」という文字と置き換わります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>カレンダーをポップアップを表示する</title> <meta name="viewport" content="width=device-width,initial-scale=1"> </head> <body> <div id="popup-calendar"> <div id="close-btn">?</div> <div id="next-prev-button"> <button id="prev" onclick="Prev()">前月</button> <button id="next" onclick="Next()">次月</button> </div> <h1 id="calendar-header"></h1> <div id="calendar"></div> </div> <div id ="a">クリック</div> <div id ="b">クリック</div> <script type='text/javascript' src='./mini-calendar.js'></script> // Calendarクラスの定義 <script> // 上記のコード // さらに続けて・・・ let a = document.getElementById('a'); let b = document.getElementById('b'); a.addEventListener('click', function(e){ if(curDateElement== null) ShowPopupCalendar(a); }); b.addEventListener('click', function(e){ if(curDateElement== null) ShowPopupCalendar(b); }); // SettingClickDay関数は書き換える function SettingClickDay(){ popupCalElement.addEventListener('click', function(e){ if(e.target.classList.contains("date")){ curDateElement.innerHTML = e.target.dataset.date; HideCalendar(); } }); } </script> </body> </html> |