어느덧 흘러 흘러 jquery & HTML & css & javascript 까지 오게 되었다.
자 달력은
www.youtube.com/watch?v=FBO_7H39tqs
이거 개발자의 품격님의 유튜브와
Datepicker란 jquery의 내장 기능과
각종 인터넷을 참고하였다
밑밥 : 만들기에 급급했습니다.
실행 화면:
우선 실행하기 .
옵션은 대충 저런식으로 하고 넣지 않아도 됨. datepicker를 참고하여 만듬
$(document).ready(function(){
option = {
firstDay: 0, //0 : sunday시작 , 1: monday 시작
showWeek: true, // 몇 번째 주인지 나옴
weekHeader: '#',
monthNames: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
value: '2021-W09', // 처음 기본 값
displayTemplate: function(weekName, firstDate, lastDate) { //어떻게 표시할지 사용자가 지정 가능
let format = 'yyyy/MM/dd'
startPoint = formatDate(firstDate, format)
endPoint = formatDate(lastDate, format)
return startPoint+'~'+ endPoint ;
}
};
$("#date").Weekpicker(option)
첫번째, 위와 같이 호출이 되면 실행이 될 제이쿼리 함수.
let exWPs = []; exWPID = 0; exWPset = {};
$.fn.Weekpicker = function (option) {
let current_year = (new Date()).getFullYear(); // 현재 년도
let current_month = (new Date()).getMonth(); // 현재 달
let id = new Date().getMilliseconds() + new Date().getMinutes(); //유니크하진 않지만 랜더 되었을 때 identity를 관리 가능
let fixedOption = _customSetting(option) //Option이 들어온다면 갈무리함.기본 값 추가
$(this).parent().append(_htmlGenerate(id, fixedOption)).trigger("create"); // 이 함수가 실행 된 부모에 달력을 넣음/형제가 되는 것임
$("#yearChange" + id).val(current_year); // 현재 년월을 기본 값으로 세팅
$("#monthChange" + id).val(current_month);
changeYearMonth(current_year, current_month, id, fixedOption.showWeek, fixedOption.firstDay);
// 본격적으로 달력을 랜더하기 위한 함수 실행
$(this).addClass('ex-weekpicker ex-weekpicker-input '+id).attr("onclick","showWeekPicker("+id+")")
// 이 기능이 추가된 요소를 클릭하면 달력이 펴지게 지정
$(window).on('click', function (e) {
if ($(e.target).hasClass('ex-weekpicker') ||
$(e.target).parent().hasClass('ex-weekpicker') ||
$(e.target).parent().parent().hasClass('ex-weekpicker') ||
$(e.target).parent().parent().parent().hasClass('ex-weekpicker') ||
$(e.target).parent().parent().parent().parent().hasClass('ex-weekpicker')||
$(e.target).parent().parent().parent().parent().parent().hasClass('ex-weekpicker'))return;
exCloseWeekPicker();
});
// 다른 곳을 클릭할 때 달력이 접힘.
exWPset[id]=""
console.log(exWPset)
//위 2줄은 현재 진행중인 set기능 추가를 위한 것 무시
// 휠 스크롤로 위 아래 다른 달로 이동
$("#ex-weekpicker-" + id).on("mousewheel", function(e){
let E = e.originalEvent;
let deltaY = E.wheelDelta
let direction = Math.round(deltaY/120)
y = Number($("#yearChange" + id).val());
m = Number($("#monthChange" + id).val());
if (direction > 0){
m = m + 1
if (m == 12){
y = y + 1
m = 0
}
} else if(direction < 0){
m = m - 1
if (m === -1){
y = y - 1
m = 11
}
}
$("#yearChange" + id).val(y);
$('#monthChange' + id).val(m);
changeYearMonth(y, m, id, fixedOption.showWeek, fixedOption.firstDay)
})
}
참 멋스럽지 않은 코드이다. jquery로써 호출만 된다면 여기서 부터 시작이 된다. 먼저 실행이 되면 위에서부터 읽으니까 순서대로 코드를 나열하겠다.
두번째, 맨 처음 넣은 option이 정리 되는 함수. 이 함수를 통과하면 fixedOption으로 관리됨.(변수명 센스 부족)
function _customSetting(option) {
let monthNames = {0: "JAN", 1: "FEB", 2: "MAR", 3: "APR", 4: "MAY", 5: "JUN",
6: "JUL", 7: "AUG", 8: "SEP", 9: "OCT", 10: "NOV", 11: "DEC" };//default
let dayNames = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"] //default
let sunday = ""
if (!option.monthNames) {
option.monthNames = monthNames
}
if (option.dayNames){dayNames = option.dayNames}else{option.dayNames = dayNames}
if (option.firstDay == 1){
sunday = dayNames.shift();
dayNames.push(sunday)
option.dayNames = dayNames
}
return option
}
Option에 값이 들어오지 않을 경우 기본값을 세팅해주고 들어올 경우 그걸로 해주고 하는 것.
세번째, 메인입니다. html를 쫘악 깔고 순서를 정리하는 곳
function _htmlGenerate(id, option) {
let prevText = "Prev";
let nextText = "Next";
let dpDiv = $("<div/>", {
id: "ex-weekpicker-"+id,
style: 'display:none;border:5px ridge;z-index:9999;float:none;position:absolute;',
}).addClass('ex-weekpicker ex-weekpicker-ui-weekpicker');
let prev, monthOption, next, yearInput, todayButton, selectFormat
prev = $('<button/>', {
type: 'button',
value: prevText,
id: 'prevButton' + id,
class: 'ex-weekpicker-controlButton-left',
}).attr('onclick', 'changeMonth(-1,' + id + ', ' + option.showWeek + ', ' + option.firstDay + ')').append($('<i />', {
class: 'ex-weekpicker fas fa-chevron-left',
}));
monthOption = $('<select />', {
id: "monthChange" + id,
class: "ex-weekpicker-form-controller ex-weekpicker-controlButton",
}).attr('onchange', 'changeMonth(0,' + id + ', ' + option.showWeek + ', ' + option.firstDay + ')');
next = $('<button/>', {
type: "button",
value: nextText,
id: 'nextButton' + id,
class: "ex-weekpicker-controlButton-right"
}).attr('onclick', 'changeMonth(1,' + id + ',' + option.showWeek + ', ' + option.firstDay + ')').append($('<i/>', {
class: 'ex-weekpicker fas fa-chevron-right',
}));
yearInput = $('<input />', {
type: "text",
id: "yearChange" + id,
class: "ex-weekpicker-yearchange"
}).attr('onchange', 'changeYear(' + id + ', ' + option.showWeek + ', ' + option.firstDay + ')');
// todayButton = $('<button>This month</button>', {
// type: 'button',
// value: 'goToday',
// id: 'todayFindButton',
// class: 'ex-weekpicker-form-control',
// style: 'float:right;',
// }).attr('onclick', 'goToToday(' + id + ', ' + option.showWeek + ', ' + option.firstDay + ')').append($('<i/>', {
// class: 'ex-weekpicker fa fa-calendar',
// value: 'Today',
// }));
selectFormat = $('<select />', {
id: "formatOption"+id,
})
.append("<option value='YYYY-WW'>YYYY-WW</option>")
.append("<option value='MM/DD/YYYY~MM/DD/YYYY'>MM/DD/YYYY~MM/DD/YYYY</option>");
for (let i = 0; i < 12; i++) {
monthOption.append("<option value=" + i + ">" + option.monthNames[i] + "</option>")
};
format = $('<p>Format:</p>',{
style:'font-size:20px;'
});
controlPanel = $('<div>',{
id:"ex-weekpicker-controlpanel"+id,
class:"ex-weekpicker-controlpanel",
});
format.append(selectFormat);
controlPanel.append(prev);
controlPanel.append(yearInput);
controlPanel.append(monthOption);
controlPanel.append(next);
dpDiv.append(controlPanel)
//dpDiv.append(todayButton);
// dpDiv.append(format);
weekDay = $('<table />', {
class: "ex-weekpicker table table-borderd"
})
let tableRow = $('<tr />', { id: "table-head-day",class:"ex-weekpicker" });
let tableHead = $('<thead />',{class:"ex-weekpicker"});
if (option.showWeek) {
if (option.weekHeader) {
$('<td>' + option.weekHeader + '</td>').appendTo(tableRow)
for (let a = 0; a < option.dayNames.length; a++) {
$('<td>' + option.dayNames[a] + '</td>').appendTo(tableRow)
}
} else {
$('<td>#</td>').appendTo(tableRow)
for (let a = 0; a < option.dayNames.length; a++) {
$('<td>' + option.dayNames[a] + '</td>').appendTo(tableRow)
}
}
} else {
for (let a = 0; a < option.dayNames.length; a++) {
$('<td>' + option.dayNames[a] + '</td>').appendTo(tableRow)
}
}
tableHead.append(tableRow);
weekDay.append(tableHead);
weekDay.append($('<tbody />', { id: "tb_body" + id , class:"ex-weekpicker"}));
dpDiv.append(weekDay);
let warper = $('<div />', { id: "warper"+id, class:"ex-weekpicker" }).append(dpDiv);
if(!exWPs.includes(id)){exWPs.push(id)}
return warper;
}
이제부터 함수 여러개 // 윤년 체크하는 것들 부터 주의 첫번째 날 구하는 것// 다 유튜브 개발자의 품격 출처
여기서 내가 add 한 것은 거기 유튜브에서는 이번달을 뽑는 것이였는데 나는 빈칸에 전달의 날짜가 나오게 하는 것을 했다.
그러니까 1월 1일이 금요일인데 그 앞에 '월화수목'이 비어 있는 것이 아니라 12월 27일 28일 29일 30일 31일이 채워져있는 것을 말한다.
function changeYearMonth(year, month, id, showWeek, firstDay) {
let month_day = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if (month == 1) {
if (checkLeapYear(year)) month_day[1] == 29;
}
let first_day_of_week = getFirstDayOfWeek(year, month, firstDay);
let arr_calendar = [];
//전 달의 끝 날짜를 집어 넣는 작업
for (let i = (month == 0 ? month_day[month_day.length - 1] : month_day[month - 1]) - first_day_of_week + 1 ; i <= (month == 0 ? month_day[month_day.length - 1] : month_day[month - 1]); i++) {
arr_calendar.push(String(i));
};
for (let i = 1; i <= month_day[month]; i++) {
arr_calendar.push(String(i));
};
let remain_day = 7 - (arr_calendar.length % 7);
//이 달 끝에 다음 달의 앞 날짜를 당겨오는 작업
if (remain_day < 7) {
for (let i = 0; i < remain_day; i++) {
arr_calendar.push(String(i + 1))
}
};
renderCalendar(arr_calendar, id, showWeek);
}
function renderCalendar(data, id, showWeek) {
let h = [];
for (let i = 0; i < data.length; i++) {
let nthWeek = Math.floor(i / 7)+1;
if (i == 0) {
if (showWeek) {
h.push('<tr name="'+nthWeek+'thweek'+id+'" onclick="getWeekNumber(' + nthWeek + ',' + id + ');" class="ex-weekpicker-weekSelect">');
h.push('<td name="week" style="cursor:pointer;">' + nthWeekOfYear(nthWeek, id) + '</td>');
} else {
h.push('<tr name="'+nthWeek+'thweek'+id+'" onclick="getWeekNumber(' + nthWeek + ',' + id + ');" class="ex-weekpicker-weekSelect">');
}
} else if (i % 7 == 0) {
if (showWeek) {
h.push('</tr>');
h.push('<tr name="'+nthWeek+'thweek'+id+'" onclick="getWeekNumber(' + nthWeek + ',' + id + ');" class="ex-weekpicker-weekSelect">');
h.push('<td name="week" style="cursor:pointer;">' + nthWeekOfYear(nthWeek, id) + '</td>');
} else {
h.push('</tr>');
h.push('<tr name="'+nthWeek+'thweek'+id+'" onclick="getWeekNumber(' + nthWeek + ',' + id + ');" class="ex-weekpicker-weekSelect">');
}
}
h.push('<td name="day" style="cursor:pointer;" id="'+ data[i] +'">' + data[i] + '</td>');
};
h.push('</tr>');
$('#tb_body' + id).html(h.join("")).trigger("create");
}
function checkLeapYear(year) {
if (year % 400 == 0) {
return true;
} else if (year % 100 == 0) {
return false;
} else if (year % 4 == 0) {
return true;
} else {
return false;
}
}
function getFirstDayOfWeek(year, month, firstDay) {
month += 1
if (month < 10) month = "0" + month;
if (firstDay == 1) {
if (Number((new Date(month + "-01-" + year)).getDay()) == 0) {
return 6
} else {
return (new Date(month + "-01-" + year)).getDay() - 1
}
}
return (new Date(month + "-01-" + year)).getDay();
}
여기까지 htmlgenerate된 html에 changeYearMonth로 하나의 리스트를 만들어서 rendercalendar에 넣어 html에 차례대로 넣는 작업이다.
여기까지가 실행이다. 이제 버튼을 누를때 등 이벤트에 관련된 함수들을 나열하겠다.
onclick에 배정이 되어 있는 함수이다. 월을 바꾸던 년을 바꾸던 loadCalendar로 가서 또다시 changeYearMonth로 간다.
function changeMonth(diff, id, showWeek, firstDay) {
if (diff == 0) {
this.year = Number($("#yearChange" + id).val())
this.month = Number($("#monthChange" + id).val())
} else {
this.year = Number($("#yearChange" + id).val())
this.month = Number($("#monthChange" + id).val())
this.month = this.month + Number(diff);
if (this.month == -1) {
this.year = this.year - 1;
this.month = 11;
} else if (this.month == 12) {
this.year = this.year + 1;
this.month = 0;
}
}
loadCalendar(id, showWeek, firstDay);
}
function changeYear(id, showWeek, firstDay) {
this.year = Number($("#yearChange" + id).val())
this.month = Number($("#monthChange" + id).val())
loadCalendar(id, showWeek, firstDay);
}
function loadCalendar(id, showWeek, firstDay) {
$("#yearChange" + id).val(this.year);
$('#monthChange' + id).val(this.month);
changeYearMonth(this.year, this.month, id, showWeek, firstDay)
}
그리고 몇주차인지 계산하는 함수를 넣겠다. 사실 몇주차인지 계산하는게 없어서 내가 만들었다.
원래 getWeekNumber에서 최종 input에 표시된다. 그래서 여기서 form에 대한 설정을 받아 처리했는데 그냥 콜백함수로 사용자가 지정할 수 있도록 하였다.
function getWeekNumber(nthWeek, id) {
let yearValue = $('#yearChange'+ id).val()
//let selectedFormat = $("#formatOption"+ id).val()
let findInputElement = $("."+id)
weekDuration = formattingDate(nthWeek, id, yearValue)
startdate = new Date(weekDuration[0])
enddate = new Date(weekDuration[1])
if (option.displayTemplate) {
let displayText = option.displayTemplate(
nthWeekOfYear(nthWeek, id),
startdate,
enddate);
$(findInputElement).val(displayText);
$("#ex-weekpicker-" + id).toggle()
}
else{
$(findInputElement).val(yearValue+"-W"+nthWeekOfYear(nthWeek, id) )
$("#ex-weekpicker-" + id).toggle()
}
}
function nthWeekOfYear(nthWeek, id) {
year = $("#yearChange" + id).val()
month = Number($("#monthChange" + id).val()) + 1;
let first_day = new Date("01-" + (7 - (new Date("01-01-" + year).getDay()) + 1) + "-" + year)
let day_gap = (new Date(month + "-01-" + year) - first_day) / 1000 / 60 / 60 / 24;
var nthWeekOfThisYear = Math.ceil(((day_gap + 1) / 7) + nthWeek)
if(month==12){
if(nthWeekOfThisYear>=53){
if($(this).children("td #1")){
return 1
}
}
}
return nthWeekOfThisYear
}
여기까지 기능적인 부분이였고 눌렀을 때 없어지고 생기고 하는 것들 함수 보이겠다.
function exCloseWeekPicker(){
for(x = 0 ; x<exWPs.length ; x++){
$("#ex-weekpicker-"+exWPs[x]).hide();
}
}
//아이디 관리를 하는 exWPs에서 있나없나 검사하고 있으면 싹다 닫게
function showWeekPicker(id){
$("#ex-weekpicker-" + id).toggle()
}
$(document).keyup(function (e) {
if (e.key === "Escape") { // escape key maps to keycode `27`
exCloseWeekPicker();
}
});
$(window).on('click', function (e) {
if ($(e.target).hasClass('ex-weekpicker') ||
$(e.target).parent().hasClass('ex-weekpicker') ||
$(e.target).parent().parent().hasClass('ex-weekpicker') ||
$(e.target).parent().parent().parent().hasClass('ex-weekpicker') ||
$(e.target).parent().parent().parent().parent().hasClass('ex-weekpicker')||
$(e.target).parent().parent().parent().parent().parent().hasClass('ex-weekpicker'))return;
exCloseWeekPicker();
});
그럼 여기까지 !
'Library > jQeury' 카테고리의 다른 글
jquery/Javascript DatePicker를 보고 만든 WeekPicker(3) - 마무리 (0) | 2021.06.11 |
---|---|
jquery/Javascript DatePicker를 보고 만든 WeekPicker(2) (0) | 2021.04.15 |
jQuery - jQuery AJAX를 사용하여 Json 데이터 불러오기 (0) | 2021.02.25 |
jQuery - 스크롤 이벤트 Scroll event (0) | 2021.02.24 |
jQuery - preventdefault (0) | 2021.02.24 |