사악미소
현대마법의 공방
사악미소
전체 방문자
오늘
어제
  • 분류 전체보기
    • Document
    • JavaScript
    • jQuery
    • Spring Web
      • Spring Framework
      • Spring Boot
    • Android
      • Java Code
      • Setting
    • iOS
      • Swift Code
      • Setting
    • PHP
      • Code
      • Setting
    • AWS
    • LINUX
      • Rocky Linux
      • CentOS
    • Node.js
    • Developer Tool
    • GIT
    • MAC
    • Scraping Document
    • MariaDB
    • WYSIWYG
    • Scouter
    • Docker
    • Planning
    • 용어정리
반응형

인기 글

최근 댓글

Programmer 사악미소.
사악미소

사악미소의 현대마법의 공방

[JavaScript] 자바스크립트를 이용한 캘린더 제작
JavaScript

[JavaScript] 자바스크립트를 이용한 캘린더 제작

2022. 12. 23. 14:42
728x90

 

jQuery등을 통한 캘린더 라이브러리가 많이 존재하지만 뭔가 꼭 있어야 하거나, 구현해야하는 효과가 있는경우

 

원하는 캘린더 라이브러리를 다시 찾아봐야 하거나, 라이브러리를 마개조 해야하는 상황이 발생하여

 

순수하게 자바스크립트만을 이용한 달력을 제작하게 되었다.

 

 

위 3가지 조건을 만족시키는 순수 자바스크립트 캘린더를 제작해 보려고 한다.

 


 

# 소스코드

