Part 6-1 JavaScript – 月曆上下月顯示
填滿月曆表格目前是寫在js/updateData.js中的updataData函式,在該函式中,我們取得今年今月今日的資訊填入calendar物件中,然後再根據calendar物件的日期相關資料填滿月曆表格,接著,我們要滑鼠點選月曆月份左右二個箭頭按鈕,更新月曆表格,為些,我們要把填月曆表格的程式片段包裝成一個函式fillInMonth(),以便於我們呼叫這個函式來顯示今月、上月(上上月…)、下月(下下月…)的月曆表格,以下的程式,大家可以看到,把updateData函式一分為二:updateDate與fillInMonth二個函式:
二個事件處理函式皆加上fillInMonth函式的呼叫:
function updateData(){
let today = new Date();
calendarData.currentDate.year = today.getFullYear();
calendarData.currentDate.month = today.getMonth() + 1;
calendarData.currentDate.day = today.getDay();
calendarData.currentDate.date =today.getDate();
calendarData.calendar.month = calendarData.currentDate.month;
calendarData.calendar.year = today.getFullYear();
document.getElementById("cur-year").innerHTML = calendarData.currentDate.year;
document.getElementById("cur-day").innerHTML = getWeekDayName( calendarData.currentDate.day );
document.getElementById("cur-month").innerHTML = getMonthName ( calendarData.currentDate.month );
document.getElementById("cur-date").innerHTML = addOrdinalIndicator ( calendarData.currentDate.date );
fillInMonth();
}
function fillInMonth(){
document.getElementById("cal-year").innerHTML = calendarData.calendar.year;
document.getElementById("cal-month").innerHTML = getMonthName ( calendarData.calendar.month );
var monthDays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 32]; //第一個元素放個啞巴元素,好讓我們可以用1~12來存取月份的天數
//判斷今年是否是閏年
if ( ((calendarData.calendar.year % 4 == 0) && (calendarData.calendar.year % 100 != 0)) || (calendarData.calendar.year % 400 == 0) ) monthDays[2] = 29;
var weekDay = (new Date(calendarData.calendar.year, calendarData.calendar.month,1)).getDay() ; //取得今年今月1日為禮拜幾
console.log(weekDay);
var days = document.getElementsByTagName("td");
//中間段,當月
for (var i = 1; i <= monthDays[calendarData.calendar.month]; i++){
days[weekDay + i - 1].innerHTML = i;
}
//上個月段
for (var i = (weekDay-1), day = monthDays[calendarData.calendar.month-1]; i >=0; i--, day--){
days[i].innerHTML = day;
days[i].classList.add("color");
}
//下個月段
for (var i = (weekDay+monthDays[calendarData.calendar.month]), day = 1; i <days.length; i++, day++){
days[i].innerHTML = day;
days[i].classList.add("color");``
}
//處理今日元素表格的顯著背景設定
if (document.getElementById("current-day")) {
document.getElementById("current-day").removeAttribute("id");
}
days[weekDay + calendarData.currentDate.date - 1].setAttribute("id", "current-day");
}
先寫下previousMonth與nextMonth二個函式:
function previousMonth(){
console.log("Prev...");
}
function nextMonth(){
console.log("Next...");
}
函式只輸出prev或Next,用來測試動作是否有反應。
接著,在二個箭頭按鈕的標籤加上onClick事件處理,指定當滑鼠在其上按了左鍵或右鍵對應的事件處理函式。
<tr>
<th colspan="7" class="border-color">
<h4 id="cal-year">2019</h4>
<div >
<i class="fas fa-caret-left icon" onclick="previousMonth()"></i>
<h3 id="cal-month">January</h3>
<i class="fas fa-caret-right icon" onclick="nextMonth()"></i>
</div>
</th>
</tr>
存檔,測試,按F12,打開console,按左右二個箭頭按鍵,檢查console是否有列印出prev和next…
二個事件處理函式皆加上fillInMonth函式的呼叫:
function previousMonth(){
console.log("Prev...");
calendarData.calendar.month--;
fillInMonth();
}
function nextMonth(){
console.log("Next...");
calendarData.calendar.month++;
fillInMonth();
}
存檔測試,有幾個問題浮出來了:
1.月曆表格元素的顏色顯示不正常,當月的日期元素是白色,操作幾次之後,會發現,當月的日期元素混到顏色了…,這個問題很容易解決,我們在填表之前,先把有設定color屬性的元素去除掉color屬性設定:
for (var i = 0; i <= 41; i++){
if (days[i].classList.contains("color")) days[i].classList.remove("color");
}
2.進行月份加加減減時,會超出月份的值域,也就是會小於等於0,大於12,此時,我們要加上判斷,
當值等於0時,月份設為12,然後年份減1,當值大於12時,月份設為1,然後年份加1。
程式如下:function previousMonth(){
console.log("Prev...");
calendarData.calendar.month--;
if (calendarData.calendar.month == 0) {
calendarData.calendar.month = 12;
calendarData.calendar.year--;
}
fillInMonth();
}
function nextMonth(){
console.log("Next...");
calendarData.calendar.month++;
if (calendarData.calendar.month >12) {
calendarData.calendar.month = 1;
calendarData.calendar.year++;
}
fillInMonth();
}
註:date大約可從1970年往前往後285,616年,這個App應該沒人一直按左鍵2000下,使得年變負的,如果真有人要一直按一直按…,如何不要讓year變成負的?
用滑鼠按左右箭頭雖然方便,但效率不好(箭頭會隨著月份名稱長度位置會有改變,眼睛要盯著箭頭,滑鼠要跟上…),另一個方式就是按滑鼠的左右鍵!我們可以透過補捉鍵盤事件,利用鍵盤的左右鍵來觸發previousMonth與nextMonth二個函式。
取得 JavaScript KeyCode
document.onkeydown = function(e) {
switch (e.keyCode) {
case 37: previousMonth(); break;
case 39: nextMonth(); break;
}
};
另外,我們在填日期時,會將今日的表格元素進行顯著設定,但是隨著上下月的更新月曆,也都會對今日(但不是今月)元素表格進行顯著設定,此時,我們加上一個判斷式,只要左右二邊的月份不一樣,我們就不做顯著設定,程式碼如下:
if (calendarData.currentDate.year == calendarData.calendar.year && calendarData.currentDate.month == calendarData.calendar.month) {
days[weekDay + calendarData.currentDate.date - 1].setAttribute("id", "current-day");
}
等等,還有一個問題,當今月是1月的時候,若用今月的值減1取到的上個月值會是0,在我們的月份日數陣列裏頭,第0個元素是啞巴元素,一月的上個月應該是12,我們必須再處理這個狀況。
preMonth = calendarData.calendar.month-1;
if (preMonth == 0) preMonth = 12;
for (let i = (weekDay-1), day = monthDays[preMonth]; i >=0; i--, day--){
days[i].innerHTML = day;
days[i].classList.add("color");
}
var calendarData = {
currentDate : {
day : "",
date : "",
month : "",
year : "",
},
calendar:{
month : "",
year : ""
}
};
function getWeekDayName(day){
var weekDayNames = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
return weekDayNames[day];
}
function getMonthName(month){
var monthNames = ["","January","February","March","April","May","June","July","August","September","October","November","December"];
return monthNames[month];
}
function addOrdinalIndicator(date){
switch(date){
case 1:
case 21:
case 31: return date + "<sup>st</sup>";
case 2:
case 22: return date + "<sup>nd</sup>";
case 3:
case 23: return date + "<sup>rd</sup>";
default: return date + "<sup>th</sup>";
}
}
function updateData(){
let today = new Date();
calendarData.currentDate.year = today.getFullYear();
calendarData.currentDate.month = today.getMonth() + 1;
calendarData.currentDate.day = today.getDay();
calendarData.currentDate.date =today.getDate();
calendarData.calendar.month = calendarData.currentDate.month;
calendarData.calendar.year = today.getFullYear();
document.getElementById("cur-year").innerHTML = calendarData.currentDate.year;
document.getElementById("cur-day").innerHTML = getWeekDayName( calendarData.currentDate.day );
document.getElementById("cur-month").innerHTML = getMonthName ( calendarData.currentDate.month );
document.getElementById("cur-date").innerHTML = addOrdinalIndicator ( calendarData.currentDate.date );
fillInMonth();
}
function fillInMonth(){
var monthDays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; //第一個元素放個啞巴元素,好讓我們可以用1~12來存取月份的天數
document.getElementById("cal-year").innerHTML = calendarData.calendar.year;
document.getElementById("cal-month").innerHTML = getMonthName ( calendarData.calendar.month );
//判斷今年是否是閏
if ( ((calendarData.calendar.year% 4 == 0) && (calendarData.calendar.year % 100 != 0)) || (calendarData.calendar.year % 400 == 0) ) monthDays[2] = 29;
let weekDay = (new Date(calendarData.calendar.year, calendarData.calendar.month,1)).getDay() ; //取得今年今月1日為禮拜幾
console.log(weekDay);
let days = document.getElementsByTagName("td");
for (var i = 0; i <= 41; i++){
if (days[i].classList.contains("color")) days[i].classList.remove("color");
}
for (var i = 1; i <= monthDays[calendarData.calendar.month]; i++){
days[weekDay + i - 1].innerHTML = i;
}
prevMonth = calendarData.calendar.month - 1;
if (prevMonth == 0) prevMonth = 12;
for (var i = (weekDay - 1), day = monthDays[prevMonth]; i >= 0; i--, day--){
days[i].innerHTML = day;
days[i].classList.add("color");
}
for (var i = (weekDay + monthDays[calendarData.calendar.month]), day = 1; i <= 41; i++, day++){
days[i].innerHTML = day;
days[i].classList.add("color");
}
}
function previousMonth(){
console.log("Prev...");
calendarData.calendar.month--;
if( calendarData.calendar.month == 0) {
calendarData.calendar.year--;
calendarData.calendar.month = 12;
}
fillInMonth();
}
function nextMonth(){
console.log("Next...");
calendarData.calendar.month++;
if( calendarData.calendar.month == 13) {
calendarData.calendar.year++;
calendarData.calendar.month = 1;
}
fillInMonth();
}
document.onkeydown = function(e) {
switch (e.keyCode) {
case 37: previousMonth(); break;
case 39: nextMonth(); break;
}
};
最後,將新增的程式片段整理至js/updateData.js。
2019/04/23 日期上下月處理(尚有bugs,月份加加減減超過邊界值)
function convert2Weekday(day){
switch(day){
case 0: return "Sunday";
case 1: return "Monday";
case 2: return "Tuesday";
case 3: return "Wednesday";
case 4: return "Thursday";
case 5: return "Friday";
case 6: return "Saturday";
}
}
function conert2MonthName(month) {
switch(month){
case 0: return "January";
case 1: return "February";
case 2: return "March";
case 3: return "April";
case 4: return "May";
case 5: return "June";
case 6: return "July";
case 7: return "August";
case 8: return "September";
case 9: return "October";
case 10: return "November";
case 11: return "December";
}
}
function addOrdinalIndicator(date){
switch(date){
case 1:
case 21:
case 31: return date + "<sup>st</sup>";
case 2:
case 22: return date + "<sup>nd</sup>";
case 3:
case 23: return date + "<sup>rd</sup>";
default: return date + "<sup>th</sup>";
}
}
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth();
function updateDateData(){
document.getElementById("cur-year").innerHTML = date.getFullYear();
document.getElementById("cur-month").innerHTML = conert2MonthName(date.getMonth());
document.getElementById("cur-date").innerHTML = addOrdinalIndicator(date.getDate());
document.getElementById("cur-day").innerHTML = convert2Weekday(date.getDay()); //星期幾, 0~6
document.getElementById("cal-year").innerHTML = date.getFullYear();
document.getElementById("cal-month").innerHTML = conert2MonthName(date.getMonth());
fillInMonth(year, month);
}
function fillInNextMonth(){
console.log("year:" + year + " month" + month);
month++;
fillInMonth(year, month);
document.getElementById("cal-year").innerHTML = year;
document.getElementById("cal-month").innerHTML = conert2MonthName(month);
}
function fillInPreviousMonth(){
console.log("year:" + year + " month" + month);
month--;
fillInMonth(year, month);
document.getElementById("cal-year").innerHTML = year;
document.getElementById("cal-month").innerHTML = conert2MonthName(month);
}
function fillInMonth(year, month) {
let days = document.getElementsByTagName("td"); //將td標籤放入days物件集合中
date = new Date(year, month, 1);
weekDay = date.getDay(); //計算出今年今月1日是星期幾…
var monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; //每個月的天數
if ( ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0) ) monthDays[1] = 29; //閏年2月是29天
//填這個月的日期
for (var i=weekDay, j=1; j <= monthDays[month]; i++, j++){
days[i].innerHTML = j;
}
//填上個月的日期
for (var i = (weekDay-1), day = monthDays[month-1]; i >=0; i--, day--){
days[i].innerHTML = day;
days[i].classList.add("color"); //藍色背景
}
//填下個月的日期
for (var i = (weekDay+monthDays[month]), day = 1; i <days.length; i++, day++){
days[i].innerHTML = day;
days[i].classList.add("color"); //藍色背景
}
//處理今日元素表格的灰色背景設定
if (document.getElementById("current-day")) {
document.getElementById("current-day").removeAttribute("id");
}
date = new Date();
current_date = date.getDate(); //今天是幾號
days[weekDay + current_date - 1].setAttribute("id", "current-day");
}
document.onkeydown = function(e) {
switch (e.keyCode) {
case 37: fillInPreviousMonth(); break;
case 39: fillInNextMonth(); break;
}
};
20190423 課堂影音
