[JavaScript] 產生月曆
這是 JavaScript 的一個作業的一部份,我把他拆成三個部份寫。這是最後一部份,在確定是合理存在的日期後,產生當月的月曆,如下:
顯然這個問題不是只有顯示該月的天數而已,為了讓月曆好看,可能要補足上個月與下個月的部份,這才是這個問題要處理的重點。以上圖來說,2014 年 7 月有 31 天,不只要把星期二的 7 月 1 日到星期四的 7 月 31 日做出來,還要把前後的 6 月 29 日、6 月 30 日、8 月 1 日、8 月 2 日補上,這才是我們常見的月曆。
需判斷的東西
主體是這個月,所以當月共有幾天要先知道,這在上一篇 [JavaScript] 得到某年某月的天數 做出來了,想法是 Date 物件 Month 多 1,Date 取 0 退一天。
第二為了知道需不需要補足上個月的最後幾天,要知道當月第一天是星期幾,這利用 Date 物件的 getDay() 方法(星期日回傳0,星期一回傳1,....星期六回傳6)。
第三,若上個月最後幾天也要做出來,表示上個月共有幾天也要求得,這利用 Date 物件取當月,然後日期用 0 可得上個月最後一天物件。
第四為了知道是否要補齊下個月的頭幾天,就要求出當月最後一天是星期幾,前上一篇有求出當月最後一天的 Date 物件,再 .getDay() 回傳即可。
然後目標是將日期用 Array 依序列出,日期小於 1 的是上個月(例如下圖的 - 1、0),大於當月總天數的是下個月(例如下圖的 32、33)。
如上圖 2014 年 7 月的月曆,就是要產生一個陣列 days = [ -1, 0, 1, 2, 3, ... , 31, 32, 33 ]
function generateCalender(inputYear, inputMonth, inputDate) { let domCalendar = document.getElementById('tableCalendar'); if (domCalendar) { // 若已產生過日曆就刪掉他,不然會一直累加 domCalendar.remove(); } let days = []; let startDate = new Date(inputYear, inputMonth, 1); // 當月第一天的 date object let endDate = new Date(inputYear, inputMonth + 1, 0); // 當月最後一天的 date object let startDay = startDate.getDay(); // 當月第一天是禮拜幾 let endDay = endDate.getDay(); // 當月最後一天是禮拜幾 let lastMonthDate = new Date(inputYear, inputMonth, 0).getDate(); // 上個月總天數 let thisMonthDate = endDate.getDate(); // 當月總天數 for (let i = 0; i < startDay; i++) { // 若當月第一天不是禮拜日,補齊上個月的天數 days.push(- startDay + 1 + i); } for (let i = 1; i <= thisMonthDate; i++) { // 當月的所有天數 days.push(i); } for (let i = 1; i < 7 - endDay; i++) { // 若當月最後一天不是禮拜六,補齊下個月的天數 days.push(thisMonthDate + i); } let nodeTable = document.createElement('table'); nodeTable.setAttribute('id', 'tableCalendar'); for (let i = 0; i < days.length; i += 7) { let weekRow = nodeTable.insertRow(); // 開始一個 tr for (let j = 0; j < 7; j++) { let thisDate = days[i + j]; let weekCell = weekRow.insertCell(); // 即 td if (thisDate < 1) { // days 存的若是負數表示上個月的日期 weekCell.textContent = thisDate; weekCell.className = 'notThisMonth'; } else if (thisDate > thisMonthDate) { // 下個月的日期 weekCell.textContent = thisDate; weekCell.className = 'notThisMonth'; } else if (thisDate == inputDate) { // select 選的當日,就用專屬的 class weekCell.textContent = thisDate; weekCell.className = 'todayCell'; } else { // 這個月其它天數 weekCell.textContent = thisDate; } } } let thead = nodeTable.createTHead(); // thead 若在前面加,不知道為何 class 會有問題 let theadRow = thead.insertRow(); let strThead = ['日', '一', '二', '三', '四', '五', '六']; for (let str of strThead) { let th = theadRow.insertCell(); th.textContent = str; } document.getElementById('divCalendar').appendChild(nodeTable); }
留言
張貼留言