File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
/****************************
* datePicker.js
* create
* 2023.08.08
* son tae-jin
****************************/
const dayArr = [
"일", "월", "화", "수", "목", "금", "토"
];
const month = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
const isValidDate = d => {
return d instanceof Date && !isNaN(d);
}
const detectOutsideClick = (caller, container, handler) => {
const clickOb = () => {
if(!container.contains(event.target) && caller != event.target) {
container.remove();
window.removeEventListener('click', clickOb, false);
handler();
}
}
window.addEventListener('click',clickOb, false);
}
const datePicker = (event) => {
if(event.target.dataset.picker) return;
const element = event.target;
element.dataset.picker = true;
const container = document.createElement('div');
container.classList.add('datepicker');
element.parentElement.append(container);
container.style.top = element.offsetTop + element.offsetHeight + 'px';
container.style.left = element.offsetLeft + 'px';
detectOutsideClick(element, container, () => {element.removeAttribute('data-picker')});
const dateObj = new Object();
const datePropertys = ['type', 'value', 'min', 'max', 'step'];
datePropertys.forEach(el => {
if(element[el]) dateObj[el] = element[el];
});
initDataPicker(container, dateObj);
}
const initDataPicker = (container,property) => {
console.log(container, property);
switch(property.type) {
default:
initCalendar(container, property);
break;
case "month":
initMonth(container, property);
break;
}
}
const generateCalendar = (container, property, date) => {
const ul = container.querySelector('.calendar-con') ? container.querySelector('.calendar-con') : document.createElement('ul');
if(ul.classList.contains('calendar-con')) {
ul.innerHTML = '';
} else {
ul.classList.add('calendar-con');
container.append(ul);
}
const today = new Date();
const ny = today.getFullYear(), nm = today.getMonth(), nd = today.getDate();
const cYear = date.getFullYear();
const cMonth = date.getMonth();
const lastDate = new Date(cYear, cMonth + 1, 0).getDate();
const startDay = new Date(cYear, cMonth, 1).getDay();
const beforeLastDate = new Date(cYear, cMonth, 0).getDate();
const selectedDate = property.value ? new Date(property.value) : null;
const selectedDateStr = selectedDate ? `${selectedDate.getFullYear()}-${selectedDate.getMonth().toString().padStart(2, '0')}-${selectedDate.getDate().toString().padStart(2, '0')}` : '';
const genDateLi = (date) => {
const li = document.createElement('li');
const dateNm = document.createElement('button');
dateNm.type = "button";
dateNm.textContent = new Date(date).getDate();
li.appendChild(dateNm);
dateNm.dataset.date = `${date.getFullYear()}-${date.getMonth().toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
return li;
}
// 이전달 날짜
for (let k = 0; k < startDay; k++) {
const date = new Date(cYear, cMonth-1, beforeLastDate - startDay + 1 + k);
const li = genDateLi(date);
ul.appendChild(li);
li.classList.add('before');
}
// 이번달 날짜 표시
for (let i = 0; i < lastDate; i++) {
const date = new Date(cYear, cMonth, i+1);
const li = genDateLi(date);
ul.appendChild(li);
if (selectedDate && selectedDateStr == li.querySelector('button').dataset.date) {
li.classList.add('selected');
} else if(!selectedDate) {
if (ny == cYear && nm == cMonth && nd == i + 1) {
li.classList.add('today');
} else if (nd == i + 1) {
li.classList.add('sameday');
}
}
}
// 다음달 날짜 표시
const leftAfterDates = 42 - ul.querySelectorAll('li').length;
for (let j = 0; j < leftAfterDates; j++){
const date = new Date(cYear, cMonth + 1, j+1);
const li = genDateLi(date);
ul.appendChild(li);
li.classList.add('after');
}
return ul;
}
const initCalendar = (container, property) => {
const valueDate = isValidDate(new Date(property.value)) ? new Date(property.value) : new Date();
const ymNavCon = document.createElement('div');
ymNavCon.classList.add('ym-nav-con');
container.append(ymNavCon);
const ymSelector = document.createElement('input');
ymSelector.type = 'month';
ymSelector.value = `${valueDate.getFullYear()}-${(valueDate.getMonth()+1).toString().padStart(2, '0')}`;
ymSelector.classList.add('custom-datepicker');
ymSelector.onchange = event => {
console.log('onchange', event.target);
generateCalendar(container, property, new Date(ymSelector.value));
}
ymSelector.onclick = event => datePicker(event);
ymNavCon.append(ymSelector);
const ymPrev = document.createElement('button');
ymPrev.type = "button";
ymPrev.textContent = "이전";
ymPrev.classList.add('btn','prev', 'ico-pv', 'icon-only');
ymNavCon.prepend(ymPrev);
ymPrev.onclick = () => ymNav();
const ymNext = document.createElement('button');
ymNext.type = "button";
ymNext.textContent = "다음";
ymNext.classList.add('btn','next', 'ico-fw', 'icon-only');
ymNavCon.append(ymNext);
ymNext.onclick = () => ymNav();
const ul = generateCalendar(container, property, new Date(ymSelector.value));
}
const ymNav = () => {
const ymInput = event.target.parentElement.querySelector('input');
const now = new Date(ymInput.value);
if(event.target.classList.contains('prev')) {
now.setMonth(now.getMonth() - 1);
} else {
now.setMonth(now.getMonth() + 1);
}
ymInput.value = `${now.getFullYear()}-${(now.getMonth()+1).toString().padStart(2, '0')}`;
ymInput.dispatchEvent(new Event('change'));
}
const initMonth = (container, property) => {
console.log(container, property);
}
document.querySelectorAll('input[type=date], input[type=time], input[type=month], input[type=week], input[type=datetime-local]').forEach(el => {
el.onchange = () => {
if(el.value == '') {
el.removeAttribute('value');
} else {
el.setAttribute('value',el.value);
}
}
});
document.querySelectorAll('input.custom-datepicker').forEach(el => {
el.onclick = (event) => {
datePicker(event);
}
});
// document.querySelectorAll('.custom-datepicker:not(input)').forEach(el => {
// initDataPicker(el);
// })