자바 스크립트를 이용한 달력 만들기

Sohyeon Bak·2021년 4월 5일
5

프로젝트 리뷰

목록 보기
4/5
post-thumbnail

이 프로젝트는 기능 측면에서 다른 라이브러리, 프레임워크 없이 순수 자바스크립트만을 사용했다. new Date()를 이용해 달력을 제작하는 방법을 알아보자!


JS를 이용한 달력 만들기

기능은 달력을 만들고 좌우 화살표를 누르면 해당하는 월로 넘어간다.
일마다 선택이 돼야하고, 해당 일에 대한 기능이 추가 돼야한다.
먼저 달력 구현 코드다.


let nowDate = new Date();

//먼저 윤달을 계산해야한다.
let year = nowDate.getFullYear();
let lastDay = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

//아래의 조건문이 윤달을 계산하는 방법이다.
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
    lastDay[1] = 29;
} else {
    lastDay[1] = 28;
}

//이번달을 구해야한다. 달이 -1로 나오는데 0부터 시작하기 때문이다.
let thisMonth = new Date(nowDate.getFullYear(), nowDate.getMonth()).getMonth();
//그리고 지난달의 마지막 요일 인덱스를 변수로 지정한다.
let prevMonthDay = new Date(nowDate.getFullYear(), thisMonth).getDay();

let thisDate = month[thisMonth];
let date = lastDay[thisMonth];

//*실제 달력 만드는 코드
//문자열로 마크업을 시작한다.
//문자열 자체를 반복문을 이용해 만들어 준다. 
let tag = "<tr>";

if(nextData===this.$proA.innerHTML){
    let count = 0;
    //지난달의 마지막 요일 인덱스까지 빈배열로 반복문 시작
    for (let j = 0; j < thisMonthDay; j++) {
        tag += `<td></td>`;
        count++;
    }
    
    //지난달의 마지막 요일 이후부터 이번달의 마지막일까지 반복
    for (let i = 1; i <= date; i++) {
    	//7일씩 tr로 묶기
        if (count % 7 === 0) {
            tag += "<tr>";

        }
        //조건은 쉬는 날을 지정. 따로 classname을 부여. count시작
        if(((thisDate==="Jan"&& i===1)||(thisDate==="Feb"&& (i===11||i===12||i===13))||(thisDate==="Mar"&& i===1)||(thisDate==="May"&& (i===5||i===19))||(thisDate==="Aug"&& (i===20||i===21||i===22)))||(count % 7 === 0||count % 7 === 6)){
            tag += `<td class="xday"><p>${i}</p></td>`;
            count++;
        }else if(count%7===2||count%7===4){
            tag += `<td class="Ahalf"><p>${i}</p></td>`;
            count++;
        }
        else{
            tag += `<td class="pickday"><p>${i}</p></td>`;
            count++;
        }
        //7일이 끝나면 tr태그 닫기
        if (count % 7 === 0) {
            tag += "</tr>";
            }

    }

}

먼저 윤달을 계산하는 방법을 확인해야한다.
1. 해당하는 년도에서 나누기 4를 했을때 나머지가 0인 경우
2. 1번에 해당하면서 나누기 100을 했을때 또 나머지가 0인 경우 (1,2번은 &&)
3. 그리고 2번에 해당하면서 나누기 400을 했을때 0인 경우
윤년에 해당하는 것이다.

그리고 해당하는 월에 1일이 지난달 마지막 날의 요일 다음에 와야한다.
그래서 지난 달의 마지막 날의 요일을 알아내는 new Date()함수를 확인해야한다.

마지막으로 나는 table형식으로 반복문으로 달력을 만들었다.
1일 부터 마지막 달까지 count해서 주간을 분리시켰고,
일마다 해당하는 이벤트가 있기 때문에 다양한 조건문을 활용해 classname 지정했다.

달력 이벤트

