JavaScrpt/시간 날짜 달력

JavaScript Date - 달력 컨트롤(이전 달/년, 다음 달/년 이동 처리)과 날짜 클릭 이벤트 처리(동적/정적 이벤트)

carrotweb 2022. 3. 27. 15:03
728x90
반응형

이어서 달력의 월 변경 기능과 날짜 클릭 이벤트를 처리하겠습니다.

먼저 태그에 있는 style 속성으로 인해 스크립트가 복잡해 보입니다. 그래서 태그의 style 속성을 class로 변경 처리하겠습니다. 그리고 달력의 크기와 월 변경 기능을 추가할 영역을 위해 <div> 태그로 감쌉니다.

<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<title>달력 만들기</title>
		<style>
			.calendar { width: 500px; }
			.calendar table { width: 100%; }
			.calendar table > caption { font-size: larger; font-weight: bolder; color: red; text-align: left; padding: 10px 20px; }
			.calendar table > tbody > tr > td { padding: 10px 10px; text-align: center; }
			.calendar table > tbody > tr > td > span { display: block; padding: 10px 10px; }
			.calendar table > tbody > tr > td > span.today { border: 1px solid red; border-radius: 50%; color: white; background-color: red; padding: 9px 9px; }
		</style>
		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
	</head>
	<body>
		<div class="calendar">
			<div id="calendar"></div>
		</div>
		<script>
			var date = new Date();
			
			// 달력 연도
			var calendarYear = date.getFullYear();
			// 달력 월
			var calendarMonth = date.getMonth() + 1;
			// 달력 일
			var calendarToday = date.getDate();
			
			var monthLastDate = new Date(calendarYear, calendarMonth, 0);
			// 달력 월의 마지막 일
			var calendarMonthLastDate = monthLastDate.getDate();
			
			var monthStartDay = new Date(calendarYear, date.getMonth(), 1);
			// 달력 월의 시작 요일
			var calendarMonthStartDay = monthStartDay.getDay();
			
			// 주 카운트
			var calendarWeekCount = Math.ceil((calendarMonthStartDay + calendarMonthLastDate) / 7);
			
			var html = "";
			html += "<table>";
			html += "<caption>" + calendarMonth + "월</caption>";
			html += "<thead>";
			html += "<tr>";
			html += "<th>일</th><th>월</th><th>화</th><th>수</th><th>목</th><th>금</th><th>토</th>";
			html += "</tr>";
			html += "</thead>";
			html += "<tbody>";
			// 위치
			var calendarPos = 0;
			// 날짜
			var calendarDay = 0;
			for (var index1 = 0; index1 < calendarWeekCount; index1++) {
				html += "<tr>";
				for (var index2 = 0; index2 < 7; index2++) {
					html += "<td>";
					if (calendarMonthStartDay <= calendarPos && calendarDay < calendarMonthLastDate) {
						calendarDay++;
						html += "<span";
						if (calendarDay == calendarToday) {
							html += " class=\"today\"";
						}
						html += ">" + calendarDay + "</span>";
					}
					html += "</td>";
					calendarPos++;
				}
				html += "</tr>";
			}
			html += "</tbody>";
			html += "</table>";
			$("#calendar").html(html);
		</script>
	</body>
</html>

 

 

월(이전 달, 다음 달) 변경 기능 추가

년과 월을 표시할 <span> 태그를 추가하고 이전 달과 다음 달로 이동할 수 있는 버튼과 오늘 날짜로 이동하는 버튼을 추가합니다.

<div class="calendar">
	<div class="calendar-header">
		<span class="calendar-yearmonth"></span>
		<div class="calendar-controls">
			<button type="button" class="calendar-prev">&lt;</button>
			<button type="button" class="calendar-next">&gt;</button>
			<button type="button" class="calendar-today">오늘</button>
		</div>
	</div>
	<div id="calendar"></div>
</div>

 

<style>에도 class를 추가합니다.

