[JavaScript] SelectBox를 사용하는 날짜 검색창 제작[JavaScript] SelectBox를 사용하는 날짜 검색창 제작
Posted at 2020. 7. 12. 20:31 | Posted in JavaScript & jQuery/JavaScript■ 셀렉트 박스를 이용한 캘린더 제작
위와 같이 <SELECT> 태그를 통해 날짜값을 지정하여 검색하는 페이지를 제작하게 되었다.
jQuery UI의 DatePicker등을 사용하면 그냥 손쉽게 해결 할 수 있고,
보통은 다 이렇게 하지만, 또 막상 일을 하다보면 위와 같은 검색을 선호하는 클라이언트가 또 있을 수 있다라는 생각이들어
추가적으로 실제 업무에서 많이 쓰이게 되는 GET 방식을 통한 검색조건 전달의 경우를 포함하여
내용을 정리해보았다.
※ 예외 처리해야할 사항들
① 매월의 마지막 날의 날짜는 항상 일치하지 않기에, 그달의 마지막 날보다 큰 날짜는 자동적으로 선택할 수 없어야 한다.
② 처음 접속시 해당월의 첫째날( 01일 )과 마지막날( 28일, 29,일 30일, 31일 등 )이 자동 세팅되어야 한다.
③ GET방식을 통해 검색 시작일과 종료일의 날짜 데이터가 전달되는 경우의 수를 처리해야 한다.
④ 사용자가 날짜를 선택하는 과정에서 31일이 선택되어 있는 가운데 31일이 존재하지 않는 년, 월을 선택한 경우
해당 월의 마지막 날로 자동 변경시켜주어야 한다.
위 경우를 상정하여 아래 코드를 작성하게 되었다.
# 소스코드
<html> <head> <title>:: JavaScript 매월 주차 구하기 ::</title> <script type="text/javascript"> document.addEventListener("DOMContentLoaded", function() { const stdDays = document.querySelector("span:nth-child(1)"); // @param 시작일 영역지정 const endDays = document.querySelector("span:nth-child(2)"); // @param 종료일 영역지정 let stdFirstDate = null; // @param 시작일의 첫날 let endFirstDate = null; // @param 종료일의 첫날 let stdLastDate = null; // @param 시작일의 전체일수 let endLastDate = null; // @param 종료일의 전체일수 // @param GET방식으로 전달된 시작일, 종료일의 지정값이 존재하지 않는경우 ( ※ 맨처음 시작시에 실행 ) if(nullPointerException(getParameter("stdDate")) == false && nullPointerException(getParameter("endDate")) == false) { const toDate = new Date(); stdFirstDate = new Date(toDate.getFullYear(), (toDate.getMonth() + 1)); stdLastDate = new Date(stdFirstDate.getFullYear(), (stdFirstDate.getMonth() + 1), 1); // @param 다음달의 첫째날을 지정 stdLastDate.setDate(0); // @param 다음달에서 하루를 빼서 원하는 월의 마지막 날로 맞춤 endFirstDate = new Date(toDate.getFullYear(), (toDate.getMonth() + 1)); endLastDate = new Date(endFirstDate.getFullYear(), (endFirstDate.getMonth() + 1), 1); // @param 다음달의 첫째날을 지정 endLastDate.setDate(0); // @param 다음달에서 하루를 빼서 원하는 월의 마지막 날로 맞춤 } // @param GET방식으로 전달된 시작일, 종료일의 지정값이 존재하는 경우 else { const stdDate = getParameter("stdDate"); stdFirstDate = new Date( Number(stdDate.substring(0, 4)) , Number(stdDate.substring(6, 8)) , Number(stdDate.substring(4, 6)) ); stdLastDate = new Date(stdFirstDate.getFullYear(), stdFirstDate.getMonth(), 1); // @param 다음달의 첫째날을 지정 stdLastDate.setDate(0); // @param 다음달에서 하루를 빼서 원하는 월의 마지막 날로 맞춤 const endDate = getParameter("endDate"); endFirstDate = new Date( Number(endDate.substring(0, 4)) , Number(endDate.substring(4, 6)) , Number(endDate.substring(6, 8)) ); endLastDate = new Date(endFirstDate.getFullYear(), endFirstDate.getMonth(), 1); // @param 다음달의 첫째날을 지정 endLastDate.setDate(0); // @param 다음달에서 하루를 빼서 원하는 월의 마지막 날로 맞춤 } // @param 년도( Year ) - 선택 for(let year = 0; stdDays.querySelector("select:nth-child(1)").length > year; year++) { if(stdDays.querySelector("select:nth-child(1)").options[year].value == stdFirstDate.getFullYear()) { stdDays.querySelector("select:nth-child(1)").options[year].selected = true; } if(endDays.querySelector("select:nth-child(1)").options[year].value == stdFirstDate.getFullYear()) { endDays.querySelector("select:nth-child(1)").options[year].selected = true; } } // @param 월( Month ) - 선택 for(let month = 0; stdDays.querySelector("select:nth-child(2)").length > month; month++) { if(stdDays.querySelector("select:nth-child(2)").options[month].value == stdFirstDate.getMonth()) { stdDays.querySelector("select:nth-child(2)").options[month].selected = true; } if(endDays.querySelector("select:nth-child(2)").options[month].value == endFirstDate.getMonth()) { endDays.querySelector("select:nth-child(2)").options[month].selected = true; } } // @param 일( Day ) - 생성 및 선택 // @details - 날짜는 매월 마지막일이 다르게 끝나기 때문에 직접 생성하고, // 선택한 날( 기본값 시작일 - 01일, 종료일은 - 말일 )을 자동으로 selected 한다. for(let date = 1; stdLastDate.getDate() >= date; date++) { if(stdFirstDate.getDate() == date) { stdDays.querySelector("select:nth-child(3)").innerHTML += "<option value='" + date + "' selected>" + autoLeftPad(date, 2) + "</option>"; } else { stdDays.querySelector("select:nth-child(3)").innerHTML += "<option value='" + date + "'>" + autoLeftPad(date, 2) + "</option>"; } } for(let date = 1; endLastDate.getDate() >= date; date++) { if((nullPointerException(getParameter("endDate")) == true) ? endFirstDate.getDate() : endLastDate.getDate() == date) { endDays.querySelector("select:nth-child(3)").innerHTML += "<option value='" + date + "' selected>" + autoLeftPad(date, 2) + "</option>"; } else { endDays.querySelector("select:nth-child(3)").innerHTML += "<option value='" + date + "'>" + autoLeftPad(date, 2) + "</option>"; } } }); /** * @brief 시작일( 년, 월 ), 종료일 ( 년, 월 )의 값이 변경된 경우 실행 * @details 시작일( 년, 월 ), 종료일 ( 년, 월 )의 값이 변경에 따른 해당 년월의 전체일수를 다시 체크, * 변경된 년월의 일보다 선택된 일이 큰경우 마지막 날로 선택일 자동 변경 */ function changeConditionPeriod(cal) { const searchDays = cal.parentNode; const checkDate = searchDays.querySelector("select:nth-child(3)").value; // @param 다음달의 첫째날을 지정 let lastDate = new Date( searchDays.querySelector("select:nth-child(1)").value , searchDays.querySelector("select:nth-child(2)").value , 1 ); lastDate.setDate(0); // @param 하루를 뺌 // @param 일정보 초기화 searchDays.querySelector("select:nth-child(3)").innerHTML = ""; // @param 일정보 재삽입 for(let date = 1; lastDate.getDate() >= date; date++) { if(checkDate == date) { searchDays.querySelector("select:nth-child(3)").innerHTML += "<option value='" + date + "' selected>" + autoLeftPad(date, 2) + "</option>"; } else { searchDays.querySelector("select:nth-child(3)").innerHTML += "<option value='" + date + "'>" + autoLeftPad(date, 2) + "</option>"; } } // @param 일정보 예외처리 선택되어있는 마지막 날이 바꾼 월의 날보다 큰경우의 예외처리 if(checkDate > lastDate.getDate()) { searchDays.querySelector("select:nth-child(3) > option:last-child").selected = true; } } /** * @brief 강제로 앞에 0을 붙여서 두자릿수 숫자로 변경한다. * @param num 앞에 0을 붙일 숫자 값 * @param digit 자릿수를 지정 */ function autoLeftPad(num, digit) { if(String(num).length < digit) { num = new Array(digit - String(num).length + 1).join("0") + num; } return num; } /** * @brief GET으로 넘어오는 값의 존재 여부를 체크 */ function nullPointerException(worth) { if( worth == "" || worth == null || worth == undefined || (worth != null && typeof worth == "object" && !Object.keys(worth).length == "") ) { return false; } else { return true; } } /** * @brief GET방식으로 전달된 값을 추출 * @param param 추출할 key의 명칭 */ var getParameter = function(param) { let returnValue; let url = location.href; let parameters = (url.slice(url.indexOf("?") + 1, url.length)).split("&"); for(let i = 0; i < parameters.length; i++) { let varName = parameters[i].split("=")[0]; if (varName.toUpperCase() == param.toUpperCase()) { returnValue = parameters[i].split("=")[1]; return decodeURIComponent(returnValue); } } }; </script> </head> <body> <h1>■ SelectBox를 이용한 캘린더</h1> <hr/> <!-- 년( Year )은 자동으로 생성시 너무 많이 늘어날 수 있어서 --> <!-- 월( Month )은 01 ~ 12라는 고정값을 알고 있기에 직접 값을 지정 --> <!-- 일( Day )은 마지막 일이 항상 변하기 때문에 자동 생성 한다. --> <div> <span> 시작일 : <select onChange="changeConditionPeriod(this);"> <option value="2018">2018</option> <option value="2019">2019</option> <option value="2020">2020</option> <option value="2021">2021</option> <option value="2022">2022</option> <option value="2023">2023</option> <option value="2024">2024</option> <option value="2025">2025</option> </select> 년 <select onChange="changeConditionPeriod(this);"> <option value="1">01</option> <option value="2">02</option> <option value="3">03</option> <option value="4">04</option> <option value="5">05</option> <option value="6">06</option> <option value="7">07</option> <option value="8">08</option> <option value="9">09</option> <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> </select> 월 <select class="choiceDay"></select> 일 </span> ~ <span> 종료일 : <select onChange="changeConditionPeriod(this);"> <option value="2018">2018</option> <option value="2019">2019</option> <option value="2020">2020</option> <option value="2021">2021</option> <option value="2022">2022</option> <option value="2023">2023</option> <option value="2024">2024</option> <option value="2025">2025</option> </select> 년 <select onChange="changeConditionPeriod(this);"> <option value="1">01</option> <option value="2">02</option> <option value="3">03</option> <option value="4">04</option> <option value="5">05</option> <option value="6">06</option> <option value="7">07</option> <option value="8">08</option> <option value="9">09</option> <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> </select> 월 <select class="choiceDay"></select> 일 </span> </div> </body> </html> |
이제 위 코드를 브라우저를 통해 실행시켜 보면
# 출력결과
위와 같이 예외처리해야할 사항들이 정상적으로 반영되어 기능하는 모습을 확인 할 수 있다.
'JavaScript & jQuery > JavaScript' 카테고리의 다른 글
[JavaScript] 자바스크립트로 HWP 파일 제어 (0) | 2020.09.07 |
---|---|
[JavaScript] 자바스크립트를 이용한 캘린더 제작 (13) | 2020.07.13 |
[JavaScript] 매월의 월요일 기준, 주차 구하기 (4) | 2020.06.29 |
[JavaScript] Table을 Excel 처럼 즉시 수정가능하게 만들기 (1) | 2020.06.24 |
[JavaScript] 정규 표현식 사용방법 (0) | 2020.05.07 |