본 프로젝트는 대학교 학과 상담신청 페이지다.
교수님을 선택하고, 상담내용과 상담 날짜, 시간을 선택하고 본인의 이메일을 기입해 확인 메일을 받을 수 있는 흐름이다.
그래서 교수님마다 수업시간이나 누군가 미리 신청해 놓은 시간은 노란색으로 날짜를 표시하고, 공휴일이나 주말은 회색으로 블락처리했다.
날짜를 선택해야 시간을 선택할 수 있도록 날짜를 클릭하기 전에도 마찬가지로 블락처리를 해뒀다.

this.$info.innerHTML =""
this.$defaultDay.classList.add('show')

//해당 월의 1일을 담은 배열을 생성
const arr = [this.$defaultDay];

//pickDay에 해당하는 요소를 querySelectAll을 통해 모두 가져와서 반복문을 돌린다.
for(let j = 0; j<this.$pickDay.length; j++){
    this.$pickDay[j].addEventListener('click',(e)=>{ 
    	//클릭했을때 필요한 안내문을 추가하고, clssname을 변경한다
        this.$info.innerHTML="오전/오후 모두 가능합니다."
        this.$defaultDay.classList.remove('show')
        this.$pickDay[j].classList.add('show');
        //클릭한 해당 일만 show가 붙게 클릭할때마다 직전 요소는 show를 remove 시킨다
        arr.push(this.$pickDay[j])
        if(arr[arr.length-2]!==this.$pickDay[j]){
            arr[arr.length-2].classList.remove('show')
        }
        this.Time.isAllDay($info.innerHTML)
    })
}

for (let k = 0; k<this.$Ahalf.length; k++){
    this.$Ahalf[k].addEventListener('click',(e) =>{
        this.$defaultDay.classList.remove('show')
        this.$Ahalf[k].classList.add('show')
        arr.push(this.$Ahalf[k])
        if(arr[arr.length-2]!==this.$Ahalf[k]){
            arr[arr.length-2].classList.remove('show')
        }
        if(nextData===this.$proA.innerHTML){
            this.$info.innerHTML="오전만 가능합니다."
            this.Time.isAfterDay($info.innerHTML)
        }else if(nextData===this.$proB.innerHTML){
            this.$info.innerHTML="오후만 가능합니다."
            this.Time.isBeforeDay($info.innerHTML)
        }else if (nextData===this.$proC.innerHTML){
            this.$info.innerHTML="오전만 가능합니다."
            this.Time.isAfterDay($info.innerHTML)
        }

    })
}
//공휴일이나 주말은 아무런 효과가 없도록 한다
for (let y = 0; y<this.$xday.length; y++){
    this.$xday[y].addEventListener('click', (e) =>{
        this.$info.innerHTML=""
    })
}

일단 기본 기능에 충실해서 문제를 해결해 나가려고 했다.
그러다 보니 코드가 깔끔하지 못하고 가독성이 떨어진다고 생각된다.
날짜를 클릭할 때 라디오 버튼처럼 하나씩 클릭이 되야하는데,
직전 이벤트가 남아있다보니 그 문제를 해결하는데 오래 걸렸다.
배열을 이용했지만 최선이라고 생각하지 않는다.
날짜에 해당하는 이벤트는 다음 시간을 선택하는데 영향을 주기 때문에
데이터를 전달하기도 해야해서 더욱 복잡한 과정이었기도 하다.



프로젝트를 진행하면서 순수 자바 스크립트로만 사이트를 만들고 배포하는 모든 과정이 생소해서 컴포넌트의 부모 자식 관계를 설정하는 것도 쉽지 않았다. 그리고 class 문법을 사용해 fields와 method를 적절하게 사용하는 것도 하면서 익혔던 것 같다. 그리고 확실히 DOM에 대해서도 다양하게 알아보고 파고들었던 경험이었다.

아직 코드가 정리도 안됐고, 기능도 부족한 부분이 있는데, 다시 리팩토링을 진행하면서 반응형으로도 만들어 봐야겠다.


- 배포 페이지 : 상담 신청 페이지
- 깃헙 페이지 : 깃헙

profile
정리하고 기억하는 곳

0개의 댓글