PageSourceSearch

https://www.cnmh.go.kr/main/js/func.js

js cnmh.go.kr collected 2026-10-05 05:31:21 UTC 16,102 bytes, 395 lines download raw bytes

1const AC = 'active',
2    FX = 'fixed',
3    ALL = 'all_nav',
4    ScrollNo = 'scroll-no',
5    srOnly = '.sr-only',    
6    OpenTxt = '열기',
7    CloseTxt = '닫기',
8    $html = $('html');
9
10/*  mobile ------------------------------------------------------------------------------ */
11function mobile() {
12    return window.innerWidth < 1024 ? 1 : 0 //ipad pro는 넓어서 web화면이 나오게
13}
14/*  initial setup of accessibility ------------------------------------------------------- */
15function accessInit(el) {
16    $(el).attr('aria-expanded', 'false')
17    //$(el).append('<span class="sr-only">' + OpenTxt + '</span>').attr('aria-expanded', 'false')
18}
19
20/* --------------------------------------------------------------------------------------
21*   화면크기
22----------------------------------------------------------------------------------------- */
23function zoom(el) {
24    const   zoomLevels = [0.9, 1, 1.1, 1.2, 1.3],
25            classNames = ['xsm', 'sm', 'md', 'lg', 'xlg'],
26            $item = $(el);
27    let zoom = 1;        
28    
29    $html.on('click', el, function(){
30        const $na = $(this);
31
32        $na.attr('aria-selected', true).parent().addClass(AC).siblings().removeClass(AC).children().removeAttr('aria-selected')/*.attr('aria-selected', false)*/
33        $.each(classNames, function(index, className) {
34            if ($na.hasClass(className)) zoom = zoomLevels[index];
35        });
36        //초기화
37        if($na.hasClass('ico-reset')) {
38            $html.css('zoom', 1);
39            $item.eq(1).attr('aria-selected', true).parent().addClass(AC).siblings().removeClass(AC).children().removeAttr('aria-selected')/*.attr('aria-selected', false)*/
40        }
41        localStorage.setItem('zoomDefault', zoom);
42        $html.css('zoom', zoom);
43    })
44
45    //로컬 저장
46    zoom = localStorage.getItem('zoomDefault') || 1;
47    $html.css('zoom', zoom);
48    $.each(zoomLevels, function (index, zoomLevel){
49        if(zoom == zoomLevel) $item.eq(index).attr('aria-selected', true).parent().addClass(AC)
50    })
51}
52
53/*  ---------------------------------------------------------------------------------------
54*    gnb
55----------------------------------------------------------------------------------------- */
56function gnb() {
57    const   $gnb = $('#head_menu'),            
58            $depth1 = $gnb.find('>li>a:not(.linkWindow)'),
59            $depth2 = $gnb.find('.submenu>ul>li>a:not(.linkWindow)');
60
61    //초기셋팅 - 1차뎁스 접근성, 2차뎁스 첫번째 메뉴 활성
62    accessInit($depth1)
63    accessInit($depth2)
64    $gnb.find('>li>a.active').attr('aria-current', 'page')
65    $('.subfirst').addClass(AC).find('>a').attr('aria-expanded', 'true')
66
67    //1차, 2차뎁스 클릭
68    $depth1.add($depth2).on('click', function(e) {
69        const $na = $(this)
70
71        e.preventDefault()
72        $html.addClass(AC)//배경 dim처리
73        $na.attr('aria-expanded', 'true').parent().addClass(AC).siblings().removeClass(AC).find('>a:not(.linkWindow)').attr('aria-expanded', 'false')
74    })
75
76    //2차뎁스 타이틀 생성
77    $depth2.each(function(){
78        if(!$(this).next().is("div")) $(this).after("<div></div>")
79        $(this).next("div").prepend($(this).clone()).find('a').removeAttr('aria-expanded');
80    })
81
82    //열린 메뉴 닫기
83    function gnbClose() {
84        $depth1.attr('aria-expanded', 'false').parent().add($html).removeClass(AC)
85    }    
86    $html.on('click keyup', function(e) {
87        if(!$(e.target).closest($gnb).length) gnbClose()
88    })
89    $(window).on('scroll', function() { gnbClose() }) //2차뎁스가 열린상태에서 스크롤시
90}
91
92/*  ---------------------------------------------------------------------------------------
93*    mGnb
94----------------------------------------------------------------------------------------- */
95function mGnb(){
96    const $mGnbWrap = $('.m-gnb-wrap'),
97          $mGnb = $('.topmenu-all');
98
99    $('.m-gnb-top-etc').prepend($('#header').find('.etc-ul').clone());  
100    $mGnb.children('li').eq(0).addClass(AC)
101    $('#m-gnb-open').on('click', function() {
102        $(this).add($mGnbWrap).toggleClass(AC)
103        $html.addClass(ScrollNo)
104    })
105    $mGnbWrap.on('click', '.ico-close', function() {
106        $mGnbWrap.removeClass(AC)
107        $html.removeClass(ScrollNo)
108    })
109    $mGnb.on('click', '>li>a', function(e) {
110        e.preventDefault()
111        $(this).parent().addClass(AC).siblings().removeClass(AC)
112    })
113
114    //모바일에서 Active 찾아서 활성화
115    $mGnb.find('>li').each(function(){
116        if ($(this).children().hasClass(AC)) {
117            $(this).addClass(AC).siblings().removeClass(AC)            
118        }       
119    })  
120    
121}
122
123/*  -------------------------------------------------------------------------------------
124*   snb
125----------------------------------------------------------------------------------------- */
126function snb(){
127	const   $snb = $('#snb');
128
129    // snb 접근성 세팅
130    $snb.find('#left_menu_top li>a').each(function(){
131        const   $na = $(this),
132                $parent = $na.parent(),
133                isActive = $parent.hasClass(AC);
134
135        if (isActive) $na.attr('aria-current', 'page')
136        if ($na.next('ul').length > 0) { //3차뎁스
137            $na.attr('aria-expanded', isActive ? 'true' : 'false').removeAttr('aria-current')
138            $parent.addClass('is-depth3')
139        }
140    });
141
142    // 하위 3차뎁스를 갖고 있는 메뉴를 클릭했을때
143    $snb.on('click', '.is-depth3>a', function(e) {
144        const   $na = $(this),
145                $parent = $na.parent(),
146                isActive = $parent.hasClass(AC);
147        
148        e.preventDefault()
149        if (!isActive){
150            $parent.addClass(AC).siblings().removeClass(AC)
151            $('.is-depth3').find('>a').attr('aria-expanded', 'false')
152            $na.attr('aria-expanded', 'true')
153        }
154    }); 
155}
156
157/*  -------------------------------------------------------------------------------------
158*   리스트 열고 닫기			listOpen('.sns .sns_btn', 'target클래스명') 
159----------------------------------------------------------------------------------------- */
160function listOpen(el, target, noAnyClick){
161    accessInit(el);
162
163    const $el = $(el);
164
165    $html.on('click', el, function(e) { 
166        const   $na = $(this),
167                $elTarget = $na.closest(target),
168                isActive = $elTarget.hasClass(AC)
169
170        e.preventDefault()     
171        if(!isActive) $html.trigger('click')
172        $elTarget.toggleClass(AC)     
173        $na.attr('aria-expanded', isActive ? 'false' : 'true') 
174        .find(srOnly).text(isActive ? OpenTxt : CloseTxt)
175    })
176    if(!noAnyClick){
177        $html.on('click', function(e) {
178            if(!$(e.target).closest(target).length){
179                $(target).removeClass(AC)
180                .find(el).attr('aria-expanded', 'false')
181                .find(srOnly).text(OpenTxt)
182            }
183        })
184    }
185    $(target).on('click', '.btn-close', function(e){
186        $el.trigger('click');
187    })
188}
189
190/*  -------------------------------------------------------------------------------------
191*   data값으로 열고 닫기			dataOpen('클릭할 클래스명') 
192----------------------------------------------------------------------------------------- */
193function dataOpen(el){
194    accessInit(el);
195
196    $(el).on('click', function() {			
197        const   $na = $(this),
198                isActive = $na.hasClass(AC)
199        $('#' + $na.data('id')).toggle();
200        $na.toggleClass(AC).attr('aria-expanded', isActive ? 'false' : 'true').find(srOnly).text(isActive ? OpenTxt : CloseTxt);
201    }) 
202}
203
204/*  -------------------------------------------------------------------------------------
205*   팝업 또는 레이어 열고 닫기
206----------------------------------------------------------------------------------------- */
207let $clickSpot;
208
209function layerPopup(el){
210    accessInit(el);
211    const OL = 'opened-layer';
212
213	$(el).on('click', function(e) {	
214        e.preventDefault();
215
216        $clickSpot = $(this);
217        const isActive = $clickSpot.hasClass(AC);
218
219        $clickSpot.toggleClass(AC).attr('aria-expanded', isActive ? 'false' : 'true')
220		$('#' + $(this).data('id')).attr('tabindex', 0).fadeIn(300).focus().addClass(OL);
221		$html.addClass(ScrollNo);
222    })	
223
224	$html.on('click', '.opened-layer .popup-close', function(e) {	
225        e.preventDefault();
226        $(this).closest('.opened-layer').removeAttr('tabindex').fadeOut(100).removeClass(OL);
227		$html.removeClass(ScrollNo);
228		$clickSpot.focus().removeClass(AC).attr('aria-expanded', 'false');
229    })
230
231    $html.on('keydown', '.opened-layer .popup-close', function(e) {
232        if(e.keyCode == 9) $(this).closest('.opened-layer').focus();
233       })
234}
235
236/*  -------------------------------------------------------------------------------------
237*    tab메뉴 - 페이지가 전환되는 탭메뉴(ex. depth4, depth5)             tabs(this)
238*    tab메뉴와 콘텐츠가 포함된 경우                                     tabs(this, "탭콘텐츠")
239----------------------------------------------------------------------------------------- */
240function tabs(el, cont) {
241    const tabLi = $(el).find('>li').length
242	$(el).addClass("num" + tabLi + "")
243
244	
245	//탭콘텐츠 내에서 전환되는 경우
246	if(cont) {
247        //탭메뉴 접근성
248        $(el).find('li.active')
249            .children('a, button').attr('aria-selected', true)
250            .parent().siblings('li').find('>a, >button').attr('aria-selected', false)
251
252        $(el).on("click", ">li>a, >li>button", function(e){
253            $(this).attr('aria-selected', true).parent().addClass(AC)
254            .siblings().removeClass(AC).find(">button, >a").attr('aria-selected', false)
255            $("#"+$(this).data('id')).addClass(AC).siblings().removeClass(AC)
256            e.preventDefault()
257        })
258	}else{
259        //탭메뉴 접근성
260        $(el).find('li.active')
261            .children('a, button').attr('aria-current', 'page')
262
263        //탭메뉴(모바일)
264        $(el).find('li>a, li>button').on("click", function(e) {
265            if (mobile() && $(this).parent().hasClass(AC)) {
266                e.preventDefault()
267                $(this).parents(el).toggleClass(AC)
268            }
269        })
270        //탭메뉴(모바일) : 벗어난 곳 클릭시 탭메뉴 닫히게
271        $html.on('click', function(e) {
272            if(!$(e.target).closest(el).length) $(el).removeClass(AC)
273        })
274    }
275}
276
277
278/* --------------------------------------------------------------------------------------
279*   아코디언 - details로 수정( ※name속성을 W3C Validation에서 오류로 인식하기 때문에 data-name으로 그룹설정)
280----------------------------------------------------------------------------------------- */
281function accordion(el){
282    const $el = $(el)
283    
284    //전체 details 스캔해서 open 되어 있는거에 active지정
285    $el.children('details').each(function(){
286        $(this).attr('open') ? $(this).addClass(AC).find('summary i').append('<span class="sr-only">' + CloseTxt + '</span>') : $(this).removeClass(AC).find('summary i').append('<span class="sr-only">' + OpenTxt + '</span>')
287    }) 
288    
289    //summary클릭했을때
290	$el.on('click', 'summary', function(){           
291        const   $details = $(this).parent('details'),
292                isOpen = $details.attr('open'),
293                $accordion = $(this).parents(el),
294                $btnAll = $accordion.find('.btn-all');
295
296        $details.toggleClass(AC, !isOpen).find("summary i .sr-only").text(!isOpen ? CloseTxt : OpenTxt)
297
298        //details가 열리면? 전체버튼 닫기 : 열기
299        $accordion.children('details').hasClass(AC) ? $btnAll.addClass(AC).find("span").text(CloseTxt) : $btnAll.removeClass(AC).find("span").text(OpenTxt)        
300    })
301
302    //전체 버튼 클릭했을때
303    $el.on('click', '.btn-all', function () {
304        $(this).hasClass(AC) ? $(this).parents(el).find('details.active summary').trigger('click') : $(this).parents(el).find('summary').trigger('click');
305    })
306}
307
308
309
310/*  -------------------------------------------------------------------------------------
311* dialog
312----------------------------------------------------------------------------------------- */
313
314function dialogPop(){
315    document.addEventListener('click', function(event) {
316        const target = event.target;
317        if (target.classList.contains('open-dialog')) {
318            const dialogId = target.dataset.target;
319            const dialog = document.getElementById(dialogId);
320            if (dialog) {
321                dialog.showModal();
322            }
323        } else if (target.classList.contains('btn-close') || target.closest('.btn-close') || target.classList.contains('btn-cancel')){
324            const dialog = target.closest('.dialog');
325            if (dialog) {
326                dialog.close();
327            }
328        }
329    });     
330}
331 
332
333/*  -------------------------------------------------------------------------------------
334* 첨부파일
335----------------------------------------------------------------------------------------- */
336function fileLoad(fileBox) {
337    let $fileBox = $(fileBox);
338    $.each($fileBox, function(idx){
339        var $this = $fileBox.eq(idx),
340            $btnUpload = $this.find('[type="file"]'),
341            $label = $this.find('.file-label');
342        
343        $btnUpload.on('change', function() {
344            var $target = $(this),
345                fileName = $target.val(),
346                $fileText = $target.siblings('.file-name');
347            $fileText.val(fileName);
348        })        
349        $btnUpload.on('focusin focusout', function(e) {
350            e.type == 'focusin' ?
351            $label.addClass('file-focus') : $label.removeClass('file-focus');
352        })    
353    })
354}	
355
356/* --------------------------------------------------------------------------------------
357*   공통 - header 고정, top버튼, 접근성(아이콘, target처리)
358----------------------------------------------------------------------------------------- */
359$(function(){
360    //header 고정
361    let lastScroll
362    $(window).on('load scroll', function() {
363        let scrollT = $(this).scrollTop()
364        scrollT > lastScroll ? $('#header').addClass(FX) : $('#header').removeClass(FX)
365        lastScroll = scrollT
366    })
367    //top버튼
368    $(window).on('load scroll', function() {
369        $(window).scrollTop() > 0 ? $('.go-top').addClass(FX) : $('.go-top').removeClass(FX)        
370    }) 
371    // web accessibility
372	//$('[class*="ri-"]').attr('aria-hidden', 'true')
373	//$('a[target="_blank"]').attr('title', '새창으로 열림')
374	//$("a[target='_blank')]").not(".board-view .file .file-list .link").attr("title","새창으로 열림");
375	$("a[target='_blank']").not(".board-view .file .file-list .link a").attr("title","새창으로 열림");
376    $('.page-info .current strong').prepend('<span class="sr-only">
376현재 페이지</span>');
377    $('.page-info .current b').prepend('<span class="sr-only">전체 페이지 수</span>');
378
379    //모바일에서 원본이미지보기
380    if(mobile()){
381        $('.img-zoom, .zoom_posi, .img').each(function(){
382            const imgSrc = $(this).find('img').attr('src')
383            $(this).append('<a href="' + imgSrc + '" target="_blank" title="이미지 새창열기" class="btn-zoom"></a>')
384        })
385    }
386
387    //비밀번호 보기
388    $('.btn-pw-view').on('click', function(){
389        $(this).toggleClass(AC)
390        var $pwInput = $(this).prev('input'), $srOnly = $(this).find(srOnly)
391        $pwInput.attr('type') == 'password' ? $pwInput.attr('type', 'text').add($srOnly).text('비밀번호 숨기기') : $pwInput.attr('type', 'password').add($srOnly).text('비밀번호 보기')
392    })  
393
394})
395

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.