팀프로젝트 작업중 다른 부분들은 기존에 배운 js로 가능했지만 현재 날짜를 가져와 달력을 만드는 것은 배우지 않았다.
지금 바닐라스크립트로 작성중인 반응형 웹들도 대부분 플러그인으로 쉽게 사용하는 것으로 알고있지만, 단순 불러오는 것이 아닌 알고있는 코드와 메서드들로 달력을 만들어 보고 싶었다.
순수 자바스크립트로 달력을 만드는 것은 검색해 보아도 자료가 많지 않았다. (대부분 제이쿼리 혹은 플러그인)
그 중 한 블로그의 글을 보고 참조하여 만들어 보았다.
https://sirius7.tistory.com/35
<script>
window.onload = function () { buildCalendar(); } // 웹 페이지가 로드되면 buildCalendar 실행
let nowMonth = new Date(); // 현재 달을 페이지를 로드한 날의 달로 초기화
let today = new Date(); // 페이지를 로드한 날짜를 저장
today.setHours(0, 0, 0, 0); // 비교 편의를 위해 today의 시간을 초기화
// 달력 생성 : 해당 달에 맞춰 테이블을 만들고, 날짜를 채워 넣는다.
function buildCalendar() {
let firstDate = new Date(nowMonth.getFullYear(), nowMonth.getMonth(), 1); // 이번달 1일
let lastDate = new Date(nowMonth.getFullYear(), nowMonth.getMonth() + 1, 0); // 이번달 마지막날
let tbody_Calendar = document.querySelector(".Calendar > tbody");
document.getElementById("calYear").innerText = nowMonth.getFullYear(); // 연도 숫자 갱신
document.getElementById("calMonth").innerText = leftPad(nowMonth.getMonth() + 1); // 월 숫자 갱신
while (tbody_Calendar.rows.length > 0) { // 이전 출력결과가 남아있는 경우 초기화
tbody_Calendar.deleteRow(tbody_Calendar.rows.length - 1);
}
let nowRow = tbody_Calendar.insertRow(); // 첫번째 행 추가
for (let j = 0; j < firstDate.getDay(); j++) { // 이번달 1일의 요일만큼
let nowColumn = nowRow.insertCell(); // 열 추가
}
for (let nowDay = firstDate; nowDay <= lastDate; nowDay.setDate(nowDay.getDate() + 1)) { // day는 날짜를 저장하는 변수, 이번달 마지막날까지 증가시키며 반복
let nowColumn = nowRow.insertCell(); // 새 열을 추가하고
let newDIV = document.createElement("p");
newDIV.innerHTML = leftPad(nowDay.getDate()); // 추가한 열에 날짜 입력
nowColumn.appendChild(newDIV);
if (nowDay.getDay() == 6) { // 토요일인 경우
nowRow = tbody_Calendar.insertRow(); // 새로운 행 추가
}
if (nowDay < today) { // 지난날인 경우
newDIV.className = "pastDay";
}
else if (nowDay.getFullYear() == today.getFullYear() && nowDay.getMonth() == today.getMonth() && nowDay.getDate() == today.getDate()) { // 오늘인 경우
newDIV.className = "today";
newDIV.onclick = function () { choiceDate(this); }
}
else { // 미래인 경우
newDIV.className = "futureDay";
newDIV.onclick = function () { choiceDate(this); }
}
}
}
// 날짜 선택
function choiceDate(newDIV) {
if (document.getElementsByClassName("choiceDay")[0]) { // 기존에 선택한 날짜가 있으면
document.getElementsByClassName("choiceDay")[0].classList.remove("choiceDay"); // 해당 날짜의 "choiceDay" class 제거
}
newDIV.classList.add("choiceDay"); // 선택된 날짜에 "choiceDay" class 추가
}
// 이전달 버튼 클릭
function prevCalendar() {
nowMonth = new Date(nowMonth.getFullYear(), nowMonth.getMonth() - 1, nowMonth.getDate()); // 현재 달을 1 감소
buildCalendar(); // 달력 다시 생성
}
// 다음달 버튼 클릭
function nextCalendar() {
nowMonth = new Date(nowMonth.getFullYear(), nowMonth.getMonth() + 1, nowMonth.getDate()); // 현재 달을 1 증가
buildCalendar(); // 달력 다시 생성
}
// input값이 한자리 숫자인 경우 앞에 '0' 붙혀주는 함수
function leftPad(value) {
if (value < 10) {
value = "0" + value;
return value;
}
return value;
}
</script>
코드를 읽어보니 달력을 만드는 과정은 이랬다.
1. 현재 날짜를 new Date()로 불러온다.
2. 현재 날짜의 월에서 첫 날과 마지막 날을 변수에 저장한다.
3. tbody에 행을 추가하고 첫 날의 요일(숫자)만큼 열을 추가한다 (지난 달)
4. 열을 추가한 뒤 p태그를 create하고 innerHTML을 한다.
5. creat한 날짜의 요일이 토요일(6)인 경우 테이블의 행을 추가한다.
6. 현재 날짜 연산자를 이용해 비교한 후 과거와, 오늘, 미래의 날에 class를 add 해 준다.
7. 다음달, 이전 달 버튼을 클릭하면 Month가 1씩 증감하고 그 달을 기준으로 다시 달력을 불러오는 함수를 호출한다.
출발일을 선택한 후 다음 날짜를 클릭하면 리턴일이 되어 값을 각각 다르게 지정하고 input하고 싶었지만 잘 되지 않아 실패를 하였다.
선택한 날중 앞 뒤를 따져 class를 붙이는 것도 쉽지 않았고, 각각 다른 날을 출발일, 리턴일로 정하는 것도 아직은 어려웠다. 그래서 어쩔 수 없이 출발일 달력과 리턴일 달력을 따로 만들었다.
완성을 한 후 프로젝트 기한까지 시간이 남는다면 수정해 보려고 한다.