PageSourceSearch

https://www.step.or.kr/step/js/common.js?date=1790396611896

js step.or.kr collected 2026-09-26 04:24:48 UTC 58,808 bytes, 2,002 lines download raw bytes

1var windowCurrentUrl = "";
2$(function(){
3	windowCurrentUrl = window.top.location.href;
4});
5
6////// 언어 변경 수신용.
7window.addEventListener("message", function (event) {
8
9    // 동일 도메인이라면 origin 체크 생략 가능
10    if (!event.data || event.data.type !== "LANG_CHANGED") return;
11
12    const lang = event.data.lang;
13    applyLangCss(lang);
14});
15
16document.addEventListener("DOMContentLoaded", function () {
17    applyLangCss(getLangFromCookie());
18});
19
20function applyLangCss(lang) {
21    const normalizedLang = (lang || "ko").toLowerCase();
22
23    document.documentElement.setAttribute("lang", normalizedLang);
24
25    // 기존 언어 CSS 제거
26    document.querySelectorAll("link[data-lang-style]")
27        .forEach(el => el.remove());
28
29    const cssMap = {
30        en: "/step/css/lang/global_en.css",
31        ja: "/step/css/lang/global_ja.css",
32        es: "/step/css/lang/global_es.css",
33        fr: "/step/css/lang/global_fr.css",
34        de: "/step/css/lang/global_de.css", 
35        ne: "/step/css/lang/global_ne.css",
36        pt: "/step/css/lang/global_pt.css",
37        tet: "/step/css/lang/global_tet.css",
38        my: "/step/css/lang/global_my.css",
39        si: "/step/css/lang/global_si.css",
40        ta: "/step/css/lang/global_ta.css",
41        id: "/step/css/lang/global_id.css",
42        fil: "/step/css/lang/global_fil.css",
43        km: "/step/css/lang/global_km.css",
44        ur: "/step/css/lang/global_ur.css",
45        sd: "/step/css/lang/global_sd.css",
46        lo: "/step/css/lang/global_lo.css",
47        uz: "/step/css/lang/global_uz.css",
48        th: "/step/css/lang/global_th.css",
49        vi: "/step/css/lang/global_vi.css",
50        mn: "/step/css/lang/global_mn.css",
51        "zh-cn": "/step/css/lang/global_zh-cn.css",
52        "zh-tw": "/step/css/lang/global_zh-TW.css",
53        bn: "/step/css/lang/global_bn.css",
54        ky: "/step/css/lang/global_ky.css",
55        ru: "/step/css/lang/global_ru.css",
56        tg: "/step/css/lang/global_tg.css",
57        ms: "/step/css/lang/global_ms.css"
58    };
59
60    if(normalizedLang == "ko"){
61        return ;
62    }
63
64    const cssHref = cssMap[normalizedLang] ;
65    
66    const link = document.createElement("link");
67    link.rel = "stylesheet";
68    link.href = cssHref;
69    link.setAttribute("data-lang-style", normalizedLang);
70
71    document.head.appendChild(link);
72}
73
74function getLangFromCookie() {
75    const cookies = document.cookie.split("; ");
76    for (let cookie of cookies) {
77        if (cookie.startsWith("googtrans=")) {
78            const parts = cookie.split("=")[1].split("/");
79            if (parts.length === 3) {
80                return parts[2];
81            }
82        }
83    }
84    return "ko";
85}
86
87
88/**
89 * 공통 페이징 함수
90 * @param {number} totalCount - 전체 데이터 개수
91 * @param {Function} callback - 페이지 변경 시 실행할 함수
92 */
93function fnCommonPaging(totalCount, callback) {
94    let currPage = parseInt($("#p_pageno").val()) || 1;
95    let listCnt = parseInt($("#p_listscale").val()) || 9;
96    let naviCnt = 10;
97    
98    // 반응형 처리
99    if ($(window).width() < 510) {
100        naviCnt = 5;
101    }
102    
103    const totalPage = Math.ceil(totalCount / listCnt);
104    const currGroup = Math.floor(currPage / naviCnt) + ((currPage % naviCnt === 0) ? 0 : 1);
105    const startPage = currGroup * naviCnt - naviCnt + 1;
106    const endPage = Math.min(currGroup * naviCnt, totalPage);
107    
108    const firstPage = 1;
109    const prevPage = startPage - 1;
110    const nextPage = endPage + 1;
111    const lastPage = totalPage;
112    
113    const $area = $(".page_list").empty();
114    
115    
116   
117    // 처음으로
118    $('<a href="javascript:void(0);" class="p_first"><img src="/step/images/board/btn_first_bg.svg" alt="제일 처음으로"></a>')
119        .appendTo($area)
120        .click(function() {
121            if (totalCount > 0) {
122                $("#p_pageno").val(firstPage);
123                callback(firstPage);
124            }
125            return false;
126        });
127    
128    // 이전으로
129    $('<a href="javascript:void(0);" class="p_prev"><img src="/step/images/board/btn_prev_bg.svg" alt="이전으로"></a>')
130        .appendTo($area)
131        .click(function() {
132            if (firstPage <= prevPage) {
133                $("#p_pageno").val(prevPage);
134                callback(prevPage);
135            }
136            return false;
137        });
138    
139    // 페이지 번호
140    for (let i = startPage; i <= endPage; i++) {
141        (function(pageNum) {
142            if (pageNum === currPage) {
143                $('<strong class="ds_number">' + pageNum + '</strong>').appendTo($area);
144            } else {
145                $('<a class="ds_number" href="javascript:void(0);">' + pageNum + '</a>')
146                    .appendTo($area)
147                    .click(function() {
148                        $("#p_pageno").val(pageNum);
149                        callback(pageNum);
150                        return false;
151                    });
152            }
153        })(i);
154    }
155    
156    // 다음으로
157    $('<a href="javascript:void(0);" class="p_next"><img src="/step/images/board/btn_next_bg.svg" alt="다음으로"></a>')
158        .appendTo($area)
159        .click(function() {
160            if (lastPage >= nextPage) {
161                $("#p_pageno").val(nextPage);
162                callback(nextPage);
163            }
164            return false;
165        });
166    
167    // 마지막으로
168    $('<a href="javascript:void(0);" class="p_end"><img src="/step/images/board/btn_end_bg.svg" alt="제일마지막으로"></a>')
169        .appendTo($area)
170        .click(function() {
171            if (totalCount > 0) {
172                $("#p_pageno").val(lastPage);
173                callback(lastPage);
174            }
175            return false;
176        });
177        
178	top.window.scrollTo(0, 0);
179}
180
181function layout(arg) {
182
183    var SCOPE = this;
184
185    SCOPE.option = arg;
186
187    var Selector = SCOPE.option.selector;
188
189    /* nav 드롭다운 메뉴 */
190    var locateDropnMenuLen = $(Selector.locateDropnMenu).length;
191
192    for (var i = 0; i < locateDropnMenuLen; i++) {
193
194        var locateDropnMenu = $(Selector.locateDropnMenu).eq(i);
195
196        locateDropnMenu.attr({
197            'data-height': locateDropnMenu.outerHeight()
198        });
199    }
200
201    function outDropMenu() {
202
203        for (var j = 0; j < locateDropnMenuLen; j++) {
204
205            var locateDropnMenu = $(Selector.locateDropnMenu).eq(j);
206
207            if (locateDropnMenu.css('display') == 'block') {
208
209                locateDropnMenu
210                    .stop(0, 1).animate({
211                        'height': '0',
212                        'opacity': '0'
213                    }, 100, 'easeOutExpo', function () {
214
215                        $(this).css('display', 'none');
216                    });
217            } else {
218
219                continue;
220            }
221        }
222
223        return 1;
224    }
225
226    var idx = null;
227
228    $(Selector.nav).on('mouseleave', function (event) {
229
230        outDropMenu();
231
232        idx = null;
233    });
234
235    return 1;
236
237    new layout({
238        selector: {
239            head: '#header', // 헤더 전체를 스크롤 고정할지
240            nav: '#gnb_wrap', // 고정 기준이 되는 내비게이션
241            locate: '.depth_1', // 드롭다운 토글 버튼
242            locateDropnMenu: '.gnbSubM' // 드롭다운 메뉴 (HTML에는 아직 없음, gnb 함수에서 다루나?)
243        }
244    });
245}
246
247function calendarData(date) {
248
249    if (date) {
250
251        date = date.split('-');
252        date[1] = date[1] - 1;
253        date = new Date(date[0], date[1], date[2]);
254    } else {
255
256        var date = new Date();
257    }
258    var currentYear = date.getFullYear();
259    //년도를 구함
260
261    var currentMonth = date.getMonth() + 1;
262    //연을 구함. 월은 0부터 시작하므로 +1, 12월은 11을 출력
263
264    var currentDate = date.getDate();
265    //오늘 일자.
266
267    date.setDate(1);
268
269    var currentDay = date.getDay();
270    //이번달 1일의 요일은 출력. 0은 일요일 6은 토요일
271
272    var lastDate = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
273
274    if ((currentYear % 4 === 0 && currentYear % 100 !== 0) || currentYear % 400 === 0) {
275
276        lastDate[1] = 29;
277    }
278    //각 달의 마지막 일을 계산, 윤년의 경우 년도가 4의 배수이고 100의 배수가 아닐 때 혹은 400의 배수일 때 2월달이 29일 임.
279
280    var currentLastDate = lastDate[currentMonth - 1];
281    var week = Math.ceil((currentDay + currentLastDate) / 7);
282    //총 몇 주인지 구함.
283
284    if (currentMonth != 1) {
285
286        var prevDate = currentYear + '-' + (currentMonth - 1) + '-' + currentDate;
287    } else {
288
289        var prevDate = (currentYear - 1) + '-' + 12 + '-' + currentDate;
290    }
291    //만약 이번달이 1월이라면 1년 전 12월로 출력.
292
293    if (currentMonth != 12) {
294
295        var nextDate = currentYear + '-' + (currentMonth + 1) + '-' + currentDate;
296    } else {
297
298        var nextDate = (currentYear + 1) + '-' + 1 + '-' + currentDate;
299    }
300    //만약 이번달이 12월이라면 1년 후 1월로 출력.
301
302
303    if (currentMonth < 10) {
304
305        var currentMonth = '0' + currentMonth;
306    }
307    //10월 이하라면 앞에 0을 붙여준다.
308
309    return {
310        prev: prevDate,
311        next: nextDate,
312        y: currentYear,
313        m: currentMonth,
314        d: currentDay,
315        last: currentLastDate,
316        week: week,
317    };
318}
319
320function calendarString(date) {
321
322    var data = calendarData(date);
323
324    var calendar = '';
325
326    var dateString = new Array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat');
327    var dateStringKor = new Array('일', '월', '화', '수', '목', '금', '토');
328
329    calendar += '<div class="layer_cal_head">';
330    calendar += '   <a href="#" class="prev" onclick="picker(\'' + data.prev + '\', \'prev\'); return false;"><span class="hide">이전달</span></a>';
331    calendar += '   <b>
331' + data.y + '. ' + data.m + '</b>';
332    calendar += '   <a href="#" class="next" onclick="picker(\'' + data.next + '\', \'next\'); return false;"><span class="hide">다음달</span></a>';
333    calendar += '</div>';
334
335    calendar += '<table border="0" cellspacing="0" cellpadding="0">';
336    calendar += '   <caption>' + data.y + '년 ' + data.m + '월 달력</caption>';
337    calendar += '   <thead>';
338    calendar += '        <tr>';
339    calendar += '          <th class="sun" scope="row">일</th>';
340    calendar += '          <th class="mon" scope="row">월</th>';
341    calendar += '          <th class="tue" scope="row">화</th>';
342    calendar += '          <th class="wed" scope="row">수</th>';
343    calendar += '          <th class="thu" scope="row">목</th>';
344    calendar += '          <th class="fri" scope="row">금</th>';
345    calendar += '          <th class="sat" scope="row">토</th>';
346    calendar += '        </tr>';
347    calendar += '   </thead>';
348    calendar += '<tbody>';
349
350    var dateNum = 1 - data.d;
351
352    var endCnt = 0;
353
354    for (var i = 0; i < data.week; i++) {
355
356        calendar += '<tr>';
357
358        for (var j = 0; j < 7; j++, dateNum++) {
359
360            if (dateNum < 1) {
361                calendar += '<td class="not_day"><a href="#">' + (Number(calendarData(data.prev).last) + Number(dateNum)) + '</a></td>';
362                continue;
363            }
364
365            if (dateNum > data.last) {
366                calendar += '<td class="not_day"><a href="#">' + (((data.last + j) - data.last + 1) - (endCnt + 1)) + '</a></td>';
367                continue;
368            }
369
370            calendar += '<td class="' + dateString[j] + '"><a data-date="' + data.y + '.' + data.m + '.' + (dateNum < 10 ? '0' + dateNum : dateNum) + '(' + dateStringKor[j] + ')" href="#">' + dateNum + '</a></td>';
371
372            endCnt = j;
373
374        }
375        calendar += '</tr>';
376    }
377
378    calendar += '</tbody>';
379    calendar += '</table>';
380
381    return calendar;
382}
383
384function picker(date, dir, write) {
385
386    var calNum = 0
387
388    var str = '';
389
390    while (calNum < 2) {
391
392        str += '<div class="layer_calender ' + (calNum ? 'cal_right' : 'cal_left') + '">' + function () {
393
394            var str = '';
395
396            if (calNum) {
397
398                str = calendarString(function () {
399
400                    var str = calendarData(date).next;
401
402                    if (dir == 'next') {
403
404                        str = date;
405                    }
406
407                    return str;
408                }());
409            } else {
410
411                str = calendarString(function () {
412
413                    var str = date;
414
415                    if (dir == 'next') {
416
417                        str = calendarData(date).prev;;
418                    }
419
420                    return str;
421                }());
422            }
423
424            return str;
425
426        }() + '</div>';
427
428        calNum++;
429    }
430
431    if (write) {
432
433        document.write(str);
434    } else {
435
436        $('.calendar_wrap').html(str);
437    }
438
439    return 1;
440}
441
442function tableResponsed() {
443    const parent = $('.res_bbs_wrap');
444    const parentLen = parent.length;
445
446    if (!parentLen) return false;
447
448    for (let z = 0; z < parentLen; z++) {
449        const wrap = parent.eq(z);
450
451        // 기존 반응형 구조 제거
452        wrap.find('.tbl_responsed').remove();
453
454        const theadTh = wrap.find('.tbl thead th, .tbl_board thead th');
455        const tbodyTr = wrap.find('.tbl tbody tr, .tbl_board tbody tr');
456
457        const tiArr = [];
458        let str = '';
459        let useAllCheck = false;
460        let useAllCheckStr = '';
461
462        theadTh.each(function () {
463            tiArr.push($(this).html());
464        });
465
466        tbodyTr.each(function (j) {
467            const childTd = $(this).children();
468            let strItem = `\n<li class="item item_${j}">`;
469
470            childTd.each(function (k) {
471                const td = $(this);
472                const hasCheckbox = td.find('input[type=checkbox]').length > 0;
473                const hasRadio = td.find('input[type=radio]').length > 0;
474
475                if (hasCheckbox && !useAllCheck) {
476                    useAllCheck = true;
477                    useAllCheckStr = tiArr[k];
478                }
479
480                let tdHtml = td.html();
481
482                if (hasRadio) {
483                    const inputId = `radio_${z}_${j}_${k}`;
484                    tdHtml = tdHtml.replace(
485                        /<input([^>]*type="radio"[^>]*)name="([^"]*)"(.*?)>/g,
486                        (match, attrs, name, rest) => {
487                            return `<input${attrs}name="${name}_tbl${z}_col${k}" id="${inputId}" ${rest}>`;
488                        }
489                    );
490                    if (!/for=/.test(tdHtml)) {
491                        tdHtml += `<label for="radio_${z}_${j}_${k}">선택</label>`;
492                    }
493                }
494
495                // 20251126 수정
496                const strTitle = hasRadio ? '' : `<b>${tiArr[k]}</b>`;
497                // 20251126 수정
498
499                strItem += `\n<div class="child_${k}">` +
500                    strTitle +
501                    ((hasCheckbox || hasRadio) ?
502                        `<div class="use_list_checkbox">${tdHtml}</div>` :
503                        td.html()) +
504                    '</div>';
505            });
506
507            strItem += '\n</li>';
508            str += strItem;
509        });
510
511        // 20251126 수정
512        const checkAllHtml = (useAllCheck && $('.customCheckAll').length > 0) ?
513    `<div class="use_all_checkbox">
514        <input type="checkbox" id="customCheckAll_${z}" class="customCheckAll" />
515        <label for="customCheckAll_${z}"><span class="label-txt">${useAllCheckStr} 전체 선택</span></label>
516     </div>` :
517    '';
518        // 20251126 수정
519        
520        
521        wrap.append(
522            `\n<div class="tbl_responsed">
523                ${checkAllHtml}
524                <ul>${str}</ul>
525             </div>`
526        );
527    }
528
529    return syncInputs();
530}
531
532function syncInputs() {
533    $('.tbl_responsed input[type=checkbox], .tbl_responsed input[type=radio]').each(function () {
534        const clonedInput = $(this);
535        const li = clonedInput.closest('li');
536        const index = li.index();
537        const tdIndex = clonedInput.closest('div[class^=child_]').index();
538
539        const originalInput = $('.res_bbs_wrap .tbl tbody tr')
540            .eq(index)
541            .children()
542            .eq(tdIndex)
543            .find(`input[type=${clonedInput.attr('type')}]`);
544
545        clonedInput.on('change', function () {
546            if (clonedInput.attr('type') === 'radio') {
547                const name = clonedInput.attr('name');
548                $('input[name="' + name + '"]').not(clonedInput).prop('checked', false);
549                originalInput.prop('checked', true);
550            } else {
551                originalInput.prop('checked', clonedInput.prop('checked'));
552            }
553        });
554
555        originalInput.on('change', function () {
556            clonedInput.prop('checked', originalInput.prop('checked'));
557        });
558    });
559
560    return true;
561}
562
563$(document).on('change', '.customCheckAll', function () {
564    const isChecked = $(this).is(':checked');
565    const wrapper = $(this).closest('.tbl_responsed');
566
567    wrapper.find('input[type=checkbox]').not(this).each(function () {
568        $(this).prop('checked', isChecked).trigger('change');
569    });
570
571    const wrapIndex = $('.tbl_responsed').index(wrapper);
572    $('.res_bbs_wrap .tbl tbody tr').each(function () {
573        $(this).find('input[type=checkbox]').prop('checked', isChecked).trigger('change');
574    });
575});
576
577$(window).on('load', function () {
578    tableResponsed();
579
580    // 혹시 외부 UI 시스템이 자동 삽입한 #checkAll 제거
581    setTimeout(() => {
582        $('#checkAll, label[for="checkAll"]').remove();
583    }, 150);
584});
585
586function resSch_List(id) {
587    var item = $(id);
588
589    $(".none").stop(0, 1).slideUp(300, 'easeOutCubic');
590
591    item.slideDown(300, 'easeOutCubic', function () {
592        var box_position = item.position();
593        $('html, body').stop(0, 1).animate({
594            scrollTop: box_position.top - 120
595        }, 1000, 'easeOutExpo');
596    });
597
598    return false;
599}
600
601function showhide(_this, i) {
602
603    if ($(i).css('display') == 'none') {
604
605        $(i).slideDown(300, 'easeOutCubic');
606    } else {
607
608        $(i).slideUp(300, 'easeOutCubic');
609    }
610
611
612}
613
614function linkTab() {
615    var tab = $(".linkTab");
616    var tabUl = tab.find(">ul");
617    var tabLi = tab.find(">ul>li");
618    var text = "";
619
620    tabLi.each(function () {
621        if ($(this).find("a").hasClass("on")) {
622            text = $(this).find(">a>span").text();
623        }
624    });
625
626    /*$(".tab-col-3 li:nth-child(3n+1) a").css({borderLeft:"1px solid #d6d6e0"});
627     $(".tab-col-4 li:nth-child(4n+1) a").css({borderLeft:"1px solid #d6d6e0"});
628     $(".tab-col-5 li:nth-child(5n+1) a").css({borderLeft:"1px solid #d6d6e0"});
629     $(".tab-col-6 li:nth-child(6n+1) a").css({borderLeft:"1px solid #d6d6e0"});*/
630
631    tab.prepend("<button class='mlinkTab_btn'>" + text + "</button>");
632
633    $(document).on("click", ".mlinkTab_btn", function () {
634        if ($(this).next("ul").is(":hidden")) {
635            $(this).addClass("on");
636            $(this).next("ul").stop().slideDown("fast");
637        } else {
638            $(this).removeClass("on");
639            $(this).next("ul").stop().slideUp("fast");
640        }
641    });
642}
643
644// jquery ui 달력 한글
645$.datepicker.setDefaults({
646    dateFormat: 'yy-mm-dd',
647    prevText: '이전 달',
648    nextText: '다음 달',
649    monthNames: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
650    monthNamesShort: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
651    dayNames: ['일', '월', '화', '수', '목', '금', '토'],
652    dayNamesShort: ['일', '월', '화', '수', '목', '금', '토'],
653    dayNamesMin: ['일', '월', '화', '수', '목', '금', '토'],
654    showMonthAfterYear: true,
655    yearSuffix: '년',
656    changeYear: true,
657    changeMonth: true
658});
659
660$(function () {
661    $(".datepicker").datepicker({
662        beforeShow: function (input, inst) {
663            setTimeout(function () {
664                var offsets = $(".datepicker-wrap").offset();
665                //var top = offsets.top + 25;
666                inst.dpDiv.css({
667                    //top: top,
668                    left: offsets.left,
669                });
670                inst.dpDiv.outerWidth($(input).outerWidth());
671            });
672        }
673    });
674});
675
676function sitemap() { //사이트맵(전체메뉴)
677    var sm_btn = $(".sitemap_btn");
678    var sm = $("#siteMap");
679    var overlay = $("#sitemap-overlay");
680    var speed = 300;
681    var close = $(".sitemap_close");
682    var dep2btn = $(".sitemap_list>li>ul>li>a");
683    var dep3 = $(".sitemap_list>li>ul>li>ul");
684    var dep3btn = $(".sitemap_list>li>ul>li>ul>li>a");
685    // var winW = $(window).outerWidth();
686
687    // gnb-depth03 시작 위치에 맞춰 전체메뉴 위치 설정
688    var gnbDepth03 = $(".gnb-depth03");
689    if (gnbDepth03.length) {
690        sm.css("top", gnbDepth03.position().top + "px");
691    }
692
693    sm_btn.on("click", function () {
694        // 모바일 전체메뉴(mMenu) 오버레이 밀림 방지
695        if ($(window).width() < 1161) {
696            overlay.css('top', 0).fadeIn(speed);
697            return;
698        }
699
700        if (sm.is(":hidden")) {
701            sm.stop(0, 1).slideDown(speed, 'easeOutCubic');
702            var gnbBottom = gnbDepth03.length ? gnbDepth03[0].getBoundingClientRect().bottom : 0;
703            overlay.css('top', gnbBottom + 'px').fadeIn(speed);
704        } else {
705            sm.stop(0, 1).slideUp(speed, 'easeOutCubic');
706            overlay.fadeOut(speed);
707        }
708    });
709
710    close.on("click", function () {
711        sm.stop(0, 1).slideUp(speed, 'easeOutCubic');
712        overlay.fadeOut(speed);
713    });
714
715    overlay.on("click", function () {
716        sm.stop(0, 1).slideUp(speed, 'easeOutCubic');
717        overlay.fadeOut(speed);
718    });
719
720    dep3.on("mouseenter focusin", function () {
721        $(this).prev("a").addClass("ov");
722    });
723    dep3.on("mouseleave focusout", function () {
724        $(this).prev("a").removeClass("ov");
725    });
726    dep3btn.on("mouseenter focusin", function () {
727        $(this).closest("ul").prev("a").addClass("ov");
728    });
729
730
731    dep2btn.on("click", function () {
732        if ($(window).width() < 724) {
733            if ($(this).next().is(":hidden")) {
734
735                dep2btn.removeClass("on");
736                dep3.stop(0, 1).slideUp(speed, 'easeOutCubic');
737                $(this).addClass("on");
738                $(this).next().stop(0, 1).slideDown(speed, 'easeOutCubic');
739            } else {
740
741                $(this).removeClass("on");
742                $(this).next().stop(0, 1).slideUp(speed, 'easeOutCubic');
743            }
744        }
745
746        if ($(this).next().length) {
747
748            return false;
749        }
750    });
751
752    dep2btn.each(function () {
753
754        if (!$(this).next().length) {
755
756            $(this).addClass("empty");
757        }
758    });
759}
760
761
762function gnb(param, obj, btn, wrap, dur, meth) {
763    var param = $(param);
764    var btn = param.find(btn);
765    var obj = param.find(obj);
766    var wrap = $(wrap);
767    var data = false;
768    var elem;
769    var targetHeight = new Array();
770    var targetHeightResult;
771    var heightResult = btn.outerHeight(true);
772    var allBtn = $(".allm_btn");
773    var allMenu = $("#allMenu");
774
775    function gnb_height() {
776        $.each(obj, function (idx) {
777            targetHeight[idx] = $(this).parent().find(obj).outerHeight(true) + 80;
778        });
779    }
780
781    function _open() {
782        btn.parent().find(obj).removeAttr("style");
783        btn.not(elem).removeClass("current").eq(elem).addClass("current");
784        obj.not(elem).hide().css({
785            display: "none",
786            //opacity: 0
787        });
788        gnb_height();
789        obj.eq(elem).show().stop().animate({
790            display: "block",
791            opacity: 1
792        }, {
793            duration: 300,
794            easing: 'swing'
795        });
796        param.stop(true, false).animate({
797            "height": targetHeight[elem]
798        }, {
799            duration: 300,
800            easing: 'swing'
801        });
802        param.addClass("active");
803        $("#header").addClass("on");
804    }
805
806    function _close() {
807        btn.removeClass("current");
808        /*obj.css({
809            display: "none",
810            opacity: 0
811        });*/
812        param.stop(true, false).animate({
813            "height": heightResult
814        }, {
815            duration: 300,
816            easing: 'swing'
817        });
818        param.removeClass("active");
819        $("#header").removeClass("on");
820    }
821    btn.on('mouseover focusin', function () {
822        elem = $(this).parent().index();
823        _open();
824        allMenu.slideUp();
825        $("#header").removeClass("mask");
826        $("#siteMap").css('display', 'none');
827
828    });
829    obj.find("a").last().on("focusout", function () {
830        _close();
831        btn.removeClass("current");
832        param.removeClass("active");
833        wrap.removeClass("on");
834    });
835    wrap.on("mouseleave", function () {
836        _close();
837    });
838    allBtn.click(function () {
839        _close();
840    });
841}
842
843function blind_on() {
844    if ($(window).width() <= 1160) {
845        $(".blind").css({
846            display: "block"
847        }).stop().animate({
848            opacity: 0.5
849        }, 500);
850    }
851}
852
853function blind_off() {
854    $(".blind").stop().animate({
855        opacity: 0
856    }, 500, function () {
857        $(".blind").css({
858            display: "none"
859        });
860    });
861}
862
863$(window).on('resize orientationchange', function () {
864    if ($(window).width() >= 1160) {
865        // PC로 전환되면 모바일 메뉴 & 블라인드 강제 닫기
866        $("#mMenu").css({
867            display: "none",
868            right: "-100%"
869        });
870        $("body").removeClass('on');
871
872        $(".blind").stop().animate({
873            opacity: 0
874        }, 300, function () {
875            $(this).css({
876                display: "none"
877            });
878        });
879    }
880});
881
882function mMenu() { //모바일 메뉴
883    var mBtn = $(".sitemap_btn");
884    var menuBox = $("#mMenu");
885    var mClose = $(".mMenu_close");
886    var dep1btn = $(".mMenu_list>li>a");
887    var dep2con = $(".mMenu_list>li>ul");
888    var dep2btn = $(".mMenu_list>li>ul>li>a");
889    var dep3con = $(".mMenu_list>li>ul>li>ul");
890    var dep3btn = $(".mMenu_list>li>ul>li>ul>li>a");
891    var speed = 300;
892
893    function lockScroll(e) {
894        if (!$(e.target).closest('#mMenu .mMenu_list').length) {
895            e.preventDefault();
896        }
897    }
898
899    dep2btn.each(function () {
900        if ($(this).hasClass("on")) {
901            $(this).closest("ul").show();
902            $(this).closest("ul").prev("a").addClass("on");
903        }
904        if (!$(this).next().length) {
905            $(this).addClass("empty");
906        }
907    });
908    dep3btn.each(function () {
909        if ($(this).hasClass("on")) {
910            $(this).closest("ul").show();
911            $(this).closest("ul").prev("a").addClass("on");
912            $(this).closest("ul").parents("ul").show();
913            $(this).closest("ul").parents("ul").prev("a").addClass("on");
914        }
915    });
916
917    mBtn.on("click", function () {
918        if (!isMobile()) return;
919
920        blind_on();
921        menuBox.css({
922            display: "flex"
923        }).animate({
924            right: "0px"
925        }, speed);
926
927        $("body").addClass('on').css("overflow", "hidden");
928        document.addEventListener('wheel', lockScroll, { passive: false });
929        document.addEventListener('touchmove', lockScroll, { passive: false });
930    });
931
932    function isMobile() {
933        return $(window).width() < 1161;
934    }
935
936    function closeMenu() {
937        var w = menuBox.outerWidth() || 280;
938        blind_off();
939        $("#sitemap-overlay").fadeOut(speed);
940        menuBox.stop(true).animate({
941            right: -w
942        }, speed, function () {
943            menuBox.css({ display: "none" });
944        });
945        $("body").css({
946            overflow: "auto",
947            position: "static",
948            width: "auto",
949            height: "auto"
950        }).removeClass('on');
951        document.removeEventListener('wheel', lockScroll);
952        document.removeEventListener('touchmove', lockScroll);
953    }
954
955    mClose.on("click", function () {
956        closeMenu();
957    });
958
959    $("#sitemap-overlay").on("touchend click", function (e) {
960        if (e.type === 'touchend') e.preventDefault();
961        if (!isMobile()) return;
962        closeMenu();
963    });
964
965    dep1btn.on("click", function () {
966        dep2con.slideUp(speed);
967        dep1btn.removeClass("on");
968        if ($(this).next("ul").is(":hidden")) {
969            $(this).addClass("on").next("ul").slideDown(speed);
970        } else {
971            $(this).removeClass("on").next("ul").slideUp(speed);
972        }
973        return false;
974    });
975    dep2btn.on("click", function () {
976        dep3con.slideUp(speed);
977        dep2btn.removeClass("on");
978        if ($(this).next("ul").is(":hidden")) {
979            $(this).addClass("on").next("ul").slideDown(speed);
980        } else {
981            $(this).removeClass("on").next("ul").slideUp(speed);
982        }
983        if ($(this).next("ul").length) {
984            return false;
985        }
986    });
987}
988
989function bing() {
990
991    var btn = $('.bing');
992
993    btn.on('click', function (event) {
994
995        event.preventDefault();
996
997        $('#bing').toggle();
998
999    });
1000
1001    return 1;
1002}
1003
1004// 실행부
1005$(function () {
1006
1007    bing();
1008
1009    $("#wrap").prepend("<div class='blind'></div>");
1010    $(".blind").css({
1011        display: "none",
1012        position: "fixed",
1013        left: 0,
1014        top: 0,
1015        width: "100%",
1016        height: "100%",
1017        background: "#000",
1018        opacity: 0,
1019        zIndex: 998
1020    });
1021
1022    // 레이아웃 제어
1023    window.Layout = new layout({
1024        selector: {
1025            head: '#header',
1026            nav: '#nav',
1027            locate: '#gnb .depth_1',
1028            locateDropnMenu: '#gnb .dropList',
1029            container: '#container'
1030        }
1031    });
1032
1033    window.onresize = function () {
1034
1035        return 1;
1036    };
1037
1038    gnb(); //GNB메뉴
1039    mMenu(); //모바일메뉴
1040
1041
1042    linkTab(); // 서브페이지 상단 탭버튼 반응형
1043
1044
1045    sitemap(); //사이트맵(전체메뉴)
1046});
1047
1048
1049
1050$('.linkTab li').find('a').click(function () {
1051    $('.linkTab a').removeClass('on');
1052    $(this).addClass('on');
1053})
1054
1055
1056$('.dropdown-menu.opened').on('click', function (e) {
1057    e.stopPropagation();
1058});
1059
1060
1061function clampDropdown($el) {
1062    $el.css({ left: '', right: '', transform: '' });
1063    const rect = $el[0].getBoundingClientRect();
1064    const margin = 12;
1065    if (rect.right > document.documentElement.clientWidth - margin) {
1066        const op = $el[0].offsetParent || document.documentElement;
1067        const opRect = op.getBoundingClientRect();
1068        $el.css({
1069            left: ((document.documentElement.clientWidth - margin) - opRect.left - rect.width) + 'px',
1070            right: 'auto',
1071            transform: 'none'
1072        });
1073    } else if (rect.left < margin) {
1074        const op = $el[0].offsetParent || document.documentElement;
1075        const opRect = op.getBoundingClientRect();
1076        $el.css({
1077            left: (margin - opRect.left) + 'px',
1078            right: 'auto',
1079            transform: 'none'
1080        });
1081    }
1082}
1083
1084function bot_link() {
1085    //    20260129 추가
1086    var btn = $(".toggleBtn").not(".train .toggleBtn");
1087//    20260129 추가
1088    var box_btn = $(".dropList>li>a");
1089
1090    $(".dropList").hide().attr("aria-hidden", "true");
1091
1092    btn.on("click", function (e) {
1093        e.stopPropagation();
1094        var dropList = $(this).siblings(".dropList");
1095        if (dropList.is(":hidden")) {
1096            $(".dropList").hide().attr("aria-hidden", "true");
1097            $(".toggleBtn").removeClass("on");
1098            $(".dr_dropList").stop(true, true).slideUp(200).attr("aria-hidden", "true");
1099            $(".dr_toggleBtn").removeClass("on").attr("aria-expanded", "false");
1100            $(".train_tooltip").stop(true, true).hide();
1101            $(".train.dropToggle").removeClass("on");
1102
1103            dropList.show().attr("aria-hidden", "false");
1104            clampDropdown(dropList);
1105            $(this).addClass("on");
1106        } else {
1107            dropList.hide().attr("aria-hidden", "true");
1108            $(this).removeClass("on");
1109        }
1110    });
1111
1112    box_btn.on("click", function (e) {
1113        e.preventDefault();
1114        e.stopPropagation();
1115        $(this).closest(".dropList").hide().attr("aria-hidden", "true");
1116        $(this).closest(".dropToggle").find(".toggleBtn").removeClass("on");
1117    });
1118
1119    $(document).on("click", function () {
1120        $(".dropList").hide().attr("aria-hidden", "true");
1121        $(".toggleBtn").removeClass("on");
1122    });
1123}
1124
1125function bot_link1() {
1126    const BTN_SEL = '.dr_toggleBtn';
1127    const LIST_SEL = '.dr_dropList';
1128    const INSIDE = `${BTN_SEL}, ${LIST_SEL}`;
1129    let justToggled = false;
1130
1131    $(LIST_SEL).hide().attr('aria-hidden', 'true');
1132    $(BTN_SEL).removeClass('on').attr('aria-expanded', 'false');
1133
1134    $(document).off('.botlink1');
1135
1136    $(document).on('click.botlink1', BTN_SEL, function (e) {
1137        e.stopPropagation();
1138        justToggled = true;
1139
1140        const $btn = $(this);
1141        const $list = $btn.siblings(LIST_SEL);
1142        const willOpen = $list.is(':hidden');
1143
1144        $(LIST_SEL).not($list).stop(true, true).slideUp(200).attr('aria-hidden', 'true');
1145        $(BTN_SEL).not($btn).removeClass('on').attr('aria-expanded', 'false');
1146        $(".dropList").hide().attr("aria-hidden", "true");
1147        $(".toggleBtn").removeClass("on");
1148        $(".train_tooltip").stop(true, true).hide();
1149        $(".train.dropToggle").removeClass("on");
1150
1151        if (willOpen) {
1152            $list.css('visibility', 'hidden').show();
1153            clampDropdown($list);
1154            $list.hide().css('visibility', '');
1155            $list.stop(true, true).slideDown(200).attr('aria-hidden', 'false');
1156            $btn.addClass('on').attr('aria-expanded', 'true');
1157        } else {
1158            $list.stop(true, true).slideUp(200).attr('aria-hidden', 'true');
1159            $btn.removeClass('on').attr('aria-expanded', 'false');
1160        }
1161
1162        setTimeout(() => {
1163            justToggled = false;
1164        }, 0);
1165    });
1166
1167    $(document).on('click.botlink1', LIST_SEL, function (e) {
1168        e.stopPropagation();
1169    });
1170
1171    $(document).on('click.botlink1', function (e) {
1172        if (justToggled) return;
1173        if (!$(e.target).closest(INSIDE).length) {
1174            $(LIST_SEL).stop(true, true).slideUp(200).attr('aria-hidden', 'true');
1175            $(BTN_SEL).removeClass('on').attr('aria-expanded', 'false');
1176        }
1177    });
1178
1179    $(document).on('keydown.botlink1', function (e) {
1180        if (e.key === 'Escape') {
1181            $(LIST_SEL).stop(true, true).slideUp(200).attr('aria-hidden', 'true');
1182            $(BTN_SEL).removeClass('on').attr('aria-expanded', 'false');
1183        }
1184    });
1185
1186    $(document).on('click.botlink1', `${LIST_SEL} > li > a`, function () {
1187        $(LIST_SEL).stop(true, true).slideUp(200).attr('aria-hidden', 'true');
1188        $(BTN_SEL).removeClass('on').attr('aria-expanded', 'false');
1189    });
1190}
1191
1192function searchResize(){
1193	let currentWidthSize = window.outerWidth;
1194	if(currentWidthSize >= 1200){
1195		if($(".M-sch").is(":visible")){
1196			$(".M-sch").hide();
1197			$("#M-sch-overlay").hide();
1198		}
1199	}
1200	
1201}
1202
1203function lnbReHeight() {
1204    // 레이아웃 관련 모양을 잡기위한 스크립트
1205    var lnb = $('#lnb');
1206    var container = $('#container_wrap');
1207
1208    if (container.outerHeight() < lnb.outerHeight()) {
1209
1210        lnb.css('height', 'auto');
1211    } else {
1212
1213        lnb.css('height', container.outerHeight());
1214    }
1215
1216    return 1;
1217}
1218
1219function lnbMenu() {
1220    // 좌측메뉴
1221    var lm = $("#lnb>nav>ul");
1222    lm.a = lm.find(">li>a");
1223    lm.dep2 = lm.find(">li>ul");
1224    lm.dep2.a = lm.dep2.find(">li>a");
1225    lm.dep3 = lm.dep2.find(">li>ul");
1226    lm.dep3.a = lm.dep3.find(">li>a");
1227    lm.dep4 = lm.dep3.find(">li>ul");
1228    lm.dep4.a = lm.dep4.find(">li>a");
1229
1230    //좌측메뉴 4뎁스 버튼에 ov클래스가 있으면 해당메뉴의 상위 뎁스에 ov클래스를 자동으로 넣어줌
1231    lm.dep4.a.each(function () {
1232        if ($(this).hasClass("ov")) {
1233            $(this).closest("ul").siblings("a").addClass("ov");
1234        }
1235    });
1236
1237    //좌측메뉴 3뎁스 버튼에 ov클래스가 있으면 해당메뉴의 상위 뎁스에 ov클래스를 자동으로 넣어줌
1238    lm.dep3.a.each(function () {
1239        if ($(this).hasClass("ov")) {
1240            $(this).closest("ul").siblings("a").addClass("ov");
1241        }
1242    });
1243
1244    //좌측메뉴 2뎁스 버튼에 ov클래스가 있으면 해당메뉴의 상위 뎁스에 ov클래스를 자동으로 넣어줌
1245    lm.dep2.a.each(function () {
1246        if ($(this).hasClass("ov")) {
1247            $(this).closest("ul").siblings("a").addClass("ov");
1248        }    // 20260305수정
1249	});
1250    lm.find('a').on('click', function (event) {
1251        var t = $(this);
1252
1253        if (t.next().find('>li').length) {
1254            event.preventDefault();
1255
1256            var ld_1 = '.lnb_depth_1';
1257            var ld_2 = '.lnb_depth_2';
1258            var ld_3 = '.lnb_depth_3';
1259
1260            if (t.hasClass('ov')) {
1261                t.removeClass('ov');
1262                t.next().slideUp(200, 'easeOutCubic', lnbReHeight);
1263                return;
1264            }
1265
1266            if (t.parents(ld_3).is(ld_3)) {
1267                $(ld_3 + '>li>a').removeClass('ov')
1268                    .next().slideUp(200, 'easeOutCubic', lnbReHeight);
1269            } else if (t.parents(ld_2).is(ld_2)) {
1270                $(ld_2 + '>li>a').removeClass('ov')
1271                    .next().slideUp(200, 'easeOutCubic', lnbReHeight);
1272            } else if (t.parents(ld_1).is(ld_1)) {
1273                $(ld_1 + '>a').removeClass('ov')
1274                    .next().slideUp(200, 'easeOutCubic', lnbReHeight);
1275            }
1276
1277            t.addClass('ov');
1278            t.next().slideDown(200, 'easeOutCubic', lnbReHeight);
1279        }
1280    });
1281}
1282
1283function executeForm(data, action, method, except){
1284    if(method == null) method = 'post';
1285
1286    var form = $('<form>');
1287    form.attr('action', action);
1288    form.attr('method', method);
1289
1290    for(var key in data){
1291        if(except != null && key in except) continue;
1292        else if(data[key] == null) continue;
1293
1294        if(typeof data[key] === 'object') data[key] = JSON.stringify(data[key]);
1295        var input = $('<input type="hidden" >').attr('name', key).val(data[key]);
1296        form.append(input);
1297    }
1298
1299    form.appendTo('body').submit();
1300}
1301
1302$(window).on('load resize', function () {
1303    lnbReHeight();
1304    searchResize();
1305});
1306
1307
1308$(document).ready(function () {
1309    bot_link();
1310    bot_link1();
1311    lnbMenu();
1312
1313    $('.tab-btn > li > a').each(function (idx) {
1314        $(this).on('click', function () {
1315            $('.tab-btn > li a').removeClass('on');
1316            $('.tab-cont > div').removeClass('on');
1317            $('.tab-btn > li a').eq(idx).addClass('on');
1318            $('.tab-cont > div').eq(idx).addClass('on');
1319        });
1320    });
1321
1322
1323});
1324
1325$(document).ready(function () {
1326    $(function () {
1327        const $menuBtns = $('.depth_1');
1328        const $subMenus = $('.gnbSubM');
1329        let hideTimer = null;
1330
1331        function openSubMenu($this) {
1332            const $currentSub = $this.next('.gnbSubM');
1333
1334            if ($currentSub.length) {
1335                $subMenus.not($currentSub).stop(true, true).slide
1335Up(200);
1336                $currentSub.stop(true, true).slideDown(200);
1337            } else {
1338                $subMenus.stop(true, true).slideUp(200);
1339            }
1340        }
1341
1342        // depth_1에 마우스 올리거나 포커스되면
1343        $menuBtns.on('mouseenter focus', function () {
1344            clearTimeout(hideTimer);
1345            openSubMenu($(this));
1346        });
1347
1348        // depth_1에서 엔터키 눌렀을 때
1349        $menuBtns.on('keydown', function (e) {
1350            if (e.key === "Enter" || e.keyCode === 13) {
1351                e.preventDefault();
1352                clearTimeout(hideTimer);
1353                openSubMenu($(this));
1354            }
1355        });
1356
1357        // nav 전체 영역을 벗어나면 닫기
1358        $('#nav').on('mouseleave', function () {
1359            hideTimer = setTimeout(() => {
1360                $subMenus.stop(true, true).slideUp(200);
1361            }, 150);
1362        });
1363
1364        $('#nav').on('mouseenter', function () {
1365            clearTimeout(hideTimer);
1366        });
1367    });
1368
1369
1370    $(function () {
1371        const $dropToggle = $('.board-drop');
1372        $dropToggle.find('.dropBtn').on('click', function (e) {
1373            e.preventDefault();
1374            const $wrap = $(this).closest('.board-drop').find('.dropList-wrap');
1375            $('.dropList-wrap').not($wrap).hide();
1376            $wrap.toggle();
1377        });
1378        $dropToggle.find('.drop-close').on('click', function (e) {
1379            e.preventDefault();
1380            $(this).closest('.dropList-wrap').hide();
1381        });
1382        $(document).on('click', function (e) {
1383            if (!$(e.target).closest('.board-drop').length) {
1384                $('.dropList-wrap').hide();
1385            }
1386        });
1387    });
1388});
1389$(document).ready(function () {
1390    $('.TabBtn > li > a , .board_tab > li > a, .find-tab > li > a').each(function (idx) {
1391        $(this).on('click', function () {
1392            $('.TabBtn > li > a , .board_tab > li > a , .find-tab > li > a').removeClass('on');
1393            $('.TabCont > div, .board__cont > div , .find-cont > div').removeClass('on');
1394            $('.TabBtn > li > a , .board_tab > li > a , .find-tab > li > a').eq(idx).addClass('on');
1395            $('.TabCont > div , .board__cont > div , .find-cont > div').eq(idx).addClass('on');
1396        });
1397    });
1398
1399    $(function () {
1400        $('.faq_toggle').on('click', function () {
1401            const $this = $(this);
1402            const $answer = $this.closest('.faq_item').find('.answer');
1403
1404            if ($this.hasClass('active')) {
1405                $this.removeClass('active');
1406                $answer.stop(true, true).slideUp(300);
1407            } else {
1408                $('.faq_toggle').removeClass('active');
1409                $('.answer').stop(true, true).slideUp(300);
1410
1411                $this.addClass('active');
1412                $answer.stop(true, true).slideDown(300);
1413            }
1414        });
1415    });
1416
1417    $(function () {
1418        $('.tree_view .ch_wrap input[type="checkbox"]').on('change', function () {
1419            $(this).parent().siblings('ul').slideToggle(300);
1420        });
1421    });
1422
1423});
1424
1425$(function () {
1426    var $mSchOverlay = $('#M-sch-overlay');
1427
1428    function openMSch() {
1429        $('.M-sch').stop(true, true).slideDown(300);
1430        $mSchOverlay.stop(true, true).fadeIn(300);
1431    }
1432
1433    function closeMSch() {
1434        $('.M-sch').stop(true, true).slideUp(300);
1435        $mSchOverlay.stop(true, true).fadeOut(300);
1436    }
1437
1438    // 검색 버튼 클릭 시
1439    $('.Mgnb-search > button').on('click', function (e) {
1440        e.preventDefault();
1441
1442        // 이미 보이면 닫고, 아니면 열기
1443        if ($('.M-sch').is(':visible')) {
1444            closeMSch();
1445        } else {
1446            openMSch();
1447        }
1448    });
1449
1450    // 검색창 닫기 버튼
1451    $('.gsearch_close').on('click', function (e) {
1452        e.preventDefault();
1453        closeMSch();
1454    });
1455
1456    // 오버레이 클릭 시 검색창 닫기
1457    $mSchOverlay.on('touchend click', function (e) {
1458        if (e.type === 'touchend') e.preventDefault();
1459        closeMSch();
1460    });
1461
1462    document.querySelectorAll('.status-toggle input[type="checkbox"]').forEach(function (checkbox) {
1463        checkbox.addEventListener('change', function () {
1464            const statusSpan = this.parentElement.previousElementSibling;
1465            statusSpan.textContent = this.checked ? '켜기' : '끄기';
1466        });
1467    });
1468
1469    $(document).ready(function () {
1470        $('.sns-toggle input[type="checkbox"]').on('change', function () {
1471            const $status = $(this).closest('.status-group').find('.status');
1472            if ($(this).is(':checked')) {
1473                $status.text('연결완료').addClass('on');
1474            } else {
1475                $status.text('연결해제').removeClass('on');
1476            }
1477        });
1478    });
1479});
1480
1481$(document).ready(function () {
1482    const $learnMore = $('.status-toggle input[type="checkbox"].learn-more'); //이어서 학습하기
1483    const $userInfoName = $('.status-toggle input[type="checkbox"].userInfoName'); //개인정보 (성명)
1484    const $loginExtend = $('.status-toggle input[type="checkbox"].loginExtend'); //로그인 연장
1485    
1486    const $myLearn = $('.My-learn');
1487	const $login = $('.login-time');
1488	const $maskingName = $('.maskingName');
1489    /////////////////////////
1490    //////이어서 학습하기//////
1491    ////////////////////////
1492    // 페이지 로드시 체크박스 상태에 따라 초기 표시 여부 설정
1493    if ($learnMore.is(':checked')) {
1494        $myLearn.slideDown(0); // 애니메이션 없이 보이기
1495    } else {
1496        $myLearn.slideUp(0);
1497    }
1498    // 체크박스 상태 변경 시 처리
1499    $learnMore.change(function () {
1500        if ($(this).is(':checked')) {
1501            $myLearn.stop(true, true).slideDown();
1502        } else {
1503            $myLearn.stop(true, true).slideUp();
1504        }
1505    });
1506    
1507    
1508    /////////////////////////
1509    //////개인정보 (성명)//////
1510    ////////////////////////
1511    // 페이지 로드시 체크박스 상태에 따라 초기 표시 여부 설정 
1512    if ($userInfoName.is(':checked')) {
1513        $maskingName.show();
1514    } else {
1515        $maskingName.hide();
1516    }
1517    // 체크박스 상태 변경 시 처리
1518    
1519    $userInfoName.change(function () {
1520        if ($(this).is(':checked')) {
1521              $maskingName.show();
1522        } else {
1523             $maskingName.hide();
1524        }
1525    });
1526    
1527    
1528    /////////////////////////
1529    ////////로그인 연장////////
1530    ////////////////////////    
1531    // 페이지 로드시 체크박스 상태에 따라 초기 표시 여부 설정
1532    if ($loginExtend.is(':checked')) {
1533		$login.show();
1534    } else {
1535		$login.hide();
1536    }
1537    // 체크박스 상태 변경 시 처리
1538    $loginExtend.change(function () {
1539        if ($(this).is(':checked')) {
1540            $login.show();
1541        } else {
1542            $login.hide();
1543        }
1544    });
1545    
1546    
1547    /////////////////////////////////////////
1548    ////설정 로그인 및 노출 checkbox change 이벤트.////
1549    /////////////////////////////////////////
1550	$(".dr_dropList > .setting-ct > .setting-row input[type=checkbox]").change(function(){
1551		if(isInitConfig) return;
1552		
1553		var $userLoginInfo = $(".dr_dropList > .setting-ct > .setting-row input[type=checkbox");
1554		
1555		var jsonData = {};
1556		
1557		$.each($userLoginInfo,function(index,item){
1558			const name = $(item).attr("name");     		// checkbox의 name
1559			const checked = $(item).is(":checked");		// true/false
1560			
1561			jsonData[name] = checked;
1562			
1563		});
1564		
1565		$.ajax({
1566			url : "/user/updateLoginUserInfo.face"
1567			,type : "post"
1568			,contentType : "application/json; charset=UTF-8"
1569			,data : JSON.stringify(jsonData)
1570			,success : function(res){console.log(res)}
1571			,error : function(res) {console.log(res)}
1572		});
1573		
1574	});
1575});
1576
1577var LAYER_POPUP_DEFAULT_OPTIONS = {
1578		modal: true,
1579		autoOpen: false
1580	}
1581
1582	function LayerPopup(id, type, options, parent, windou){
1583		
1584		var _this = this;
1585		
1586		// init ------------------------------------------------------------------------------------------
1587		// 설정 기본값에 사용자정의 값을 덮어씌운다.
1588		this.options = $.extend(true, {}, LAYER_POPUP_DEFAULT_OPTIONS, options);
1589		// close의 경우 전체 레이어팝업 배열에서도 제거해야하므로 onclose로 정의한다.
1590		
1591		// 입력된 id없으면 임의로 생성한다. 
1592		if(id == null) id = Math.random().replace(/[^0-9]/g, '').toString();
1593		
1594		// 입력된 부모가 없으면 body로 한다.
1595		if(parent == null) parent = document.body;
1596		parent = $(parent);
1597		
1598		// id로 이미 element가 있는지 찾는다.
1599		this.popup = $('#' + id);
1600		
1601		// element가 없으면 생성 후 parent로 넣는다.
1602		if(this.popup.length == 0){
1603			this.popup = $('<div>').appendTo(parent);
1604		}
1605		// element가 너무 많으면 첫번째것 제외하고 다 제거한다.
1606		else if(this.popup.length > 1){
1607			this.popup = this.popup.remove().eq(0).appendTo(parent);
1608		}
1609		
1610		// 처음엔 안보이게
1611		this.popup.attr('id', id).css('display', 'none');
1612		// init finish ------------------------------------------------------------------------------------------
1613		
1614		// member method ------------------------------------------------------------------------------------------
1615		
1616		this.reload = function(){
1617			if(type == 'iframe') {
1618				var iframe = this.popup.find('iframe');
1619				
1620				if(iframe.length == 0){
1621					iframe = $('<iframe>');
1622					this.popup.append(iframe);
1623				}
1624				iframe.hide();
1625					
1626				var url = this.options.url;
1627				url = url.replace(/\?$/, '')
1628				if(this.options.params) {
1629					
1630					var d = '?';
1631					if(url.match(/\?/)) {
1632						d = '&';
1633					}
1634					
1635					Object.keys(this.options.params).forEach(function(k){
1636						url += d + k + '=' + _this.options.params[k];
1637						d = '&';
1638					});
1639				}
1640					
1641				var d = '?';
1642				if(url.match(/\?/)) {
1643					d = '&';
1644				}
1645				url += d + 't=' + Math.random();
1646				
1647				iframe.attr({width: '100%', height: '100%', src: url});
1648				
1649				if(this.options.onload) iframe.on('load', this.options.onload);
1650				iframe.show();
1651				
1652				iframe.parent().css('overflow', 'hidden');
1653			}
1654			else if(type == 'content') {
1655				this.popup.html(this.options.content);
1656				
1657				if(this.options.onload) this.options.onload();
1658			}
1659			else if(type == 'url') {
1660				this.popup.load(this.options.url, this.options.params, function(){
1661					if(_this.options.onload) _this.options.onload();
1662				});
1663			}
1664			else if(type == 'id') {
1665				
1666			}
1667			
1668		}
1669		
1670		this.open = function(){
1671			this.popup.show();
1672			// this.popup.parent().css('position', 'fixed');
1673			// if(windou != null) this.popup.parents('.ui-dialog').position({my: 'center', at: 'center', of: windou});
1674			LayerPopup.openedPopup.push(_this);
1675			setTimeout(function() {
1676				_this.popup[0].focus();
1677			}, 100);
1678		}
1679		
1680		this.close = function(){
1681			// this.popup.find('iframe').hide().remove();)
1682			this.popup.hide();
1683			if(this.popup.is('#scheduleRegistPopup')) {
1684				//tinymce.activeEditor.destroy();
1685				tinymce.execCommand('mceRemoveEditor', true, 'editorCntt');
1686				tinymce.execCommand('mceAddEditor', true, 'editorCntt');
1687			} else if(this.popup.is('#scheduleRegistPopup')) {
1688				this.popup.refreshSchedule();
1689			}
1690			let idx = LayerPopup.openedPopup.indexOf(_this);
1691			LayerPopup.openedPopup.splice(idx, 1);
1692			
1693			if(_this.options.onclose) _this.options.onclose();
1694		}
1695		
1696		// member method finish ------------------------------------------------------------------------------------------
1697	}
1698
1699	LayerPopup.openedPopup = [];
1700	LayerPopup.getCurrentFocused = function(){
1701		return LayerPopup.openedPopup[LayerPopup.openedPopup.length - 1];
1702	}
1703
1704	
1705	$(function () {
1706        const $btn = $('.learn-btn');
1707        const $panel = $('.Mylearn-cont');
1708
1709        // 클릭 직후 한 틱 동안 바깥 클릭 닫힘을 무시하기 위한 플래그
1710        let justToggled = false;
1711
1712        $(document).off('.uiLearn');
1713        $btn.off('.uiLearn');
1714
1715        $btn.on('click.uiLearn', function (e) {
1716            e.stopPropagation();
1717            location.href = '/portal/default/myPage/learnManage/myLearn.page';
1718        });
1719
1720        $(document).on('click.uiLearn', '.Mylearn-cont', function (e) {
1721            e.stopPropagation();
1722        });
1723
1724        $(document).on('click.uiLearn', function (e) {
1725            if (justToggled) return;
1726            if ($panel.is(':visible') && !$(e.target).closest('.Mylearn-cont, .learn-btn').length) {
1727                $panel.stop(true, true).slideUp(300);
1728                $btn.removeClass('on');
1729            }
1730        });
1731
1732        $(document).on('keydown.uiLearn', function (e) {
1733            if (e.key === 'Escape' && $panel.is(':visible')) {
1734                $panel.stop(true, true).slideUp(300);
1735                $btn.removeClass('on');
1736                $btn.trigger('focus');
1737            }
1738        });
1739    });
1740
1741
1742$(function () {
1743    var threshold = 25,
1744        ticking = false,
1745        $hdr = $('.header-sticky'),
1746        // 모바일에서는 #gnb_wrap 전체를 고정 (.header-sticky는 2단 GNB 전용이므로 모바일에서는 사용하지 않음)
1747        $gnbWrap = $('#gnb_wrap');
1748    $Pop = $('.MainPopup');
1749
1750    // .header-sticky가 고정될 때의 실제 높이를 CSS 변수(--gnb-sticky-height)에 반영
1751    function updateStickyHeight() {
1752        var h = $hdr.outerHeight();
1753        if (h) {
1754            document.documentElement.style.setProperty('--gnb-sticky-height', h + 'px');
1755        }
1756
1757        // GNB 실제 높이를 --gnb-height에 반영하여 GNB 변경에 따른 위치 오류 방지
1758        var wrapH = $gnbWrap.outerHeight();
1759        var totalH = (wrapH || 0) + (h || 0);
1760        if (totalH) {
1761            document.documentElement.style.setProperty('--gnb-height', totalH + 'px');
1762        }
1763    }
1764
1765    function update() {
1766        var y = window.scrollY || document.documentElement.scrollTop || 0;
1767        $hdr.toggleClass('is-fixed', y > threshold);
1768        $gnbWrap.toggleClass('is-fixed', y > threshold);
1769        $Pop.toggleClass('is-fixed', y > threshold);
1770        ticking = false;
1771    }
1772
1773    $(window).on('scroll', function () {
1774        if (!ticking) {
1775            window.requestAnimationFrame(update);
1776            ticking = true;
1777        }
1778    });
1779
1780    $(window).on('resize', updateStickyHeight);
1781
1782    updateStickyHeight();
1783    update();
1784});
1785
1786
1787$(function () {
1788    const $btn = $('.Quick .quick-btn'); // 트리거 버튼
1789    const $panel = $('.quick-cnt'); // 드롭다운 패널
1790
1791    // 접근성 속성 세팅
1792    $btn.attr({
1793        role: 'button',
1794        'aria-haspopup': 'true',
1795        'aria-expanded': 'false'
1796    });
1797
1798    // 열기/닫기 함수
1799    function openPanel() {
1800        $btn.attr('aria-expanded', 'true');
1801        $panel.stop(true, true).slideDown(180, function () { clampDropdown($panel); });
1802        // 외부 클릭/ESC 바인딩
1803        $(document).on('mousedown.quick touchstart.quick', outsideHandler);
1804        $(document).on('keydown.quick', escHandler);
1805    }
1806
1807    function closePanel() {
1808        $btn.attr('aria-expanded', 'false');
1809        $panel.stop(true, true).slideUp(160, function () {
1810            $(document).off('.quick'); // 네임스페이스로 한 번에 해제
1811        });
1812    }
1813
1814    function togglePanel(e) {
1815        e.preventDefault();
1816        $panel.is(':visible') ? closePanel() : openPanel();
1817    }
1818
1819    // 바깥 영역 클릭 시 닫기
1820    function outsideHandler(e) {
1821        if ($(e.target).closest('.Quick, .quick-cnt').length === 0) {
1822            closePanel();
1823        }
1824    }
1825    // ESC로 닫기
1826    function escHandler(e) {
1827        if (e.key === 'Escape') {
1828            closePanel();
1829            $btn.focus();
1830        }
1831    }
1832
1833    // 버튼 클릭으로 토글
1834    $btn.on('click', togglePanel);
1835
1836    // 드롭다운 내부 링크 클릭 후 닫고 싶으면(선택)
1837    $('.quick-cnt a').on('click', closePanel);
1838});
1839
1840// 푸터 selectbox 옵션 위로 활성화
1841	 /**
1842     * 한글 여부 확인
1843     */
1844	function isHangulChar(ch) {
1845	  c = ch.charCodeAt(0);
1846	  if( 0x1100<=c && c<=0x11FF ) return true;
1847	  if( 0x3130<=c && c<=0x318F ) return true;
1848	  if( 0xAC00<=c && c<=0xD7A3 ) return true;
1849	  return false;
1850	}
1851	
1852	    /**
1853     * 문자열의 byte length를 얻는다.
1854     *
1855     * @param   str 문자열
1856     * @return  byte length
1857     * @author  marie
1858     */
1859    function jsByteLength(str) {
1860        if (str == "") {
1861            return  0;
1862        }
1863
1864        var bytes = 0;
1865
1866        for (var i = 0; i < str.length; i++) {
1867        	code=str.charCodeAt(i);
1868			if (code < 128) {
1869				bytes += 1;
1870			}else if (code < 2048){
1871				bytes += 2;
1872			}else if (code < 65536){
1873				bytes += 3;
1874			}else{
1875				bytes += 4;
1876			}
1877        }
1878
1879        return  bytes;
1880    }
1881    
1882    
1883let isFirst = true; // 페이지 최초 접근 history.replaceState 처리해서 이력을 안남기지만 뒤로가기 하면 state 조회되게.
1884let actions = [];
1885/**
1886 * 뒤로가기 히스토리을 추가한다.
1887 * @param state action : 작업구분(search, detail, ..), data : 조회 조건
1888 */
1889function pushHistory( state, url) {
1890	let title = document.title;
1891	if( url == null) {
1892		url = document.location.href;
1893	}
1894	state.title = title;
1895
1896	console.log( 'push : ' + JSON.stringify( state));
1897	if (isFirst) {
1898		window.history.replaceState(state, title, url);
1899		isFirst = false;
1900	} else {
1901		window.history.pushState( state, title, url);
1902	}
1903}
1904
1905
1906
1907/**
1908 * popState 시 id별 등록된 함수 관리(추가, 실행, 삭제, 비우기)
1909 * @see https://api.jquery.com/category/callbacks-object/
1910 * @param id
1911 * @returns {*}
1912 * @constructor
1913 */
1914jQuery.popStateAction = function (id) {
1915	let callbacks,
1916		action = id && actions[ id ];
1917
1918	if ( !action ) {
1919		callbacks = jQuery.Callbacks();
1920		action = {
1921			fire: callbacks.fire,
1922			add: callbacks.add,
1923			remove: callbacks.remove,
1924			empty: callbacks.empty
1925		};
1926		if ( id ) {
1927			actions[ id ] = action;
1928		}
1929	}
1930	return action;
1931};
1932
1933window.addEventListener('popstate', (event) => {
1934	if (event.state != null) {
1935		console.log( 'pop ' + JSON.stringify( event.state));
1936		let state = event.state;
1937		let action = state.action;
1938		document.title = state.title;
1939		// popstate로 처리할경우 pushstate안하도록 flag 처리
1940		state.isHistory = true;
1941
1942		// 등록된 action을 실행
1943		$.popStateAction(action).fire(state);
1944	}
1945});
1946
1947function unescapeHtml( text ) {
1948    var doc = new DOMParser().parseFromString(text, "text/html");
1949    return doc.documentElement.textContent;
1950}
1951
1952function loadTmpl (options) {
1953	let tmpl = typeof(options) == 'string' ? options :   options.name;
1954	let deferred = $.Deferred();
1955	if ($.templates[tmpl]) {
1956		deferred.resolve();
1957	} else {
1958		$.getScript("/step/js/tmpl/" + tmpl + ".js")
1959			.then(function () {
1960				if ($.templates[tmpl]) {
1961					deferred.resolve();
1962				} else {
1963					console.log("Script: \"" + tmpl + ".js\" failed to load");
1964					deferred.reject();
1965				}
1966			});
1967	}
1968	return deferred.promise();
1969}
1970
1971//URL 검증  
1972function endWithUrl(){
1973	  // 현재 페이지 URL
1974	  const currentUrl = window.location.href;
1975	  
1976	  if (currentUrl.endsWith('.page') || currentUrl.includes('/portal/')) {
1977		  return "page";
1978	  // 그 외는 .face로 리다이렉트
1979	  }	 else {
1980	  	 return "face";
1981	  }
1982}
1983
1984//공백체크
1985function isEmpty(value){
1986	if( value == "" || value == null || value == undefined || ( value != null && typeof value == "object" && !Object.keys(value).length ) ){
1987		return true;
1988	}else{
1989		return false;
1990	}
1991};
1992
1993function fn_loginPageConfim(){
1994	if(confirm("로그인이 필요한 기능 입니다. 로그인 페이지로 이동하시겠습니까?")){
1995		if(windowCurrentUrl == null){
1996			windowCurrentUrl = window.top.location.href;		
1997		}
1998		var target = "/portal/default/login.page?redirect_url=" + encodeURIComponent(windowCurrentUrl);
1999		
2000    	window.top.location.href = target;
2001	}
2002}

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.