PageSourceSearch

https://nosmokeguide.go.kr/resources/js/mlc_calendar.js

js nosmokeguide.go.kr collected 2026-09-24 09:48:44 UTC 15,825 bytes, 365 lines download raw bytes

1"use strict";
2
3class MLcCalendar {
4    CALENDAR_TYPE = "calendar-type";
5    LIST_TYPE = "list-type";
6    SEARCH_TYPE = "search-type";
7    TITLE_FORMAT = "yyyy년 mm월";
8
9    calendarEl = null;
10    monthEl = null;
11    monthPickerEl = null;
12    calendarType = null;
13    month = null;
14    mobile = false;
15
16    constructor(selector, type, month, mobile) {
17        this.calendarEl = document.querySelector(selector);
18        this.calendarType = type;
19
20        this.monthEl = this.calendarEl.querySelector(".month-switch .calendar-month");
21        if (this.monthEl) this.monthEl.dataset.format = this.TITLE_FORMAT;
22
23        if (type !== this.SEARCH_TYPE) {
24            this.month = month || moment().format("YYYY-MM");
25            this.mobile = mobile;
26
27            this._changeCalendarType(this.calendarType);
28            this._initMonthPicker();
29
30            this._setMonthEl();
31            this._drawCalendar();
32        } else {
33            this._drawCalendar();
34        }
35    }
36
37    /**
38     * 날짜별 데이터 출력
39     * @param {*} json - { dDay, data }
40     */
41    setData = (json) => {
42        this._clearDateCell();
43
44        // dDay값이 있고, dDay 월이 조회하려는 월(this.month) 비고하여 showDDay() 실행
45        // ex) dDay 월이 2024-08일때, 조회하려는 월이 2024-07부터만 showDDay() 실행
46        // if (json.dDay) {
47        //     this.showDDay(json.dDay);
48        // }
49
50        let noDataEl = this.calendarEl.querySelector(".no-data");
51
52        if (json.data && Object.keys(json.data).length !== 0) {
53            let dateItem;
54            json.data.forEach((item, i) => {
55                dateItem = this.calendarEl.querySelector(`[data-date="${item.date}"]`);
56
57                dateItem.classList.remove("empty");
58                dateItem.querySelector(".level").innerHTML = item.qsLevelLabel;
59                dateItem.querySelector(".level").classList.add("level-" + item.qsLevel);
60                dateItem.querySelector(".title").innerHTML = item.title ?? '';
61                dateItem.querySelector(".text").innerHTML = item.text ?? '';
62
63                // diaryNo를 id로 추가
64                dateItem.setAttribute("data-diary-id", item.id);
65            });
66
67            this.showDDay(json.data);
68            if (noDataEl) noDataEl.classList.add("d-none");
69            return Object.keys(json.data).length;
70        } else {
71            if (noDataEl) noDataEl.classList.remove("d-none");
72            return 0;
73        }
74    };
75
76    /**
77     * 검색결과 데이터 출력
78     * @param {*} json
79     */
80    setDataSearch = (json) => {
81        this._clearDateCell();
82
83        // if (json.dDay) {
84        //    this.showDDay(json.dDay);
85        // }
86
87        let noDataEl = this.calendarEl.querySelector(".no-data");
88
89        if (json.data && Object.keys(json.data).length !== 0) {
90            let html = "";
91
92            json.data.forEach((item, i) => {
93                html += this._htmlDateItemSearch(item);
94            });
95
96            this.calendarEl.querySelector("ul.date-list").innerHTML = html;
97            this.calendarEl.querySelector(".no-data")?.classList.add("d-none");
98            this.showDDay(json.data);
99
100            if (noDataEl) noDataEl.classList.add("d-none");
101            return Object.keys(json.data).length;
102        } else {
103            if (noDataEl) noDataEl.classList.remove("d-none");
104            return 0;
105        }
106    };
107
108    /**
109     * 수신한 데이터 없을때
110     */
111    noData = () => {
112        console.log("noData");
113        this.calendarEl.querySelector(".no-data")?.classList.remove("d-none");
114    };
115
116    // D-Day(금연시작일로 부터 n일차) 출력
117    showDDay = (diaryList) => {
118        // diaryList 데이터를 객체로 변환 (key: diaryDate, value: dDayText)
119        const diaryMap = diaryList.reduce((map, diary) => {
120            const dateKey = diary.date;
121            map[dateKey] = diary.dDay; // 날짜별로 dDayText 매핑
122            return map;
123        }, {});
124
125        // 모든 .date-item 요소를 가져오기
126        const dateItems = this.calendarEl.querySelectorAll(".date-item");
127
128        // dateItems 순회
129        dateItems.forEach((dateEl) => {
130            const dateValue = dateEl.getAttribute("data-date")?.trim();
131
132            // diaryMap에서 일치하는 dDayText 찾기
133            const dDayText = diaryMap[dateValue];
134
135            if (dDayText && dDayText !== "D+0") {
136                // .d-day 요소에 dDayText 값 설정
137                const dDayEl = dateEl.querySelector(".d-day");
138                if (dDayEl) {
139                    dDayEl.innerHTML = dDayText;
140                    dDayEl.classList.remove("d-none");
141                }
142            }
143        });
144    };
145
146    getMonth = () => this.month;
147    setMonth = (date, add) => {
148        if (add) {
149            this.month = moment(date).add(add, "month").format("YYYY-MM");
150        } else {
151            this.month = moment(date).format("YYYY-MM");
152        }
153        console.log("setMonth() : ", this.month);
154
155        this._setMonthEl();
156        this._drawCalendar();
157
158        this.triggerEvent("changeMonth", this.month);
159    };
160
161    // calendar/list type 버튼 클릭 처리
162    changeType = (calendarTypeString) => {
163        this._changeCalendarType(calendarTypeString);
164    };
165
166    // 이전달로 이동
167    prevMonth = () => {
168        this.setMonth(this.month, -1);
169    };
170
171    // 다음달로 이동
172    nextMonth = () => {
173        this.setMonth(this.month, 1);
174    };
175
176    // 연도/월 선택용 ddatepicker 설정
177    _initMonthPicker = () => {
178        if (this.calendarType !== "search-type") {
179            this.monthPickerEl = mlc_comps.datePicker.findItem(".calendar-month");
180            // console.log( this.monthPickerEl )
181
182            this.monthPickerEl.bs_datepicker({ format: "yyyy년 mm월" }); // not working??
183
184            // 달력 변경 이벤트 처리
185            this.monthPickerEl.bs_datepicker().on("changeMonth", (event) => this.setMonth(event.date));
186            this.monthPickerEl.bs_datepicker().on("show", (event) => this._setDatepickerOrient(event));
187        }
188    };
189
190    _setDatepickerOrient = (event) => {
191        if (event.target.dataset.orient) $(".datepicker").addClass("datepicker-orient-" + event.target.dataset.orient);
192    };
193
194    // .month에 연월 값 출력, monthPicker에 setDate()
195    _setMonthEl = (date) => {
196        // console.log( "_setMonthEl() : ", date )
197        this.monthEl.value = moment(date || this.month).format(this.TITLE_FORMAT.toUpperCase());
198        this.monthPickerEl.bs_datepicker("setDate", date || this.month);
199    };
200
201    // calendar의 형태 변경, ~형보기 버튼 UI 변경
202    _changeCalendarType = (calendarTypeString) => {
203        this.calendarEl.classList.remove(this.LIST_TYPE, this.CALENDAR_TYPE, this.SEARCH_TYPE);
204        this.calendarEl.classList.add(calendarTypeString);
205
206        const changeCalendarTypeButton = this.calendarEl.querySelector(".btn-calendar-type");
207        if (!changeCalendarTypeButton) return;
208
209        if (calendarTypeString === this.CALENDAR_TYPE) {
210            changeCalendarTypeButton.querySelector("svg").innerHTML =
211                '<path d="M8.62222 6.4H20M8.62222 12H20M8.62222 17.6H20M4.35556 6.4H4.36219V6.40853H4.35556V6.4ZM4.71111 6.4C4.71111 6.50609 4.67365 6.60783 4.60697 6.68284C4.54029 6.75786 4.44985 6.8 4.35556 6.8C4.26126 6.8 4.17082 6.75786 4.10414 6.68284C4.03746 6.60783 4 6.50609 4 6.4C4 6.29391 4.03746 6.19217 4.10414 6.11716C4.17082 6.04214 4.26126 6 4.35556 6C4.44985 6 4.54029 6.04214 4.60697 6.11716C4.67365 6.19217 4.71111 6.29391 4.71111 6.4ZM4.35556 12H4.36219V12.0085H4.35556V12ZM4.71111 12C4.71111 12.1061 4.67365 12.2078 4.60697 12.2828C4.54029 12.3579 4.44985 12.4 4.35556 12.4C4.26126 12.4 4.17082 12.3579 4.10414 12.2828C4.03746 12.2078 4 12.1061 4 12C4 11.8939 4.03746 11.7922 4.10414 11.7172C4.17082 11.6421 4.26126 11.6 4.35556 11.6C4.44985 11.6 4.54029 11.6421 4.60697 11.7172C4.67365 11.7922 4.71111 11.8939 4.71111 12ZM4.35556 17.6H4.36219V17.6085H4.35556V17.6ZM4.71111 17.6C4.71111 17.7061 4.67365 17.8078 4.60697 17.8828C4.54029 17.9579 4.44985 18 4.35556 18C4.26126 18 4.17082 17.9579 4.10414 17.8828C4.03746 17.8078 4 17.7061 4 17.6C4 17.4939 4.03746 17.3922 4.10414 17.3172C4.17082 17.2421 4.26126 17.2 4.35556 17.2C4.44985 17.2 4.54029 17.2421 4.60697 17.3172C4.67365 17.3922 4.71111 17.4939 4.71111 17.6Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>';
212            changeCalendarTypeButton.querySelector("span").innerHTML = this.mobile ? "목록보기" : "목록형 보기";
213            changeCalendarTypeButton.dataset.type = this.LIST_TYPE;
214        } else {
215            changeCalendarTypeButton.querySelector("svg").innerHTML =
216                '<path d="M7.33333 4V6M16.6667 4V6M4 18V8C4 7.46957 4.21071 6.96086 4.58579 6.58579C4.96086 6.21071 5.46957 6 6 6H18C18.5304 6 19.0391 6.21071 19.4142 6.58579C19.7893 6.96086 20 7.46957 20 8V18M4 18C4 18.5304 4.21071 19.0391 4.58579 19.4142C4.96086 19.7893 5.46957 20 6 20H18C18.5304 20 19.0391 19.7893 19.4142 19.4142C19.7893 19.0391 20 18.5304 20 18M4 18V11.3333C4 10.8029 4.21071 10.2942 4.58579 9.91912C4.96086 9.54405 5.46957 9.33333 6 9.33333H18C18.5304 9.33333 19.0391 9.54405 19.4142 9.91912C19.7893 10.2942 20 10.8029 20 11.3333V18M12 12.6667H12.0071V12.6738H12V12.6667ZM12 14.6667H12.0071V14.6738H12V14.6667ZM12 16.6667H12.0071V16.6738H12V16.6667ZM10 14.6667H10.0071V14.6738H10V14.6667ZM10 16.6667H10.0071V16.6738H10V16.6667ZM8 14.6667H8.00711V14.6738H8V14.6667ZM8 16.6667H8.00711V16.6738H8V16.6667ZM14 12.6667H14.0071V12.6738H14V12.6667ZM14 14.6667H14.0071V14.6738H14V14.6667ZM14 16.6667H14.0071V16.6738H14V16.6667ZM16 12.6667H16.0071V12.6738H16V12.6667ZM16 14.6667H16.0071V14.6738H16V14.6667Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>';
217            changeCalendarTypeButton.querySelector("span").innerHTML = this.mobile ? "달력보기" : "달력형 보기";
218            changeCalendarTypeButton.dataset.type = this.CALENDAR_TYPE;
219        }
220    };
221
222    _clearDateCell = () => {
223        let dateItems = this.calendarEl.querySelectorAll(".date-item");
224        dateItems.forEach((dateItem, i) => {
225            dateItem.classList.add("empty");
226            dateItem.querySelector(".d-day").innerHTML = "";
227            dateItem.querySelector(".d-day").classList.add("d-none");
228            dateItem.querySelector(".level").innerHTML = "";
229            dateItem.querySelector(".level").classList.remove("level-1", "level-2", "level-3", "level-4", "level-5");
230            dateItem.querySelector(".title").innerHTML = "";
231            dateItem.querySelector(".text").innerHTML = "";
232        });
233    };
234
235    _drawCalendar = () => {
236        const weekdayStart = 0;
237        const weekdayEnd = 6;
238        let calDate = new Date(this.month); // this.month format은 항상 "YYYY-MM"이어야 함.
239        let thisY = calDate.getFullYear(),
240            thisM = calDate.getMonth();
241        let thisDay1 = calDate.getDay(); // thisDay_1 : 이달 1일의 요일번호. 0이 일요일
242        let dateTemp = new Date(thisY, thisM + 1, 0); // 이달의 마지막날
243        let thisDL = dateTemp.getDate(); // 이달의 마지막날
244        let thisDayL = dateTemp.getDay(); // 이달의 마지말날 요일. 6이 토요일 (다음달을 그릴지 여부 확인용)
245
246        let html = "";
247
248        // 이달 1일의 요일이 weekdayStart(0)이 아니면 이전달 정보 필요
249        if (thisDay1 !== weekdayStart) {
250            let prevY = thisY;
251            let prevM = thisM - 1;
252            if (prevM <= -1) {
253                prevM = 11;
254                prevY--;
255            }
256            let dateTemp = new Date(prevY, prevM + 1, 0);
257            let prevDL = dateTemp.getDate();
258            html += this._renderMonth("next", prevY, prevM, prevDL - (thisDay1 - 1), prevDL, weekdayStart);
259        }
260
261        // 이달 셀 생성
262        html += this._renderMonth("this", thisY, thisM, 1, thisDL, thisDay1);
263
264        // 이달 말일의 요일이 weekdayEnd(6)이 아니면 다음달 정보 필요
265        if (thisDayL !== weekdayEnd) {
266            let nextY = thisY;
267            let nextM = thisM + 1;
268            if (nextM >= 12) {
269                nextM = 1;
270                nextY++;
271            }
272            html += this._renderMonth("next", nextY, nextM, 1, weekdayEnd - thisDayL, thisDayL + 1);
273        }
274
275        this.calendarEl.querySelector("ul.date-list").innerHTML = html;
276    };
277
278    /**
279     * @param {*} className - this/prev/next = 이달/전달/다음달
280     * @param {*} thisY - 연도
281     * @param {*} thisM - 월 - 1
282     * @param {*} startD - 시작일
283     * @param {*} endD - 마지막일
284     * @param {*} startWD - 시작일의 요일
285     */
286    _renderMonth = (className, thisY, thisM, startD, endD, startWD) => {
287        let html = "";
288        let weekday = startWD;
289
290        for (let d = startD; d <= endD; d++) {
291            html += this._htmlDateItem(className, d, weekday, moment(new Date(thisY, thisM, d)).format("YYYY-MM-DD"));
292            if (weekday++ >= 6) weekday = 0;
293        }
294
295        return html;
296    };
297
298    /**
299     * .date-item html 생성
300     * @param { String } className - this/prev/next = 이달/전달/다음달
301     * @param { Number } day - 1~31
302     * @param { Number } weekday : 0 ~ 6
303     * @param { String } date : YYYY-MM-DD 포맷
304     * @returns html
305     */
306    _htmlDateItem = (className, day, weekday, date) => {
307        // const weekdays = [ '일', '월', '화', '수', '목', '금', '토' ]
308        const weekdays = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
309        let today = moment(new Date()).format("YYYY-MM-DD");
310        let tabindex = className === "this" ? 0 : -1;
311
312        return `
313<li class="date-item wd-${weekday} ${className} ${
314            today === date ? "today" : ""
315        } empty" data-date="${date}" tabindex="${tabindex}">
316    <div class="weekday">${weekdays[weekday]}</div>
317    <div class="day">${day}</div>
318    <div class="d-day d-none"></div>
319    <div class="level"></div>
320    <div class="title"></div>
321    <div class="text"></div>
322</li>
323`;
324    };
325
326    /**
327     * 검색결과용 .date-item html 생성
328     * @param { Object } item
329     * @returns html
330     */
331    _htmlDateItemSearch = (item) => {
332        const weekdays = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
333        let itemDate = new Date(item.date);
334        let weekday = itemDate.getDay();
335        let day = itemDate.getDate();
336        return `
337<li class="date-item wd-${weekday}" data-date="${item.date}" data-diary-id="${item.id}" tabindex="0">
338    <div class="weekday">${moment(itemDate).format("YYYY.MM")}</div>
339    <div class="day">${day}</div>
340    <div class="d-day d-none"></div>
341    <div class="level level-${item.qsLevel}">${item.qsLevelLabel}</div>
342    <div class="title">${item.title ?? ''}</div>
343    <div class="text">${item.text ?? ''}</div>
344</li>
345`;
346    };
347
348    // 이벤트 리스너 추가 함수
349    addEventListener = (eventName, callback) => {
350        if (!this.events) {
351            this.events = {};
352        }
353        if (!this.events[eventName]) {
354            this.events[eventName] = [];
355        }
356        this.events[eventName].push(callback);
357    };
358
359    // 이벤트 트리거 함수
360    triggerEvent = (eventName, data) => {
361        if (this.events && this.events[eventName]) {
362            this.events[eventName].forEach((callback) => callback(data));
363        }
364    };
365}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.