.calendar > .calendar-header { position: relative; height: 50px; margin: 0px 20px; }
.calendar > .calendar-header > .calendar-yearmonth { position: relative; font-size: larger; font-weight: bolder; color: red; line-height: 50px; }
.calendar > .calendar-header > .calendar-controls { position: absolute; top: 11px; right: 0px; }
.calendar > .calendar-header > .calendar-controls > button { float: left; width: 25px; height: 28px; padding: 1px 4px 0 4px; border: 1px solid #cbcbcb; background-color: #fff; font-size: 12px; cursor: pointer; }
.calendar > .calendar-header > .calendar-controls > button.calendar-today { width: 40px; }

 

<script>에서 기존의 <tabel>의 <caption>를 삭제합니다.

html += "<caption>" + calendarMonth + "월</caption>"; --> 삭제

 

오늘 날짜를 처리하기 위해 입력된 년, 월, 일과 오늘 날짜를 비교하여 처리합니다.

// (이전 소스) 오늘 날짜 처리
if (calendarDay == calendarToday) {
	html += " class=\"today\"";
}

// (변경된 소스) 입력된 년, 월, 일과 비교하여 오늘 날짜 처리 
var today = new Date();
if (calendarYear == today.getFullYear() && calendarMonth == today.getMonth() + 1
	&& calendarDay == today.getDate()) {
	html += " class=\"today\"";
}

 

 

달력을 이전 달과 다음 달로 이동하면서 처리하기 위해서 기존 스크립트를 함수로 변경합니다.

function calendar(date) {
	// 달력 연도
	var calendarYear = date.getFullYear();
	// 달력 월
	var calendarMonth = date.getMonth() + 1;
	// 달력 일
	var calendarToday = date.getDate();
	
	var monthLastDate = new Date(calendarYear, calendarMonth, 0);
	// 달력 월의 마지막 일
	var calendarMonthLastDate = monthLastDate.getDate();
	
	var monthStartDay = new Date(calendarYear, date.getMonth(), 1);
	// 달력 월의 시작 요일
	var calendarMonthStartDay = monthStartDay.getDay();
	
	// 주 카운트	
	var calendarWeekCount = Math.ceil((calendarMonthStartDay + calendarMonthLastDate) / 7);
	
	// 년월
	$(".calendar-yearmonth").html(calendarYear + "." + calendarMonth);
	
	// 오늘
	var today = new Date();
	
	var html = "";
	html += "<table>";
	html += "<thead>";
	html += "<tr>";
	html += "<th>일</th><th>월</th><th>화</th><th>수</th><th>목</th><th>금</th><th>토</th>";
	html += "</tr>";
	html += "</thead>";
	html += "<tbody>";
	// 위치
	var calendarPos = 0;
	// 날짜
	var calendarDay = 0;
	for (var index1 = 0; index1 < calendarWeekCount; index1++) {
		html += "<tr>";
		for (var index2 = 0; index2 < 7; index2++) {
			html += "<td>";
			if (calendarMonthStartDay <= calendarPos && calendarDay < calendarMonthLastDate) {
				calendarDay++;
				html += "<span";
				if (calendarYear == today.getFullYear() && calendarMonth == today.getMonth() + 1
					&& calendarDay == today.getDate()) {
					html += " class=\"today\"";
				}
				html += ">" + calendarDay + "</span>";
			}
			html += "</td>";
			calendarPos++;
		}
		html += "</tr>";
	}
	html += "</tbody>";
	html += "</table>";
	$("#calendar").html(html);
}

calendar(new Date());

 

 

정적 이벤트 vs 동적 이벤트

jQuery에서 정적 이벤트는 이미 생성되어 있는 태그에 이벤트를 추가하여 처리되게 됩니다.

$(".calendar-controls > .calendar-prev").click(function() {});
$(".calendar-controls > .calendar-prev").on("click", function() {});

 

jQuery에서 동적 이벤트는 html() 메서드를 통해 생성된 태그에 자동으로 이벤트가 추가되어 처리되게 됩니다.

$(document).on("click", ".calendar table > tbody > tr > td > span", function() {});

 

 

달력 이동 버튼 클릭 이벤트 처리

 

이전 달 이동 버튼과 다음 달 이동 버튼, 오늘 버튼에 대한 click 이벤트를 <script>에 추가합니다.

// 이전 달 이동 버튼 클릭
$(".calendar-controls > .calendar-prev").on("click", function() {
	var yearmonth = $(".calendar-yearmonth").text().split(".");
	calendar(new Date(parseInt(yearmonth[0]), parseInt(yearmonth[1]) - 2, 1));
});

// 다음 달 이동 버튼 클릭
$(".calendar-controls > .calendar-next").on("click", function() {
	var yearmonth = $(".calendar-yearmonth").text().split(".");
	calendar(new Date(parseInt(yearmonth[0]), parseInt(yearmonth[1]), 1));
});

// 오늘 이동 버튼 클릭
$(".calendar-controls > .calendar-today").on("click", function() {
	calendar(new Date());
});

 

 

 

이전 달 계산

이전 달 이동 버튼 클릭 시 달력의 년, 월을 가져옵니다. 월(getMonth())은 Zero Base으로 가져온 월에서 1을 빼야 합니다.

작성 당시 2002년 3월 20일로 월(getMonth())은 2가 됩니다. 이전 달로 만들기 위해서는 다시 1을 빼면 됩니다. 그러면 Date 객체에서는 이전 월로 계산하여 자동 설정됩니다.

new Date(2022, 3-1-1, 1); --> 2022-02-01 00:00:00
 

만약, 월이 1월이면 Zero Base으로 0입니다. 그래서 이전 년 12월로 처리하기 위해서 다시 1을 빼면 됩니다. 그러면 Date 객체에서는 이전 년으로 계산하여 자동 설정됩니다.

new Date(2022, 1-1-1, 1); --> 2021-12-01 00:00:00

 

현재 연도를 기준으로 월이 음수이면 현재 연도에서 월을 빼서 계산됩니다.

new Date(2022, 0, 1); --> 2022-01-01 00:00:00
new Date(2022, -1, 1); --> 2021-12-01 00:00:00
new Date(2022, -2, 1); --> 2021-11-01 00:00:00

 

 

다음 달 계산

다음 달 이동 버튼 클릭 시는 가져온 월이 3으로 다음 달인 4월은 Zero Base으로 3입니다. 그래서 변경 없이 처리하면 됩니다.

new Date(2022, 3, 1); --> 2022-04-01 00:00:00

 

마찬가지로 월이 12월이면 다음 년 1월로 처리하기 위해서 그냥 변경 없이 처리하면 Date 객체에서는 다음 년으로 계산하여 자동 설정됩니다.

new Date(2022, 12, 1); --> 2023-01-01 00:00:00

 

현재 연도를 기준으로 월이 12 이상이면 현재 연도에서 월을 더해서 계산됩니다. 12이면 월이 +1이 됩니다.

new Date(2022, 11, 1); --> 2022-12-01 00:00:00
new Date(2022, 12, 1); --> 2023-01-01 00:00:00
new Date(2022, 14, 1); --> 2023-03-01 00:00:00

 

 

 

날짜 클릭 이벤트 처리

날짜에 대한 click 이벤트를 <script>에 추가합니다.

// 날짜 클릭
$(document).on("click", ".calendar table > tbody > tr > td > span", function(event) {
	var yearmonth = $(".calendar-yearmonth").text().split(".");
	alert(yearmonth[0] + "." + yearmonth[1] + "." + $(event.target).text());
});

 

달력이 태그들은 매번 새롭게 생성되기 때문에 정적 이벤트로 처리할 수 없습니다. 그래서 동적 이벤트로 처리해야 새롭게 생성된 태그들도 이벤트가 자동으로 처리되게 됩니다.

 

 

이벤트를 수정해서 다양한 기능을 추가해 보시기 바랍니다.

728x90
반응형