PageSourceSearch

https://gangneung.go.kr/site/www_2025/js/main.js?ver=260424

js gangneung.go.kr collected 2026-10-02 17:25:55 UTC 31,025 bytes, 794 lines download raw bytes

1(function ($) {
2    'use strict';
3
4    $(function () {
5
6        var $window = $(window),
7            $html = $('html'),
8            $wrapper = $('#wrapper'),
9            $container = $('#container');
10		
11		// ITS D-day (기준일: 2026-10-19, NowTime: YYYYMMDDHHmm)
12        var $ddayEm = $('.main_banner .main_banner_anchor .imagebox .dday em');
13        if ($ddayEm.length && typeof NowTime !== 'undefined') {
14            var nowStr = String(NowTime),
15                year = parseInt(nowStr.substr(0, 4), 10),
16                month = parseInt(nowStr.substr(4, 2), 10) - 1,
17                day = parseInt(nowStr.substr(6, 2), 10),
18                nowDate = new Date(year, month, day),
19                targetDate = new Date(2026, 9, 19),
20                dayMs = 24 * 60 * 60 * 1000,
21                dday = Math.round((targetDate - nowDate) / dayMs);
22
23            if (!isNaN(dday)) {
24                $ddayEm.text(dday < 0 ? 0 : dday);
25            }
26        }
27		
28        // 즐겨찾기 더보기
29        var $favorite = $('.favorite'),
30            $favoriteLayer = $('.favorite_layer'),
31            $favoriteMoreButton = $favorite.find('.favorite_button.more'),
32            $favoriteMorePopup = $favoriteLayer.find('.favorite_popup.more'),
33            $favoriteMoreClose = $favoriteMorePopup.find('.favorite_close'),
34            $favoriteSettingButton = $favorite.find('.favorite_button.setting'),
35            $favoriteSettingPopup = $favoriteLayer.find('.favorite_popup.setting'),
36            $favoriteSettingClose = $favoriteSettingPopup.find('.favorite_close');
37
38        // 더보기 팝업 열기
39        $favoriteMoreButton.on('click', function () {
40            $('html').addClass('favorite_more_open');
41            $favoriteMorePopup.attr('tabindex', '-1').focus();
42            trapFocus($favoriteMorePopup);
43        });
44
45        // 더보기 팝업 닫기
46        $favoriteMoreClose.on('click', function () {
47            $('html').removeClass('favorite_more_open');
48            $favoriteMoreButton.focus();
49            releaseFocusTrap();
50        });
51
52        // 설정 팝업 열기
53        $favoriteSettingButton.on('click', function () {
54            $('html').addClass('favorite_setting_open');
55            $favoriteSettingPopup.attr('tabindex', '-1').focus();
56            trapFocus($favoriteSettingPopup);
57        });
58
59        // 설정 팝업 닫기
60        $favoriteSettingClose.on('click', function () {
61            $('html').removeClass('favorite_setting_open');
62            $favoriteSettingButton.focus();
63            releaseFocusTrap();
64        });
65
66        // 포커스 트랩 함수
67        function trapFocus($popup) {
68            setTimeout(function () {
69                var focusableElements = $popup.find('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])');
70                var firstElement = focusableElements.first();
71                var lastElement = focusableElements.last();
72
73                function handleKeydown(e) {
74                    if (e.key === 'Tab') {
75                        if (e.shiftKey) {
76                            if ($(document.activeElement).is(firstElement)) {
77                                e.preventDefault();
78                                lastElement.focus();
79                            }
80                        } else {
81                            if ($(document.activeElement).is(lastElement)) {
82                                e.preventDefault();
83                                firstElement.focus();
84                            }
85                        }
86                    }
87                }
88
89                $popup.data('trapHandler', handleKeydown);
90                $popup.on('keydown', handleKeydown);
91
92                // 포커스를 첫 요소로 이동
93                setTimeout(function () {
94                    if (firstElement.length) {
95                        firstElement.focus();
96                    } else {
97                        $popup.attr('tabindex', '-1').focus();
98                    }
99                }, 10);
100            }, 50); // 팝업 표시 후 약간의 딜레이 확보
101        }
102        function releaseFocusTrap() {
103            $('.favorite_popup').off('keydown._trap');
104        }
105
106
107        /* visual */
108        var $visual = $container.find('.visual'),
109            $visualList = $visual.find('.visual_list'),
110            visualListHtml = $visualList.html(),
111            $visualItem = $visualList.find('.visual_item'),
112            ItemLength = $visualItem.length,
113            $visualCurrent = $visual.find('.visual_current'),
114            $visualTotal =  $visual.find('.visual_total'),
115            $visualAuto = $visual.find('.visual_button.auto'),
116            $visualPrev = $visual.find('.visual_button.prev'),
117            $visualNext = $visual.find('.visual_button.next'),
118            $focuspoint;
119
120        $visualList.slick({
121            infinite : true,
122            slidesToShow : 1,
123            slidesToScroll : 1,
124            autoplay : true,
125            draggable : true,
126            current : $visualCurrent,
127            total : $visualTotal,
128            autoArrow : $visualAuto,
129            prevArrow : $visualPrev,
130            nextArrow : $visualNext,
131            playText : '재생',
132            pauseText : '정지',
133            customState : function(state) {
134                if (state.current < 10) {
135                    state.current = '0' + state.current;
136                }
137                if (state.total < 10) {
138                    state.total = '0' + state.total;
139                }
140                return state;
141            }
142        });
143
144        /* 모아보기 */
145        var $visualAll = $wrapper.find('.visual_all'),
146            $visualAllCount = $visualAll.find('.visual_all_title em'),
147            $visualAllList = $visualAll.find('.visual_all_list'),
148            $visualAllPrev = $visualAll.find('.visual_all_button.prev'),
149            $visualAllNext = $visualAll.find('.visual_all_button.next'),
150            $visualAllCurrent = $visualAll.find('.visual_current'),
151            $visualAllTotal =  $visualAll.find('.visual_total');
152
153        $visualAllList.append(visualListHtml);
154        $visualAllCount.text(ItemLength);
155        $visualAllList.slick({
156            autoplay : false,
157            infinite : true,
158            dots : false,
159            slidesToShow : 1,
160            slidesToScroll : 1,
161            rows : 2,
162            slidesPerRow : 2,
163            prevArrow : $visualAllPrev,
164            nextArrow : $visualAllNext,
165            current : $visualAllCurrent,
166            total : $visualAllTotal,
167            customState : function(state) {
168                if (state.current < 10) {
169                    state.current = '0' + state.current;
170                }
171                if (state.total < 10) {
172                    state.total = '0' + state.total;
173                }
174                return state;
175            },
176            responsive : [
177                {
178                    breakpoint: 641,
179                    settings: {
180                        rows: 2,
181                        slidesToShow: 1,
182                        slidesToScroll: 1,
183                        slidesPerRow : 1,
184                    }
185                }
186            ]
187        });
188
189        var savedScrollTop = 0;
190
191        $('.visual .visual_more').on('click',function(){
192
193            savedScrollTop = $(window).scrollTop();
194            $focuspoint = $(this);
195
196            $('html').addClass('visual_open');
197            $('html, body').scrollTop(0);
198
199            setTimeout(function () {
200                $('.visual_all').focus();
201
202                setTimeout(function () {
203                    $('.visual_all_list .slick-slide:first-child div a').focus();
204                }, 10);
205
206            }, 10);
207
208            $focuspoint = $('.visual .visual_more');
209        });
210
211        $('.visual_all .visual_close').on('click',function(){
212            $('html').removeClass('visual_open');
213            $('html, body').scrollTop(savedScrollTop);
214
215            if ($focuspoint && $focuspoint.length) {
216                $focuspoint.focus();
217            }
218        });
219
220
221        /* board */
222        var $board = $container.find('.board'),
223            $boardTabButton = $board.find('button.tab_button'),
224            $boardContent = $board.find('.board_content'),
225            $boardTabPanel = $board.find('.board_panel');
226
227        function getSlickOpt($panel) {
228            return {
229                slidesToShow: 3,
230                slidesToScroll: 1,
231                infinite: true,
232                draggable: true,
233                arrows: true,
234                prevArrow: $panel.find('.board_button.prev'),
235                nextArrow: $panel.find('.board_button.next'),
236                responsive: [
237                    {
238                        breakpoint: 1301,
239                        settings: {
240                            slidesToShow: 2,
241                        }
242                    }
243                ]
244            };
245        }
246
247        // 초기 슬릭 적용 함수
248        function initBoardSlick() {
249            $boardTabPanel.each(function () {
250                var $panel = $(this);
251                var $list = $panel.find('.board_list');
252
253                if ($(window).width() <= 800) {
254                    if ($list.hasClass('slick-initialized')) {
255                        $list.slick('unslick');
256                    }
257                } else {
258                    if (!$list.hasClass('slick-initialized')) {
259                        $list.slick(getSlickOpt($panel));
260                    }
261                }
262            });
263        }
264        initBoardSlick();
265
266        $(window).on('load resize', function () {
267            initBoardSlick();
268        });
269
270        $boardTabButton.on('click', function () {
271            var $this = $(this),
272                $parent = $this.closest('.tab_item'),
273                parentIndex = $parent.index(),
274                thisText = $this.text(),
275                $activePanel = $boardTabPanel.eq(parentIndex),
276                $list = $activePanel.find('.board_list');
277
278            $parent.addClass('active').siblings().removeClass('active');
279            $this.attr('title', '선택됨');
280            $parent.siblings().find('button.tab_button').removeAttr('title');
281
282            $boardContent.find('.skip').text(thisText + ' 목록');
283            $boardTabPanel.removeClass('active').removeAttr('title');
284            $activePanel.addClass('active').attr('title', '선택됨');
285
286            // 슬릭 재초기화 (현재 탭만)
287            if ($list.hasClass('slick-initialized')) {
288                $list.slick('unslick');
289            }
290
291            if ($(window).width() > 800) {
292                $list.slick(getSlickOpt($activePanel)).slick('setPosition');
293            }
294        });
295
296        $('.board .board_tab .tab_list').on('scroll', function () {
297            var $this = $(this),
298                scrollLeft = $this.scrollLeft(),
299                scrollWidth = $this[0].scrollWidth,
300                outerWidth = $this.outerWidth();
301
302            if (scrollLeft + outerWidth >= scrollWidth - 1) {
303                $this.closest('.board_tab').addClass('end');
304            } else {
305                $this.closest('.board_tab').removeClass('end');
306            }
307        });
308
309
310        /* magazine */
311        var $magazine = $container.find('.magazine'),
312            $magazineTabButton = $magazine.find('.tab_button'),
313            $magazineTabPanel = $magazine.find('.magazine_panel');
314
315        $magazineTabButton.on('click', function () {
316            var $this = $(this),
317                thisText = $(this).text(),
318                $parent = $this.parents('.tab_item'),
319                parentIndex = $parent.index();
320
321            $parent.addClass('active').siblings().removeClass('active');
322            $this.attr('title', '선택됨');
323            $('.magazine_content').find('.skip').text(thisText + ' 목록')
324            $parent.siblings().children('.tab_button').removeAttr('title');
325            $magazineTabPanel.eq(parentIndex).addClass('active').attr('title', '선택됨').siblings().removeClass('active').removeAttr('title');
326        });
327
328
329        /* service */
330        var $service = $container.find('.service'),
331            $serviceItem = $service.find('.service_item'),
332            $serviceItem1 = $service.find('.service_item.n1'),
333            $serviceItem2 = $service.find('.service_item.n2'),
334            $serviceItem3 = $service.find('.service_item.n3'),
335            $serviceButton = $serviceItem.find('.service_button');
336
337        /* service - 민원/행정 */
338        var $serviceSlick1 = $serviceItem1.find('.service_slick'),
339            $servicePrev = $serviceItem1.find('.service_prev'),
340            $serviceNext = $serviceItem1.find('.service_next');
341
342        $serviceSlick1.slick({
343            autoplay : false,
344            infinite : false,
345            slidesToShow : 1,
346            slidesToScroll : 1,
347            arrows : true,
348            prevArrow: $servicePrev,
349            nextArrow: $serviceNext,
350            dots : true,
351            appendDots : $serviceItem1.find('.service_dots'),
352            customPaging : function(slider, i) {
353                return '<button type="button"><span>'+(i + 1)+'번째 보기</span></button>';
354            }
355        });
356
357        /* service - 민원/행정 */
358        var $serviceSlick2 = $serviceItem2.find('.service_slick'),
359            $servicePrev = $serviceItem2.find('.service_prev'),
360            $serviceNext = $serviceItem2.find('.service_next');
361
362        $serviceSlick2.slick({
363            autoplay : false,
364            infinite : false,
365            slidesToShow : 1,
366            slidesToScroll : 1,
367            arrows : true,
368            prevArrow: $servicePrev,
369            nextArrow: $serviceNext,
370            dots : true,
371            appendDots : $serviceItem2.find('.service_dots'),
372            customPaging : function(slider, i) {
373                return '<button type="button"><span>'+(i + 1)+'번째 보기</span></button>';
374            }
375        });
376
377        /* service - 분야별정보 */
378        var $serviceSlick3 = $serviceItem3.find('.service_slick'),
379            $servicePrev = $serviceItem3.find('.service_prev'),
380            $serviceNext = $serviceItem3.find('.service_next');
381
382        $serviceSlick3.slick({
383            autoplay : false,
384            infinite : false,
385            slidesToShow : 5,
386            slidesToScroll : 5,
387            arrows : true,
388            prevArrow: $servicePrev,
389            nextArrow: $serviceNext,
390            dots : true,
391            appendDots : $serviceItem3.find('.service_dots'),
392            customPaging : function(slider, i) {
393                return '<button type="button"><span>'+(i + 1)+'번째 보기</span></button>';
394            },
395            responsive: [
396                {
397                    breakpoint: 1301,
398                    settings: {
399                        slidesToShow: 3,
400                        slidesToScroll : 3,
401                    }
402                },
403                {
404                    breakpoint: 1001,
405                    settings: {
406                        slidesToShow: 5,
407                        slidesToScroll : 5,
408                    }
409                },
410                {
411                    breakpoint: 801,
412                    settings: {
413                        slidesToShow: 4,
414                        slidesToScroll : 4,
415                    }
416                },
417                {
418                    breakpoint: 641,
419                    settings: {
420                        slidesToShow: 5,
421                        slidesToScroll : 5,
422                    }
423                },
424                {
425                    breakpoint: 481,
426                    settings: {
427                        slidesToShow: 4,
428                        slidesToScroll : 4,
429                    }
430                },
431            ]
432        });
433
434        $serviceButton.on('click', function () {
435            var $this = $(this),
436                $parent = $this.closest('.service_item');
437
438            $parent.addClass('active').attr('title', '선택됨').siblings().removeClass('active').removeAttr('title');
439
440            if ($parent.hasClass('n1')) {
441                $serviceSlick1.slick('slickGoTo', 0, true);
442                setTimeout(function () {
443                    $serviceSlick1.slick('setPosition');
444                }, 10);
445            }
446            if ($parent.hasClass('n2')) {
447                $serviceSlick2.slick('slickGoTo', 0, true);
448                setTimeout(function () {
449                    $serviceSlick2.slick('setPosition');
450                }, 10);
451            }
452            if ($parent.hasClass('n3')) {
453                $serviceSlick3.slick('slickGoTo', 0, true);
454                setTimeout(function () {
455                    $serviceSlick3.slick('setPosition');
456                }, 10);
457            }
458        });
459
460
461        /* sns */
462        var $sns = $container.find('.sns'),
463            $snsTabButton = $sns.find('button.tab_button'),
464            $snsTabPanel = $sns.find('.sns_panel'),
465            $snsPrev = $sns.find('.sns_button.prev'),
466            $snsNext = $sns.find('.sns_button.next'),
467            $snsSlickOpt = {
468                slidesToShow : 2,
469                slidesToScroll : 1,
470                infinite : false,
471                autoplay : false,
472                draggable : true,
473                arrows : true,
474                prevArrow : $snsPrev,
475                nextArrow : $snsNext,
476                responsive: [
477                    {
478                        breakpoint: 1301,
479                        settings: {
480                            slidesToShow: 1,
481                        }
482                    },
483                    {
484                        breakpoint: 1001,
485                        settings: {
486                            slidesToShow: 3,
487                            variableWidth : true,
488                            infinite : true,
489                        }
490                    },
491                ]
492            }
493
494		function setNoneClass($scope){
495			var $items = $scope.find('.tab_item');
496
497			$items.removeClass('inactive inactive-first');
498			$items.not('.active').addClass('inactive');
499
500			$items.filter('.inactive').first().addClass('inactive-first');
501		}
502
503        $('.sns .sns_panel.active .sns_list').slick($snsSlickOpt).on('beforeChange', function (event, slick, currentSlide, nextSlide) {
504            if (currentSlide !== nextSlide) {
505                $('.slick-active + .slick-cloned').each(function (index, node) {
506                    var $node = $(node);
507                    setTimeout(function () {
508                        $node.addClass('slick-current');
509                        $node.addClass('slick-active');
510                    });
511                });
512            }
513        });
514
515
516        $snsTabButton.on('click', function (event) {
517            var $this = $(this),
518                $parent = $this.parents('.tab_item'),
519                parentIndex = $parent.index();
520
521            $parent.addClass('active').siblings().removeClass('active');
522			
523			setNoneClass($parent.closest('.sns_list')); //251226 추가
524
525            $this.attr('title', '선택됨');
526            $parent.siblings().children('button.tab_button').removeAttr('title');
527            $snsTabPanel.eq(parentIndex).addClass('active').attr('title', '선택됨').siblings().removeClass('active').removeAttr('title');
528
529            $snsTabPanel.each(function () {
530                $snsTabPanel.eq(parentIndex).find('.sns_list').slick($snsSlickOpt).slick('setPosition');
531            })
532        });
533
534
535        /* popupzone */
536        var $popupzone = $container.find('.popupzone'),
537            $popupzoneList = $popupzone.find('.popupzone_list'),
538            popupzoneListHtml = $popupzoneList.html(),
539            $popupzoneItem = $popupzoneList.find('.popupzone_item'),
540            ItemLength = $popupzoneItem.length,
541            $popupzoneCurrent = $popupzone.find('.popupzone_current'),
542            $popupzoneTotal =  $popupzone.find('.popupzone_total'),
543            $popupzoneAuto =  $popupzone.find('.popupzone_button.auto'),
544            $popupzonePrev =  $popupzone.find('.popupzone_button.prev'),
545            $popupzoneNext =  $popupzone.find('.popupzone_button.next'),
546            $focuspoint;
547
548 
548       $popupzoneList.slick({
549            slidesToShow: 1,
550            autoplay: true,
551            infinite: true,
552            current : $popupzoneCurrent,
553            total : $popupzoneTotal,
554            playText: '재생',
555            pauseText: '정지',
556            autoArrow: $popupzoneAuto,
557            prevArrow: $popupzonePrev,
558            nextArrow: $popupzoneNext,
559            customState : function(state) {
560                if (state.current < 10) {
561                    state.current = '0' + state.current;
562                }
563                if (state.total < 10) {
564                    state.total = '0' + state.total;
565                }
566                return state;
567            }
568        });
569
570        /* 모아보기 */
571        var $popupzoneAll = $wrapper.find('.popupzone_all'),
572            $popupzoneAllCount = $popupzoneAll.find('.popupzone_all_title em'),
573            $popupzoneAllList = $popupzoneAll.find('.popupzone_all_list'),
574            $popupzoneAllPrev = $popupzoneAll.find('.popupzone_all_button.prev'),
575            $popupzoneAllNext = $popupzoneAll.find('.popupzone_all_button.next'),
576            $popupzoneAllCurrent = $popupzoneAll.find('.popupzone_current'),
577            $popupzoneAllTotal =  $popupzoneAll.find('.popupzone_total');
578
579        $popupzoneAllList.append(popupzoneListHtml);
580        $popupzoneAllCount.text(ItemLength);
581        $popupzoneAllList.slick({
582            autoplay : false,
583            infinite : true,
584            dots : false,
585            slidesToShow : 1,
586            slidesToScroll : 1,
587            rows : 2,
588            slidesPerRow : 3,
589            prevArrow : $popupzoneAllPrev,
590            nextArrow : $popupzoneAllNext,
591            current : $popupzoneAllCurrent,
592            total : $popupzoneAllTotal,
593            customState : function(state) {
594                if (state.current < 10) {
595                    state.current = '0' + state.current;
596                }
597                if (state.total < 10) {
598                    state.total = '0' + state.total;
599                }
600                return state;
601            },
602            responsive : [
603                {
604                    breakpoint: 641,
605                    settings: {
606                        slidesPerRow : 2,
607                    }
608                },
609                {
610                    breakpoint: 481,
611                    settings: {
612                        rows: 2,
613                        slidesPerRow : 1,
614                    }
615                }
616            ]
617        });
618
619        var savedScrollTop = 0;
620
621        $('.popupzone .popupzone_more').on('click',function(){
622
623            savedScrollTop = $(window).scrollTop(); // 현재 스크롤 위치 저장
624            $focuspoint = $(this); // 클릭한 버튼 저장
625
626            $('html').addClass('popupzone_open');
627            $('html, body').scrollTop(0);
628
629            setTimeout(function () {
630                $('.popupzone_all').focus();
631
632                setTimeout(function () {
633                    $('.popupzone_all_list .slick-slide:first-child div a').focus();
634                }, 10);
635
636            }, 10);
637
638            $focuspoint = $('.popupzone .popupzone_more');
639        });
640
641        $('.popupzone_all .popupzone_close').on('click',function(){
642            $('html').removeClass('popupzone_open');
643            $('html, body').scrollTop(savedScrollTop);
644
645            if ($focuspoint && $focuspoint.length) {
646                $focuspoint.focus();
647            }
648        });
649
650
651    });
652})(window.jQuery);
653
654
655document.addEventListener('DOMContentLoaded', function () {
656    const favoriteList = document.querySelector('.favorite .favorite_wrap .favorite_list');
657    const settingButton = document.querySelector('.favorite .favorite_button.setting');
658    const closeSettingButton = document.querySelector('.favorite_popup.setting .favorite_close');
659    const saveButton = document.querySelector('.favorite_button.save');
660    const resetButton = document.querySelector('.favorite_button.reset');
661    const favoriteSettingPopup = document.querySelector('.favorite_popup.setting');
662
663    // 필수 DOM 없으면 종료(페이지 구성 다를 때 에러 방지)
664    if (!favoriteList || !settingButton || !closeSettingButton || !saveButton || !resetButton || !favoriteSettingPopup) return;
665
666    // 링크 매핑
667    const LINK_MAP = {
668        item1:  { href: 'https://www.gn.go.kr/yeyak/index.do', blank: true },
669        item2:  { href: 'https://www.gn.go.kr/www/contents.do?key=2830', blank: false },
670        item3:  { href: 'https://www.gn.go.kr/www/selectEmployeeList.do?key=735&mode=DEF', blank: false },
671        item4:  { href: 'https://www.gn.go.kr/waterpay/ncoe/index.do', blank: true },
672        item5:  { href: 'https://bis.gn.go.kr/', blank: true },
673        item6:  { href: 'https://www.gn.go.kr/www/selectGosiNttList.do?key=263&searchGosiSe=01,04,06', blank: false },
674        item7:  { href: 'https://www.gn.go.kr/www/contents.do?key=1395', blank: false },
675        item8:  { href: 'https://www.gn.go.kr/gnlll/index.do', blank: true },
676        item9:  { href: 'https://www.gn.go.kr/www/contents.do?key=187', blank: false },
677        item10: { href: 'https://www.gn.go.kr/www/contents.do?key=734', blank: false },
678        item11: { href: 'https://www.gn.go.kr/www/contents.do?key=736', blank: false },
679        item12: { href: 'https://www.gn.go.kr/www/contents.do?key=738', blank: false },
680        item13: { href: 'https://www.gn.go.kr/www/contents.do?key=1121', blank: false },
681        item14: { href: 'https://www.gn.go.kr/www/selectBbsNttList.do?bbsNo=131&key=450', blank: false },
682        item15: { href: 'https://its.gn.go.kr/main', blank: true },
683        item16: { href: 'https://www.gn.go.kr/parkingsms/member/index.php', blank: true },
684        item17: { href: 'https://www.gn.go.kr/smartMap/selectSmartMapWebView.do', blank: true },
685        item18: { href: 'https://www.gn.go.kr/www/contents.do?key=4586', blank: false },
686        item19: { href: 'https://www.gn.go.kr/gyeyak/', blank: true },
687        item20: { href: 'https://www.gn.go.kr/www/contents.do?key=5510', blank: false },
688        item21: { href: 'https://www.gn.go.kr/yeyak/selectUnityEventWebList.do?key=6420', blank: true },
689        item22: { href: 'https://gn.go.kr/kickboard/', blank: true },
690        item23: { href: 'https://www.gn.go.kr/www/selectBbsNttList.do?bbsNo=1630&key=6852', blank: false }
691    };
692
693    // 새 기본값
694	const NEW_DEFAULT = ['item23', 'item1', 'item21', 'item2', 'item4', 'item5', 'item7', 'item8']; 
695    // 예전 기본값
696    const OLD_DEFAULT = ['item23', 'item1', 'item21', 'item2', 'item4', 'item5', 'item7', 'item8']; 
697	/* const OLD_DEFAULT = ['item1', 'item2', 'item3', 'item4', 'item5', 'item6', 'item7', 'item8']; */
698
699    function safeParse(json) {
700        try { return JSON.parse(json); } catch (e) { return null; }
701    }
702
703    function sameArray(a, b) {
704        return Array.isArray(a) && Array.isArray(b)
705            && a.length === b.length
706            && a.every((v, i) => v === b[i]);
707    }
708
709    // 저장값 읽기
710    const saved = safeParse(localStorage.getItem('favoriteItems1'));
711
712    // 새 기본값으로 세팅
713    if (!Array.isArray(saved) || sameArray(saved, OLD_DEFAULT)) {
714        localStorage.setItem('favoriteItems1', JSON.stringify(NEW_DEFAULT));
715    }
716
717    // 이벤트
718    settingButton.addEventListener('click', function () {
719        favoriteSettingPopup.style.display = 'block';
720        loadCheckedItems();
721    });
722
723    closeSettingButton.addEventListener('click', function () {
724        favoriteSettingPopup.style.display = 'none';
725    });
726
727    saveButton.addEventListener('click', function () {
728        const selectedItems = Array.from(
729            document.querySelectorAll('.favorite_menu input[type="checkbox"]:checked')
730        ).map(cb => cb.dataset.id);
731
732        if (selectedItems.length > 8) {
733            alert('즐겨찾기는 최대 8개까지 선택할 수 있습니다.');
734            return;
735        }
736
737        localStorage.setItem('favoriteItems1', JSON.stringify(selectedItems));
738        favoriteSettingPopup.style.display = 'none';
739        loadPage();
740    });
741
742    resetButton.addEventListener('click', function () {
743        document.querySelectorAll('.favorite_menu input[type="checkbox"]').forEach(cb => (cb.checked = false));
744    });
745
746    function loadCheckedItems() {
747        const favorites = safeParse(localStorage.getItem('favoriteItems1')) || [];
748        document.querySelectorAll('.favorite_menu input[type="checkbox"]').forEach(cb => {
749            cb.checked = favorites.includes(cb.dataset.id);
750        });
751    }
752
753    // label(for=itemId)에서 아이콘/텍스트 가져오기
754    function getDisplayData(itemId) {
755        const label = document.querySelector(`.favorite_popup.setting label[for="${itemId}"]`);
756        if (!label) return null;
757
758        const iconEl = label.querySelector('i.favorite_icon');
759        if (!iconEl) return null;
760
761        const nClass = Array.from(iconEl.classList).find(c => /^n\d+$/.test(c)) || '';
762        const text = label.querySelector('.favorite_label')?.textContent?.trim() || '';
763
764        return { nClass, iconClass: iconEl.className, text };
765    }
766
767    // 메인 8칸 생성
768    function loadPage() {
769        const favorites = safeParse(localStorage.getItem('favoriteItems1')) || [];
770        favoriteList.innerHTML = '';
771
772        favorites.slice(0, 8).forEach(itemId => {
773            const data = getDisplayData(itemId);
774            if (!data) return;
775
776            const linkInfo = LINK_MAP[itemId] || { href: '#', blank: false };
777
778            const li = document.createElement('li');
779            li.className = `favorite_item ${data.nClass}`;
780            li.innerHTML = `
781        <a href="${linkInfo.href}" class="favorite_anchor" data-id="${itemId}"
782           ${linkInfo.blank ? 'target="_blank" title="새창"' : ''}>
783          <i class="${data.iconClass}"></i>
784          <span>${data.text}</span>
785        </a>
786      `;
787            favoriteList.appendChild(li);
788        });
789    }
790
791    // 최초 렌더링
792    loadPage();
793});
794

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.