<html>
<head>
<title>:: JavaScript 캘린더 ::</title>
<style type="text/css">
    a { color:#000000;text-decoration:none; }
    .scriptCalendar { text-align:center; }
    .scriptCalendar > thead > tr > td { width:50px;height:50px; }
    .scriptCalendar > thead > tr:first-child > td { font-weight:bold; }
    .scriptCalendar > thead > tr:last-child > td { background-color:#90EE90; }
    .scriptCalendar > tbody > tr > td { width:50px;height:50px; }
    .calendarBtn { cursor:pointer; } 
</style>
<script type="text/javascript">
    document.addEventListener("DOMContentLoaded", function() {
        buildCalendar();
        
        document.getElementById("btnPrevCalendar").addEventListener("click", function(event) {
            prevCalendar();
        });
        
        document.getElementById("nextNextCalendar").addEventListener("click", function(event) {
            nextCalendar();
        });
    });

    var toDay = new Date(); // @param 전역 변수, 오늘 날짜 / 내 컴퓨터 로컬을 기준으로 toDay에 Date 객체를 넣어줌
    var nowDate = new Date();  // @param 전역 변수, 실제 오늘날짜 고정값
    
    /**
     * @brief   이전달 버튼 클릭시
     */
    function prevCalendar() {
        this.toDay = new Date(toDay.getFullYear(), toDay.getMonth() - 1, toDay.getDate());
        buildCalendar();    // @param 전월 캘린더 출력 요청
    }

    /**
     * @brief   다음달 버튼 클릭시
     */
    function nextCalendar() {
        this.toDay = new Date(toDay.getFullYear(), toDay.getMonth() + 1, toDay.getDate());
        buildCalendar();    // @param 명월 캘린더 출력 요청
    }

    /**
     * @brief   캘린더 오픈
     * @details 날짜 값을 받아 캘린더 폼을 생성하고, 날짜값을 채워넣는다.
     */
    function buildCalendar() {

        let doMonth = new Date(toDay.getFullYear(), toDay.getMonth(), 1);
        let lastDate = new Date(toDay.getFullYear(), toDay.getMonth() + 1, 0);

        let tbCalendar = document.querySelector(".scriptCalendar > tbody");

        document.getElementById("calYear").innerText = toDay.getFullYear();                       // @param YYYY월
        document.getElementById("calMonth").innerText = autoLeftPad((toDay.getMonth() + 1), 2);   // @param MM월
        

        // @details 이전 캘린더의 출력결과가 남아있다면, 이전 캘린더를 삭제한다.
        while(tbCalendar.rows.length > 0) {
            tbCalendar.deleteRow(tbCalendar.rows.length - 1);
        }

        // @param 첫번째 개행
        let row = tbCalendar.insertRow();

        // @param 날짜가 표기될 열의 증가값
        let dom = 1;

        // @details 시작일의 요일값( doMonth.getDay() ) + 해당월의 전체일( lastDate.getDate())을  더해준 값에서
        //               7로 나눈값을 올림( Math.ceil() )하고 다시 시작일의 요일값( doMonth.getDay() )을 빼준다.
        let daysLength = (Math.ceil((doMonth.getDay() + lastDate.getDate()) / 7) * 7) - doMonth.getDay();

        // @param 달력 출력
        // @details 시작값은 1일을 직접 지정하고 요일값( doMonth.getDay() )를 빼서 마이너스( - )로 for문을 시작한다.
        for(let day = 1 - doMonth.getDay(); daysLength >= day; day++) {

            let column = row.insertCell();

            // @param 평일( 전월일과 익월일의 데이터 제외 )
            if(Math.sign(day) == 1 && lastDate.getDate() >= day) {

                // @param 평일 날짜 데이터 삽입
                column.innerText = autoLeftPad(day, 2);

                // @param 일요일인 경우
                if(dom % 7 == 1) {
                    column.style.color = "#FF4D4D";
                }

                // @param 토요일인 경우
                if(dom % 7 == 0) {
                    column.style.color = "#4D4DFF";
                    row = tbCalendar.insertRow();   // @param 토요일이 지나면 다시 가로 행을 한줄 추가한다.
                }

            }

            // @param 평일 전월일과 익월일의 데이터 날짜변경
            else {
                let exceptDay = new Date(doMonth.getFullYear(), doMonth.getMonth(), day);
                column.innerText = autoLeftPad(exceptDay.getDate(), 2);
                column.style.color = "#A9A9A9";
            }

            // @brief   전월, 명월 음영처리
            // @details 현재년과 선택 년도가 같은경우
            if(toDay.getFullYear() == nowDate.getFullYear()) {

                // @details 현재월과 선택월이 같은경우
                if(toDay.getMonth() == nowDate.getMonth()) {

                    // @details 현재일보다 이전인 경우이면서 현재월에 포함되는 일인경우
                    if(nowDate.getDate() > day && Math.sign(day) == 1) {
                        column.style.backgroundColor = "#E5E5E5";
                    }

                    // @details 현재일보다 이후이면서 현재월에 포함되는 일인경우
                    else if(nowDate.getDate() < day && lastDate.getDate() >= day) {
                        column.style.backgroundColor = "#FFFFFF";
                        column.style.cursor = "pointer";
                        column.onclick = function(){ calendarChoiceDay(this); }
                    }

                    // @details 현재일인 경우
                    else if(nowDate.getDate() == day) {
                        column.style.backgroundColor = "#FFFFE6";
                        column.style.cursor = "pointer";
                        column.onclick = function(){ calendarChoiceDay(this); }
                    }

                // @details 현재월보다 이전인경우
                } else if(toDay.getMonth() < nowDate.getMonth()) {
                    if(Math.sign(day) == 1 && day <= lastDate.getDate()) {
                        column.style.backgroundColor = "#E5E5E5";
                    }
                }

                // @details 현재월보다 이후인경우
                else {
                    if(Math.sign(day) == 1 && day <= lastDate.getDate()) {
                        column.style.backgroundColor = "#FFFFFF";
                        column.style.cursor = "pointer";
                        column.onclick = function(){ calendarChoiceDay(this); }
                    }
                }
            }

            // @details 선택한년도가 현재년도보다 작은경우
            else if(toDay.getFullYear() < nowDate.getFullYear()) {
                if(Math.sign(day) == 1 && day <= lastDate.getDate()) {
                    column.style.backgroundColor = "#E5E5E5";
                }
            }

            // @details 선택한년도가 현재년도보다 큰경우
            else {
                if(Math.sign(day) == 1 && day <= lastDate.getDate()) {
                    column.style.backgroundColor = "#FFFFFF";
                    column.style.cursor = "pointer";
                    column.onclick = function(){ calendarChoiceDay(this); }
                }
            }
            dom++;
        }
    }

    /**
     * @brief   날짜 선택
     * @details 사용자가 선택한 날짜에 체크표시를 남긴다.
     */
    function calendarChoiceDay(column) {

        // @param 기존 선택일이 존재하는 경우 기존 선택일의 표시형식을 초기화 한다.
        if(document.getElementsByClassName("choiceDay")[0]) {
            
            // @see 금일인 경우
            if(document.getElementById("calMonth").innerText == autoLeftPad((nowDate.getMonth() + 1), 2) && document.getElementsByClassName("choiceDay")[0].innerText == autoLeftPad(toDay.getDate(), 2)) {
                document.getElementsByClassName("choiceDay")[0].style.backgroundColor = "#FFFFE6";  
            }
            
            // @see 금일이 아닌 경우
            else {
                document.getElementsByClassName("choiceDay")[0].style.backgroundColor = "#FFFFFF";
            }
            document.getElementsByClassName("choiceDay")[0].classList.remove("choiceDay");
        }

        // @param 선택일 체크 표시
        column.style.backgroundColor = "#FF9999";

        // @param 선택일 클래스명 변경
        column.classList.add("choiceDay");
    }

    /**
     * @brief   숫자 두자릿수( 00 ) 변경
     * @details 자릿수가 한자리인 ( 1, 2, 3등 )의 값을 10, 11, 12등과 같은 두자리수 형식으로 맞추기위해 0을 붙인다.
     * @param   num     앞에 0을 붙일 숫자 값
     * @param   digit   글자의 자릿수를 지정 ( 2자릿수인 경우 00, 3자릿수인 경우 000 … )
     */
    function autoLeftPad(num, digit) {
        if(String(num).length < digit) {
            num = new Array(digit - String(num).length + 1).join("0") + num;
        }
        return num;
    }

</script>
</head>
<body>
<div>
    <h3>■ JavaScript 캘린더</h3>
    <br/>
    <table class="scriptCalendar">
        <thead>
            <tr>
                <td class="calendarBtn" id="btnPrevCalendar">&#60;&#60;</td>
                <td colspan="5">
                    <span id="calYear">YYYY</span>년
                    <span id="calMonth">MM</span>월
                </td>
                <td class="calendarBtn" id="nextNextCalendar">&#62;&#62;</td>
            </tr>
            <tr>
                <td>일</td><td>월</td><td>화</td><td>수</td><td>목</td><td>금</td><td>토</td>
            </tr>
        </thead>
        <tbody></tbody>
    </table>
</div>
</body>
</html>

 


 

# 출력결과

■ JavaScript 캘린더


<< YYYY년 MM월 >>
일월화수목금토

 ※ 캘린더 기능 설명



  #1. 실행은 금일 날짜를 기준으로 실행된다.

   금  일 :


  #2. 금일 이후의 날짜만 선택할 수 있다.

   선택일 :


  #3. 지난 날짜는 선택이 불가능 하다.

 

 

 

728x90

'JavaScript' 카테고리의 다른 글

[JavaScript] 입력한 텍스트의 Byte 체크  (0) 2023.02.14
[JavaScript] 입력한 텍스트의 문자길이 체크  (0) 2023.02.14
[JavaScript] 휴대폰 번호 Hyphen(-) 삽입 형식 자동 입력폼  (0) 2022.12.26
[JavaScript] UTC값을 YYYY-MM-DD 형식으로 변경하기  (0) 2022.05.24
[JavaScript] 사용자 접속 Browser 이름 확인하기  (0) 2021.08.12
    'JavaScript' 카테고리의 다른 글
    • [JavaScript] 입력한 텍스트의 문자길이 체크
    • [JavaScript] 휴대폰 번호 Hyphen(-) 삽입 형식 자동 입력폼
    • [JavaScript] UTC값을 YYYY-MM-DD 형식으로 변경하기
    • [JavaScript] 사용자 접속 Browser 이름 확인하기
    사악미소
    사악미소

    티스토리툴바