1. Calendar
기간이 선택가능하고, 이벤트를 사용자 임의로 설정 가능한 달력.
시작일 이전의 기간은 선택이 불가능하다.
공휴일을 지정할 수 있다.
2. Code
type CalendarModel = {
listener? : any;
}
export class Calendar{
model : CalendarModel;
parent : HTMLElement;
holiday : any = {"0101" : true, "0121" : true, "0122" : true, "0123" : true, "0124" : true, "0301" : true, "0505" : true, "0527" : true, "0606" : true
, "0815" : true, "0928" : true, "0929" : true, "0930" : true, "1003" : true, "1009" : true, "1225" : true,
};
constructor(model : CalendarModel, parent : HTMLElement) {
this.model = model;
this.parent = parent;
this.load();
}
async load(){
let selected = new Date();
let selectedYear : any, selectedMonth : any, startDate : any, endDate : any;
let selectedStartDate : any = null;
let selectedEndDate : any = null;
const drawCalendar = () => {
this.parent.innerHTML = "";
settingDay();
const calendarDiv = document.createElement("calendar-div");
const table = document.createElement("table");
const thead = document.createElement("thead");
const theadTr1 = document.createElement("tr");
const theadTr2 = document.createElement("tr");
const prevMonth = document.createElement("td");
const dateInfo = document.createElement("td");
const nextMonth = document.createElement("td");
prevMonth.append("<");
prevMonth.style.cursor = "pointer";
prevMonth.addEventListener("click", () => {monthClick("prev");});
nextMonth.append(">");
nextMonth.style.cursor = "pointer";
nextMonth.addEventListener("click", () => {monthClick("next");});
dateInfo.colSpan = 5;
dateInfo.innerHTML = `<span id="infoYear">${selectedYear}</span>년 <span id="infoMonth">${selectedMonth + 1}</span>월`;
theadTr1.append(prevMonth);
theadTr1.append(dateInfo);
theadTr1.append(nextMonth);
theadTr2.innerHTML = "<td>일</td><td>월</td><td>화</td><td>수</td><td>목</td><td>금</td><td>토</td>"
thead.append(theadTr1);
thead.append(theadTr2);
table.append(thead);
table.append(document.createElement("tbody"));
calendarDiv.append(table);
this.parent.append(calendarDiv);
const body = document.querySelector("calendar-div tbody") as HTMLTableElement;
let row = body.insertRow();
for (let i = 0; i < startDate.getDay(); i++){
row.insertCell();
}
for (let i = startDate; i <= endDate; i.setDate(i.getDate() + 1)){
let cell = row.insertCell();
cell.id = "calendar_" + i.getDate();
const date = i.getDate();
cell.innerHTML = date.toString();
cell.addEventListener("click", () => {
dayClick(cell, new Date(selectedYear, selectedMonth, date));
});
if (i.getDay() == 0) cell.style.color = "red";
if (i.getDay() == 6){
cell.style.color = "gray";
row = body.insertRow();
}
const key = parseInt("" + doubleDigit(i.getMonth() + 1) + doubleDigit(i.getDate()));
if(this.holiday[key] == true) cell.style.color = "red";
}
const tds = body.getElementsByTagName("td");
if(selectedStartDate){
settingDay();
if(selectedStartDate.getFullYear() == selectedYear && selectedStartDate.getMonth() == selectedMonth){
for (let i = startDate; i <= endDate; i.setDate(i.getDate() + 1)){
if(selectedStartDate <= i && selectedStartDate >= i){
document.getElementById("calendar_" + i.getDate())?.classList.add("selected");
}
if(!selectedEndDate && i < selectedStartDate){
document.getElementById("calendar_" + i.getDate())?.classList.add("disabled");
}
}
}else if(!selectedEndDate && (selectedStartDate.getFullYear() > selectedYear || selectedStartDate.getMonth() > selectedMonth)){
for(let i = 0; i < tds.length; i ++){
tds[i].classList.add("disabled");
}
}
if(selectedEndDate){
const afterStart = selectedStartDate.getFullYear() <= selectedYear && selectedStartDate.getMonth() <= selectedMonth;
const beforeEnd = selectedEndDate.getFullYear() >= selectedYear && selectedEndDate.getMonth() >= selectedMonth;
if(afterStart && beforeEnd){
settingDay();
for (let i = startDate; i <= endDate; i.setDate(i.getDate() + 1)){
if(i >= selectedStartDate && i <= selectedEndDate){
document.getElementById("calendar_" + i.getDate())?.classList.add("selected");
}
}
}
}
}
const monthClick = (type : string) => {
if(type == "prev"){
selected = new Date(selectedYear, selectedMonth - 1, selected.getDate());
}else if(type == "next"){
selected = new Date(selectedYear, selectedMonth + 1, selected.getDate());
}
drawCalendar();
};
const dayClick = (day : HTMLTableCellElement, data : Date) => {
settingDay();
if(day.classList.contains("disabled")) return;
if(selectedEndDate){
for(let i = 0; i < tds.length; i ++){
tds[i].classList.remove("disabled", "selected");
}
selectedStartDate = data;
day.classList.add("selected");
for (let i = startDate; i <= endDate; i.setDate(i.getDate() + 1)){
if(i < selectedStartDate){
document.getElementById("calendar_" + i.getDate())?.classList.add("disabled");
}
}
selectedEndDate = null;
}else{
if(!selectedStartDate){
selectedStartDate = data;
day.classList.add("selected");
for (let i = startDate; i <= endDate; i.setDate(i.getDate() + 1)){
if(i < selectedStartDate) document.getElementById("calendar_" + i.getDate())?.classList.add("disabled");
}
}else{
selectedEndDate = data;
for(let i = 0; i < tds.length; i ++){
tds[i].classList.remove("disabled");
}
for (let i = startDate; i <= endDate; i.setDate(i.getDate() + 1)){
if(selectedStartDate < i && i <= selectedEndDate) document.getElementById("calendar_" + i.getDate())?.classList.add("selected");
}
if(this.model.listener) this.model.listener({startDate : selectedStartDate, endDate : selectedEndDate});
}
}
};
}
const settingDay = () => {
selectedYear = selected.getFullYear();
selectedMonth = selected.getMonth();
startDate = new Date(selectedYear, selectedMonth, 1);
endDate = new Date(selectedYear, selectedMonth + 1, 0);
}
drawCalendar();
function doubleDigit(number : number){
if(number < 10) return "0" + number;
else return number
}
}
}
3. How To Use
class AssetHistoryCell extends View{
constructor(parent? : View) {
super("asset-history", parent);
this.load();
}
async load(){
new Calendar({listener : (result : any) => {
console.log(result);
}}, left.el);
}
}
4. Download
반응형
'Client Side > - Type Script' 카테고리의 다른 글
Tip (0) | 2024.07.18 |
---|---|
Enum, Union Type, Tree Shaking (0) | 2023.10.30 |
Type & Interface (0) | 2023.02.01 |