PageSourceSearch

https://ratherlow.co.kr/ind-script/optimizer_user.php?filename=nZJ…72b3d3c05e0922fa015ad88&t=1771724963&user=T

js ratherlow.co.kr collected 2026-10-06 14:04:44 UTC 96,599 bytes, 2,648 lines download raw bytes

1$(function(){ 
2    if($(".menuCategory > li").length==0){
3         $(".menuCategory").hide();
4    };
5});
6/* =========================
7 * © MUNDANE
8 * 본 파일은 먼데인이 본 스킨을 위해 제작/구성한 커스텀 JavaScript 코드입니다.
9 * 무단 복제, 수정, 재배포 및 타 프로젝트 사용을 금합니다.
10 * ※ 본 스킨은 jQuery, Swiper 등 제3자 라이브러리를 사용할 수 있으며,
11 * 해당 라이브러리의 권리/라이선스는 각 저작권자에게 있습니다.
12========================= */
13
14
15
16var _0x170d25=_0x5d00;(function(_0x5e6716,_0x108d0b){var _0x4eb7a5=_0x5d00,_0x3ff56c=_0x5e6716();while(!![]){try{var _0x1e911e=-parseInt(_0x4eb7a5(0x9f))/0x1+parseInt(_0x4eb7a5(0xcb))/0x2+-parseInt(_0x4eb7a5(0xa9))/0x3+parseInt(_0x4eb7a5(0x9a))/0x4*(parseInt(_0x4eb7a5(0xd7))/0x5)+parseInt(_0x4eb7a5(0xc1))/0x6+-parseInt(_0x4eb7a5(0xa4))/0x7*(parseInt(_0x4eb7a5(0xa7))/0x8)+parseInt(_0x4eb7a5(0xe6))/0x9;if(_0x1e911e===_0x108d0b)break;else _0x3ff56c['push'](_0x3ff56c['shift']());}catch(_0x1c5b5a){_0x3ff56c['push'](_0x3ff56c['shift']());}}}(_0x5922,0x5c293));function qs(_0x566242,_0x1e6f27){var _0x28e036=_0x5d00;return(_0x1e6f27||document)[_0x28e036(0xbc)](_0x566242);}function qsa(_0x1f2a5d,_0x198325){var _0x484e94=_0x5d00;return Array[_0x484e94(0xa1)][_0x484e94(0xd6)][_0x484e94(0xac)]((_0x198325||document)[_0x484e94(0xd4)](_0x1f2a5d));}function matches(_0x22bf70,_0x26cce3){var _0x261989=_0x5d00;if(!_0x22bf70||_0x22bf70['nodeType']!==0x1)return![];var _0xb505fe=Element['prototype'],_0x78aa9a=_0xb505fe['matches']||_0xb505fe[_0x261989(0xbd)]||_0xb505fe['webkitMatchesSelector'];return _0x78aa9a['call'](_0x22bf70,_0x26cce3);}function _0x5922(){var _0x1ac660=['<div\x20id=\x22','\x20\x20\x20\x20<div\x20class=\x22mundane-license-notice__text\x22>','setHours','body','nodeType','setDate','push','4349691cRwwXT','\x20\x20\x20\x20\x20\x20\x20\x20라이선스\x20정보가\x20확인되지\x20않아\x20안내가\x20표시됩니다.<br/>','18844xhpbJO','\x22\x20class=\x22mundane-license-notice\x22\x20style=\x22display:none;\x22>','.popup_pagination','DOMContentLoaded','jQuery','322615khKXcB','display','prototype','\x20\x20\x20\x20\x20\x20\x20\x20정상\x20사용\x20중이라면\x20<a\x20href=\x22','parentElement','7uLTNrL','div','onclick','5378808nQeQNh','data-','1263036pLiZqb','</a>\x20로\x20문의\x20바랍니다.','getAttribute','call','assign','watchOverflow','style','split','Swiper','hasLicense','contains','stop','http://studiomundane.kr','\x20\x20\x20\x20\x20\x20<strong>라이선스\x20확인\x20안내</strong>','\x20\x20\x20\x20</div>','meta[name=\x22mundane-license\x22]','addEventListener','fraction','dataset','querySelector','msMatchesSelector','createElement','length','.weeks-btn','1964922QEdVvr','content','match','license','insertAdjacentHTML','charAt','cookie','none','MUNDANE','.type-image-text','580332hArZOs','getDate','MUNDANE_SWIPER_PRESETS','fadeIn','=([^;]+)','.swiper-slide','classList','.popup-color[style]','.main-popup','querySelectorAll','\x20\x20\x20\x20\x20\x20<button\x20type=\x22button\x22\x20class=\x22mln-btn\x20mln-close\x22>닫기</button>','slice','735dxeVQl','(^|;)\x5cs*','forEach','className','trim','appendChild','mundane_license_notice','join'];_0x5922=function(){return _0x1ac660;};return _0x5922();}function closest(_0x443cec,_0x5e4bc0){var _0x8f15cd=_0x5d00;while(_0x443cec&&_0x443cec[_0x8f15cd(0xe3)]===0x1){if(matches(_0x443cec,_0x5e4bc0))return _0x443cec;_0x443cec=_0x443cec[_0x8f15cd(0xa3)];}return null;}function getData(_0x20cf8a,_0x2c30a2){var _0x546008=_0x5d00;if(!_0x20cf8a)return'';if(_0x20cf8a[_0x546008(0xbb)]&&_0x20cf8a[_0x546008(0xbb)][_0x2c30a2]!=null)return _0x20cf8a['dataset'][_0x2c30a2];return _0x20cf8a['getAttribute'](_0x546008(0xa8)+_0x2c30a2)||'';}function fadeInEl(_0x3c1688,_0x3f2ed0){var _0x54a08f=_0x5d00;if(!_0x3c1688||!window['jQuery'])return;jQuery(_0x3c1688)[_0x54a08f(0xb4)](!![],!![])[_0x54a08f(0xce)](_0x3f2ed0||0x96);}function fadeOutEl(_0x3a6632,_0x53b5d8){var _0x371c75=_0x5d00;if(!_0x3a6632||!window[_0x371c75(0x9e)])return;jQuery(_0x3a6632)[_0x371c75(0xb4)](!![],!![])['fadeOut'](_0x53b5d8||0x96);}function _0x5d00(_0x3c12a3,_0xb29df0){_0x3c12a3=_0x3c12a3-0x9a;var _0x5922a0=_0x5922();var _0x5d0018=_0x5922a0[_0x3c12a3];return _0x5d0018;}function setCookieUntil(_0x3858ff,_0x4201f0,_0x234acc){var _0x227d97=_0x5d00;document[_0x227d97(0xc7)]=_0x3858ff+'='+encodeURIComponent(_0x4201f0)+';\x20path=/;\x20expires='+_0x234acc['toUTCString']();}function setCookieDays(_0x53d037,_0x3b9d0c,_0x5f4487){var _0x19cd3c=_0
16x5d00,_0x5520c9=new Date();_0x5520c9[_0x19cd3c(0xe4)](_0x5520c9[_0x19cd3c(0xcc)]()+_0x5f4487),setCookieUntil(_0x53d037,_0x3b9d0c,_0x5520c9);}function getCookie(_0x3cb42e){var _0x2f0c68=_0x5d00,_0x45da63=document[_0x2f0c68(0xc7)][_0x2f0c68(0xc3)](new RegExp(_0x2f0c68(0xd8)+_0x3cb42e+_0x2f0c68(0xcf)));return _0x45da63?decodeURIComponent(_0x45da63[0x2]):null;}function hideToday(_0x450d99){var _0x3ebaf2=_0x5d00,_0xaf074b=new Date();_0xaf074b[_0x3ebaf2(0xe1)](0x17,0x3b,0x3b,0x3e7),setCookieUntil(_0x450d99,'Y',_0xaf074b);}function readMundaneLicense(){var _0x4684bf=_0x5d00,_0x528822=qs(_0x4684bf(0xb8));return _0x528822?(_0x528822[_0x4684bf(0xab)](_0x4684bf(0xc2))||'')[_0x4684bf(0xdb)]():'';}function initMundaneLicenseState(){var _0x22616d=_0x5d00;window[_0x22616d(0xc9)]=window[_0x22616d(0xc9)]||{},window[_0x22616d(0xc9)]['license']=readMundaneLicense(),window[_0x22616d(0xc9)][_0x22616d(0xb2)]=!!window['MUNDANE'][_0x22616d(0xc4)];}function hasMundaneLicense(){var _0x410a60=_0x5d00;return!!(window[_0x410a60(0xc9)]&&window[_0x410a60(0xc9)][_0x410a60(0xb2)]);}var LICENSE_NOTICE_ID=_0x170d25(0xdd),LICENSE_CONTACT_ADDR=_0x170d25(0xb5),LICENSE_CONTACT_EMAIL='[email protected]';function buildLicenseNoticeHtml(){var _0x3abd68=_0x170d25;return[_0x3abd68(0xdf)+LICENSE_NOTICE_ID+_0x3abd68(0x9b),'\x20\x20<div\x20class=\x22mundane-license-notice__inner\x22>',_0x3abd68(0xe0),_0x3abd68(0xb6),'\x20\x20\x20\x20\x20\x20<p>','\x20\x20\x20\x20\x20\x20\x20\x20본\x20스킨은\x20<b>MUNDANE(먼데인)</b>의\x20저작물입니다.<br/>',_0x3abd68(0xe7),_0x3abd68(0xa2)+LICENSE_CONTACT_ADDR+'\x22\x20target=\x22_blank\x22\x20rel=\x22noopener\x20noreferrer\x22>'+LICENSE_CONTACT_EMAIL+_0x3abd68(0xaa),'\x20\x20\x20\x20\x20\x20</p>',_0x3abd68(0xb7),'\x20\x20\x20\x20<div\x20class=\x22mundane-license-notice__actions\x22>',_0x3abd68(0xd5),_0x3abd68(0xb7),'\x20\x20</div>','</div>'][_0x3abd68(0xde)]('');}function showLicenseNotice(){var _0x2dfc84=_0x170d25;if(hasMundaneLicense())return;var _0x400b3f=qs('#'+LICENSE_NOTICE_ID);!_0x400b3f&&(document[_0x2dfc84(0xe2)][_0x2dfc84(0xc5)]('beforeend',buildLicenseNoticeHtml()),_0x400b3f=qs('#'+LICENSE_NOTICE_ID)),fadeInEl(_0x400b3f,0x96);}var OVERLAY_ID='popup_overlay',OVERLAY_TARGET_SELECTOR=_0x170d25(0xca);
16function ensureOverlay(){var _0x2ef8b0=_0x170d25,_0x38df28=qs('#'+OVERLAY_ID);return!_0x38df28&&(_0x38df28=document[_0x2ef8b0(0xbe)](_0x2ef8b0(0xa5)),_0x38df28['id']=OVERLAY_ID,_0x38df28[_0x2ef8b0(0xda)]='popup-overlay',_0x38df28[_0x2ef8b0(0xaf)][_0x2ef8b0(0xa0)]=_0x2ef8b0(0xc8),document[_0x2ef8b0(0xe2)][_0x2ef8b0(0xdc)](_0x38df28)),_0x38df28;}function closeOverlayPopup(_0x9a21b8){fadeOutEl(_0x9a21b8,0xc8),fadeOutEl(qs('#'+OVERLAY_ID),0xc8);}function initOverlayBehavior(_0x25a51c){var _0x342894=_0x170d25,_0x436158=ensureOverlay();fadeInEl(_0x436158,0xc8),_0x436158[_0x342894(0xa6)]=function(){closeOverlayPopup(_0x25a51c);};}function getPopupTypeKey(_0x5776ad){var _0x1f71bc=_0x170d25,_0x4a4463=window[_0x1f71bc(0xcd)]||{},_0x3d8221=Object['keys'](_0x4a4463);for(var _0x26b794=0x0;_0x26b794<_0x3d8221[_0x1f71bc(0xbf)];_0x26b794++){if(_0x5776ad[_0x1f71bc(0xd1)][_0x1f71bc(0xb3)](_0x3d8221[_0x26b794]))return _0x3d8221[_0x26b794];}return null;}function buildSwiperOptions(_0x51daa3){var _0x2b8e07=_0x170d25;if(!hasMundaneLicense())return showLicenseNotice(),null;var _0x24659f=qsa('.swiper-slide',_0x51daa3)[_0x2b8e07(0xbf)],_0x102eda=_0x24659f===0x1,_0x37ca7e={'slidesPerView':0x1,'slidesPerGroup':0x1},_0x517167=qs(_0x2b8e07(0x9c),_0x51daa3);_0x517167&&!_0x102eda&&(_0x37ca7e['pagination']={'el':_0x517167,'type':_0x2b8e07(0xba)});if(_0x102eda)return _0x37ca7e['loop']=![],_0x37ca7e[_0x2b8e07(0xae)]=!![],_0x37ca7e;var _0x7ec355=window[_0x2b8e07(0xcd)]||{},_0x46aec1=getPopupTypeKey(_0x51daa3),_0x25fe3f=_0x46aec1?_0x7ec355[_0x46aec1]||{}:{},_0x4c3944={};return Object[_0x2b8e07(0xad)](_0x4c3944,_0x37ca7e),_0x4c3944['loop']=!![],Object[_0x2b8e07(0xad)](_0x4c3944,_0x25fe3f),_0x4c3944;}function initMainPopup(_0x32a0cc){var _0xd65168=_0x170d25;if(!_0x32a0cc)return;_0x32a0cc[_0xd65168(0xaf)]['display']=_0xd65168(0xc8);var _0x486f0e=qsa(_0xd65168(0xd0),_0x32a0cc)[_0xd65168(0xbf)];if(_0x486f0e<0x1)return;var _0x5f8f97=getData(_0x32a0cc,_0xd65168(0xc7))||_0x32a0cc[_0xd65168(0xab)]('id');if(!_0x5f8f97)return;if(!hasMundaneLicense()){showLicenseNotice();return;}!getCookie(_0x5f8f97)&&(fadeInEl(_0x32a0cc,0x96),matches(_0x32a0cc,OVERLAY_TARGET_SELECTOR)&&initOverlayBehavior(_0x32a0cc));var _0x53e824=qs('.swiper',_0x32a0cc);if(_0x53e824&&window[_0xd65168(0xb1)]){var _0x3eaaba=buildSwiperOptions(_0x32a0cc);if(_0x3eaaba)new Swiper(_0x53e824,_0x3eaaba);}}document[_0x170d25(0xb9)]('click',function(_0x11d852){var _0x2799ad=_0x170d25,_0x4f820e=_0x11d852['target'];if(closest(_0x4f820e,'#'+LICENSE_NOTICE_ID+'\x20.mln-close')){fadeOutEl(qs('#'+LICENSE_NOTICE_ID),0x96);return;}var _0x3f7a52=closest(_0x4f820e,_0x2799ad(0xd3));if(!_0x3f7a52)return;var _0x51dbbd=getData(_0x3f7a52,_0x2799ad(0xc7))||_0x3f7a52[_0x2799ad(0xab)]('id');if(!_0x51dbbd)return;if(closest(_0x4f820e,'.today-btn')){hideToday(_0x51dbbd),fadeOutEl(_0x3f7a52,0x96),fadeOutEl(qs('#'+OVERLAY_ID),0x96);return;}if(closest(_0x4f820e,_0x2799ad(0xc0))){setCookieDays(_0x51dbbd,'Y',0x7),fadeOutEl(_0x3f7a52,0x96),fadeOutEl(qs('#'+OVERLAY_ID),0x96);return;}closest(_0x4f820e,'.close-btn')&&(matches(_0x3f7a52,OVERLAY_TARGET_SELECTOR)?closeOverlayPopup(_0x3f7a52):fadeOutEl(_0x3f7a52,0x96));});function liftPopupColorVarsToRoot(){var _0x26e905=_0x170d25;qsa(_0x26e905(0xd3))[_0x26e905(0xd9)](function(_0x404e86){var _0xd24f68=_0x26e905,_0x15b900=qs(_0xd24f68(0xd2),_0x404e86);if(!_0x15b900)return;var _0x246041=_0x15b900[_0xd24f68(0xab)](_0xd24f68(0xaf));if(!_0x246041)return;var _0x4bd37e=_0x246041['split'](';'),_0xea5ab0=[];for(var _0x73cf9b=0x0;_0x73cf9b<_0x4bd37e[_0xd24f68(0xbf)];_0x73cf9b++){var _0x45b87d=_0x4bd37e[_0x73cf9b][_0xd24f68(0xdb)]();if(!_0x45b87d)continue;var _0xf84198=_0x45b87d[_0xd24f68(0xb0)](':');if(_0xf84198['length']<0x2)continue;var _0x141f56=_0xf84198[0x0]['trim'](),_0x3bcd35=_0xf84198[_0xd24f68(0xd6)](0x1)['join'](':')[_0xd24f68(0xdb)]();_0x3bcd35[_0xd24f68(0xc6)](0x0)==='#'&&_0xea5ab0[_0xd24f68(0xe5)](_0x141f56+':'+_0x3bcd35);}if(_0xea5ab0['length']<0x1)return;var _0x5b3527=_0x404e86[_0xd24f68(0xab)](_0xd24f68(0xaf))||'',_0x528a85=_0x5b3527?_0x5b3527+';'+_0xea5ab0[_0xd24f68(0xde)](';'):_0xea5ab0[_0xd24f68(0xde)](';');_0x404e86['setAttribute'](_0xd24f68(0xaf),_0x528a85);});}document['addEventListener'](_0x170d25(0x9d),function(){var _0x4e00d2=_0x170d25;initMundaneLicenseState(),liftPopupColorVarsToRoot(),!hasMundaneLicense()&&showLicenseNotice(),qsa(_0x4e00d2(0xd3))[_0x4e00d2(0xd9)](function(_0xa198a7){initMainPopup(_0xa198a7);});});
17
18
19window.MUNDANE_SWIPER_PRESETS = window.MUNDANE_SWIPER_PRESETS || {
20    'type-image': {
21        effect: 'fade',
22        fadeEffect: { crossFade: true },
23        autoHeight: true,
24        speed: 1500,
25        autoplay: { delay: 2500, disableOnInteraction: false },
26    },
27    'type-image-text': {
28        effect: 'slide',
29        autoHeight: true,
30        speed: 700,
31        navigation: {
32            prevEl: '.prev-btn',
33            nextEl: '.next-btn'
34        },
35    },
36    'type-text': {
37        effect: 'slide',
38        autoHeight: true,
39        speed: 1500,
40    },
41};
42
43/* =========================
44 * © MUNDANE
45 * 본 파일은 먼데인이 본 스킨을 위해 제작/구성한 커스텀 JavaScript 코드입니다.
46 * 무단 복제, 수정, 재배포 및 타 프로젝트 사용을 금합니다.
47 * ※ 본 스킨은 jQuery, Swiper 등 제3자 라이브러리를 사용할 수 있으며,
48 * 해당 라이브러리의 권리/라이선스는 각 저작권자에게 있습니다.
49========================= */
50
51(function ($) {
52
53    'use strict';
54
55    const MUNLoading = {
56
57        opt: {
58            overlaySelector: '#loading',
59            scopeSelector: '[data-loading-scope]',
60            attrName: 'data-is-loading',
61            fadeInSpeed: 200,
62            fadeOutSpeedMain: 500,
63            fadeOutSpeedSub: 500,
64            firstHideDelay: 200,
65            failSafeMs: 8000,
66            clickDelay: 80,
67            introStorageKey: 'MUN_LOADING_INTRO_SESSION_SEEN',
68            introFirstHideDelay: 900,
69            introFadeOutSpeedMain: 600,
70            introFadeOutSpeedSub: 600
71        },
72
73        state: {
74            isNavigating: false,
75            didInitHide: false,
76            failSafeTimer: null,
77            allowIntro: true,
78            didBindGlobalFailSafe: false
79        },
80
81        setOpt: function (obj) {
82            if (!obj) return;
83            $.extend(true, MUNLoading.opt, obj);
84        },
85
86        init: function () {
87            MUNLoading.bindTransition();
88            MUNLoading.bindBFCacheFix();
89            MUNLoading.bindFailSafe();
90            MUNLoading.applyScope();
91
92            const key = MUNLoading.opt.introStorageKey;
93            const $overlay = $(MUNLoading.opt.overlaySelector);
94            const $introImg = $overlay.find('img');
95
96            try {
97                MUNLoading.state.allowIntro = sessionStorage.getItem(key) !== '1';
98            } catch (e) {
99                MUNLoading.state.allowIntro = true;
100            }
101
102            if (MUNLoading.state.allowIntro) {
103                $introImg.show();
104                try { sessionStorage.setItem(key, '1'); } catch (e) {}
105            } else {
106                $introImg.hide();
107            }
108
109            MUNLoading.hideOnInit();
110
111            $(document)
112                .off('mun:categoryRendered.munLoading')
113                .on('mun:categoryRendered.munLoading', function () {
114                    MUNLoading.applyScope();
115                });
116        },
117
118        applyScope: function () {
119
120            const opt = MUNLoading.opt;
121
122            $(opt.scopeSelector).each(function () {
123
124                const $scope = $(this);
125
126                $scope.find('a').each(function () {
127
128                    const $a = $(this);
129
130                    if (MUNLoading.isSkippable($a)) return;
131                    if ($a.is('[' + opt.attrName + ']')) return;
132
133                    $a.attr(opt.attrName, '1');
134                });
135            });
136        },
137
138        bindTransition: function () {
139
140            const opt = MUNLoading.opt;
141
142            $(document)
143                .off('click.munLoading')
144                .on('click.munLoading', 'a[' + opt.attrName + '="1"]', function (e) {
145
146                    const $a = $(this);
147
148                    if (MUNLoading.isSkippable($a)) return;
149                    if ($a.is('[data-no-loading], [' + opt.attrName + '="0"]')) return;
150
151                    const href = String($a.attr('href') || '').trim();
152                    if (!href) return;
153
154                    e.preventDefault();
155
156                    MUNLoading.state.isNavigating = true;
157                    MUNLoading.show();
158
159                    setTimeout(function () {
160                        location.href = href;
161                    }, opt.clickDelay);
162                });
163        },
164
165        hideOnInit: function () {
166
167            const opt = MUNLoading.opt;
168            const startTime = Date.now();
169
170            const isIntro = !!MUNLoading.state.allowIntro;
171
172            const delay = isIntro ? opt.introFirstHideDelay : opt.firstHideDelay;
173
174            const speed = (function () {
175
176                if (isIntro) {
177                    return ($('#main').length > 0) ? opt.introFadeOutSpeedMain : opt.introFadeOutSpeedSub;
178                }
179
180                return ($('#main').length > 0) ? opt.fadeOutSpeedMain : opt.fadeOutSpeedSub;
181            })();
182
183            function doHide() {
184
185                if (MUNLoading.state.isNavigating) return;
186                if (MUNLoading.state.didInitHide) return;
187
188                MUNLoading.state.didInitHide = true;
189                MUNLoading.hide(speed);
190            }
191
192            setTimeout(function () {
193                doHide();
194            }, delay);
195
196            $(window)
197                .off('load.munLoadingInit')
198                .on('load.munLoadingInit', function () {
199
200                    if (MUNLoading.state.isNavigating) return;
201                    if (MUNLoading.state.didInitHide) return;
202
203                    const elapsed = Date.now() - startTime;
204                    if (elapsed < delay) return;
205
206                    doHide();
207                });
208        },
209
210        bindBFCacheFix: function () {
211
212            $(window)
213                .off('pageshow.munLoading')
214                .on('pageshow.munLoading', function (e) {
215
216                    const persisted = e && e.originalEvent && e.originalEvent.persisted;
217                    if (!persisted) return;
218
219                    MUNLoading.state.isNavigating = false;
220                    MUNLoading.state.didInitHide = true;
221                    MUNLoading.hide(0);
222                });
223        },
224
225        bindFailSafe: function () {
226
227            const opt = MUNLoading.opt;
228
229            if (MUNLoading.state.failSafeTimer) {
230                clearTimeout(MUNLoading.state.failSafeTimer);
231            }
232
233            MUNLoading.state.failSafeTimer = setTimeout(function () {
234                MUNLoading.hide(opt.fadeOutSpeedSub);
235            }, opt.failSafeMs);
236
237            if (MUNLoading.state.didBindGlobalFailSafe) return;
238            MUNLoading.state.didBindGlobalFailSafe = true;
239
240            window.addEventListener('error', function () {
241                MUNLoading.hide(opt.fadeOutSpeedSub);
242            });
243
244            window.addEventListener('unhandledrejection', function () {
245                MUNLoading.hide(opt.fadeOutSpeedSub);
246            });
247        },
248
249        show: function () {
250
251            const opt = MUNLoading.opt;
252            const $overlay = $(opt.overlaySelector);
253            if (!$overlay.length) return;
254
255            $overlay.find('img').hide();
256
257            $overlay.stop(true, true).addClass('on').fadeIn(opt.fadeInSpeed);
258        },
259
260        hide: function (speed) {
261
262            const opt = MUNLoading.opt;
263            const $overlay = $(opt.overlaySelector);
264            if (!$overlay.length) return;
265
266            const s = typeof speed === 'number' ? speed : opt.fadeOutSpeedSub;
267
268            if (s === 0) {
269                $overlay.stop(true, true).hide().removeClass('on');
270                return;
271            }
272
273            $overlay.stop(true, true).fadeOut(s, function () {
274                $overlay.removeClass('on').hide();
275            });
276        },
277
278        isSkippable: function ($a) {
279
280            if (!$a || !$a.length) return true;
281
282            const href = String($a.attr('href') || '').trim();
283            if (!href) return true;
284            if (href === '#' || href === '#;' || href === '#none') return true;
285            if (href.charAt(0) === '#') return true;
286            if (/^javascript:/i.test(href)) return true;
287
288            const target = String($a.attr('target') || '').toLowerCase();
289            if (target === '_blank') return true;
290            if ($a.is('[download]')) return true;
291            if (/^(tel:|mailto:)/i.test(href)) return true;
292            if (MUNLoading.isExternalLink(href)) return true;
293
294            return false;
295        },
296
297        isExternalLink: function (href) {
298
299            const h = String(href || '').trim();
300            if (!h) return false;
301
302            if (!/^(https?:)?\/\//i.test(h)) return false;
303
304            const a = document.createElement('a');
305            a.href = h;
306
307            const linkHost = String(a.hostname || '').toLowerCase();
308            const curHost = String(location.hostname || '').toLowerCase();
309
310            if (!linkHost) return false;
311
312            return linkHost !== curHost;
313        }
314    };
315
316    window.MUNLoading = MUNLoading;
317
318})(jQuery);
319(function ($) {
320
321    'use strict';
322
323    $(function () {
324
325        if (!window.MUNLoading) return;
326
327        const uiOpt = {
328            overlaySelector: '#loading',
329            scopeSelector: '[data-loading-scope]',
330            attrName: 'data-is-loading',
331            fadeInSpeed: 200,
332            fadeOutSpeedMain: 500,
333            fadeOutSpeedSub: 500,
334            firstHideDelay: 200,
335            failSafeMs: 8000,
336            clickDelay: 80,
337            introStorageKey: 'MUN_LOADING_INTRO_SESSION_SEEN',
338            introFirstHideDelay: 900,
339            introFadeOutSpeedMain: 600,
340            introFadeOutSpeedSub: 600
341        };
342
343        window.MUNLoading.setOpt(uiOpt);
344        window.MUNLoading.init();
345
346    });
347
348})(jQuery);
349/* =========================
350 * © MUNDANE
351 * 본 파일은 먼데인이 본 스킨을 위해 제작/구성한 커스텀 JavaScript 코드입니다.
352 * 무단 복제, 수정, 재배포 및 타 프로젝트 사용을 금합니다.
353 * ※ 본 스킨은 jQuery, Swiper 등 제3자 라이브러리를 사용할 수 있으며,
354 * 해당 라이브러리의 권리/라이선스는 각 저작권자에게 있습니다.
355========================= */
356
357
358$(function () {
359
360    const methods = {
361        aSubCategory: {},
362        aCategoryByNo: {},
363
364        get: function () {
365            $.ajax({
366                url: '/exec/front/Product/SubCategory',
367                dataType: 'json',
368                success: function (aData) {
369
370                    if (!aData || !aData.length) return;
371
372                    for (let i = 0; i < aData.length; i++) {
373                        const cate = aData[i];
374                        const parent = cate.parent_cate_no;
375
376                        methods.aCategoryByNo[String(cate.cate_no)] = cate;
377
378                        if (!methods.aSubCategory[parent]) {
379                            methods.aSubCategory[parent] = [];
380                        }
381                        methods.aSubCategory[parent].push(cate);
382                    }
383
384                    $('.category-Area').each(function () {
385                        const $root = $(this);
386                        methods.render($root);
387                    });
388
389                    methods.renderMenuCategory();
390
391                    $(document).trigger('mun:categoryRendered');
392                }
393            });
394        },
395
396        render: function ($root) {
397
398            $root.find('> ul > li').each(function () {
399
400                const $li = $(this);
401                const $a = $li.children('a').first();
402                const href = $a.attr('href');
403                if (!href) return;
404
405                const cateNo = methods.getParam(href, 'cate_no') || methods.getParamSeo(href);
406                if (!cateNo) return;
407
408                const cateObj = methods.aCategoryByNo[String(cateNo)];
409
410                if (cateObj) {
411                    methods.addPageClass($li, cateObj);
412
413                    const newHref = methods.cateLink(cateObj);
414                    if (newHref) {
415                        $a.attr('href', newHref);
416                    }
417                }
418
419                methods.isActive($a);
420
421                const $subTree = methods.renderSub(cateNo, 2, 4);
422                $a.attr('data-is-loading', '1');
423                if ($subTree) {
424                    $li.append($subTree);
425                }
426            });
427
428            $root.find('a.is-active').each(function () {
429                methods.openActivePath($(this));
430            });
431        },
432
433        renderSub: function (parentCateNo, depth, maxDepth) {
434
435            const subList = methods.aSubCategory[parentCateNo];
436
437            if (!subList || subList.length === 0 || depth > maxDepth) {
438                return null;
439            }
440
441            const depthClassMap = {
442                2: 'middle-category',
443                3: 'small-category',
444                4: 'sub-category'
445            };
446
447            const className = depthClassMap[depth] || ('depth-' + depth);
448
449            const $wrapper = $('<div></div>')
450            .addClass(className)
451            .addClass('depth-' + depth);
452
453            const splitDepths = { 2: true, 3: true, 4: true };
454            const onlyWhenMixed = true;
455
456            const makeLi = function (cate) {
457
458                const $li = $('<li></li>');
459
460                const $a = $('<a></a>', {
461                    href: methods.cateLink(cate),
462                    text: cate.name
463                });
464
465                methods.isActive($a);
466
467                $li.append($a);
468
469                const $child = methods.renderSub(cate.cate_no, depth + 1, maxDepth);
470                $a.attr('data-is-loading', '1');
471                if ($child) {
472                    $li.append($child);
473                }
474
475                return $li;
476            };
477
478            const canSplit = !!splitDepths[depth];
479
480            const getPageKey = function (cate) {
481
482                const d = String(cate.design_page_url || '')
483                .replace(/^\//, '')
484                .split('?')[0]
485                .toLowerCase();
486
487                if (d && d !== 'product/list.html') {
488                    return d;
489                }
490
491                return 'product/list.html';
492            };
493
494            const toSlug = function (s) {
495                return String(s || '')
496                    .toLowerCase()
497                    .replace(/^\//, '')
498                    .replace(/\.html.*$/i, '')
499                    .replace(/[^\w\-]+/g, '_')
500                    .replace(/_+/g, '_')
501                    .replace(/^_+|_+$/g, '');
502            };
503
504            if (canSplit) {
505
506                const groups = {};
507                const order = [];
508
509                $.each(subList, function (_, cate) {
510
511                    const key = getPageKey(cate);
512
513                    if (!groups[key]) {
514                        groups[key] = [];
515                        order.push(key);
516                    }
517
518                    groups[key].push(cate);
519                });
520
521                const keyCount = order.length;
522
523                if (!onlyWhenMixed || keyCount > 1) {
524
525                    order.sort(function (a, b) {
526                        const aIsList = (a === 'product/list.html');
527                        const bIsList = (b === 'product/list.html');
528                        if (aIsList && !bIsList) return 1;
529                        if (!aIsList && bIsList) return -1;
530                        return 0;
531                    });
532
533                    $.each(order, function (_, key) {
534
535                        const slug = toSlug(key);
536
537                        const $ul = $('<ul></ul>')
538                        .addClass('cate-ul')
539                        .addClass('cate-ul--' + slug)
540                        .attr('data-page-key', key);
541
542                        $.each(groups[key], function (_, cate) {
543                            $ul.append(makeLi(cate));
544                        });
545
546                        $wrapper.append($ul);
547                    });
548
549                    return $wrapper;
550                }
551            }
552
553            const $ul = $('<ul></ul>');
554            $.each(subList, function (_, cate) {
555                $ul.append(makeLi(cate));
556            });
557
558            $wrapper.append($ul);
559            return $wrapper;
560        },
561
562        addPageClass: function ($li, cate) {
563
564            if (!$li || !$li.length || !cate) return;
565
566            const d = cate.design_page_url;
567
568            if (d && d !== '/product/list.html') {
569                const slug = String(d)
570                .replace(/^\//, '')
571                .replace(/\.html.*$/i, '')
572                .replace(/[^\w\-]+/g, '_')
573                .replace(/_+/g, '_')
574                .replace(/^_+|_+$/g, '');
575
576                if (slug) {
577                    $li.addClass('page-' + slug);
578                }
579            }
580        },
581
582        isActive: function ($a) {
583            if (!$a || !$a.length) return;
584
585            const href = $a.attr('href') || '';
586            if (!href) return;
587            if (/^#/.test(href)) return;
588            if (/^javascript:/i.test(href)) return;
589
590            const currentPath = location.pathname || '';
591            const currentSearch = location.search || '';
592
593            const currentCateNo = methods.getParam(currentSearch, 'cate_no') || methods.getParamSeo(currentPath);
594            let currentBoardNo = methods.getParam(currentSearch, 'board_no');
595
596            if (!currentBoardNo && /^\/board\//.test(currentPath)) {
597                currentBoardNo = methods.getParamSeo(currentPath);
598            }
599
600            if (currentCateNo) {
601                const linkCateNo = methods.getParam(href, 'cate_no') || methods.getParamSeo(methods.getPathname(href));
602                if (linkCateNo && String(linkCateNo) === String(currentCateNo)) {
603                    $a.addClass('is-active');
604                }
605                return;
606            }
607
608            if (currentBoardNo) {
609                const linkBoardNo = methods.getParam(href, 'board_no');
610                if (linkBoardNo && String(linkBoardNo) === String(currentBoardNo)) {
611                    $a.addClass('is-active');
612                }
613                return;
614            }
615
616            const targetPath = methods.getPathname(href);
617            if (targetPath && targetPath === currentPath) {
618                $a.addClass('is-active');
619            }
620        },
621
622        openActivePath: function ($a) {
623            if (!$a || !$a.length) return;
624
625            $a.parents('li').each(function () {
626                const $li = $(this);
627                $li.addClass('is-open');
628            });
629        },
630
631        renderMenuCategory: function () {
632
633            const $titleBox = $('.mun-menu-title');
634            const $navBox = $('.mun-menu-nav');
635
636            if (!$titleBox.length && !$navBox.length) return;
637
638            const opt = {
639                showListOnDepth1: false,
640                showSiblingsOnDepth2WhenEmpty: false,
641                showParentTitleOnDepth2WhenEmpty: false,
642                hideNavWhenEmpty: true,
643                hideTitleWhenEmpty: true
644            };
645            methods.menuOpt = opt;
646
647            const currentPath = location.pathname || '';
648            const currentSearch = location.search || '';
649
650            const currentCateNo = methods.getParam(currentSearch, 'cate_no') || methods.getParamSeo(currentPath);
651
652            if (!currentCateNo) {
653                if ($titleBox.length) $titleBox.hide();
654                if ($navBox.length) $navBox.hide();
655                return;
656            }
657
658            const depth = methods.getDepth(currentCateNo);
659
660            const curObj = methods.aCategoryByNo[String(currentCateNo)] || null;
661            const parentNo = curObj ? String(curObj.parent_cate_no || '') : '';
662
663            const children = methods.aSubCategory[String(currentCateNo)] || [];
664            const siblings = parentNo ? (methods.aSubCategory[parentNo] || []) : [];
665
666            let list = [];
667            let mode = '';
668            let viewDepth = 0;
669
670            if (depth === 1) {
671                if (opt.showListOnDepth1 && children.length > 0) {
672                    list = children;
673                    mode = 'children';
674                    viewDepth = 2;
675                } else {
676                    list = [];
677                }
678            }
679
680            if (depth === 2) {
681                if (children.length > 0) {
682                    list = children;
683                    mode = 'children';
684                    viewDepth = 3;
685                } else {
686                    if (opt.showSiblingsOnDepth2WhenEmpty && siblings.length > 1) {
687                        list = siblings;
688                        mode = 'siblings';
689                        viewDepth = 2;
690                    } else {
691                        list = [];
692                    }
693                }
694            }
695
696            if (depth === 3) {
697                if (children.length > 0) {
698                    list = children;
699                    mode = 'children';
700                    viewDepth = 4;
701                } else {
702                    if (siblings.length > 1) {
703                        list = siblings;
704                        mode = 'siblings';
705                        viewDepth = 3;
706                    } else {
707                        list = [];
708                    }
709                }
710            }
711
712            if (depth >= 4) {
713                if (siblings.length > 1) {
714                    list = siblings;
715                    mode = 'siblings';
716                    viewDepth = depth;
717                } else {
718                    list = [];
719                }
720            }
721
722            const titleText = methods.getMenuTitleText(currentCateNo);
723
724            if ($titleBox.length) {
725                if (titleText) {
726                    $titleBox.show().text(titleText);
727                } else {
728                    if (opt.hideTitleWhenEmpty) $titleBox.hide();
729                    else $titleBox.show().text('');
730                }
731            }
732
733            if (!$navBox.length) return;
734
735            $navBox.empty();
736
737            if (!list || list.length === 0) {
738                if (opt.hideNavWhenEmpty) $navBox.hide();
739                else $navBox.show();
740                return;
741            }
742
743            $navBox.show();
744
745            const $ul = $('<ul></ul>')
746            .addClass('mun-menu-nav__list')
747            .addClass('depth-' + viewDepth)
748            .addClass('mode-' + mode);
749
750            $.each(list, function (_, cate) {
751
752                const $li = $('<li></li>').addClass('mun-menu-nav__item');
753
754                const $a = $('<a></a>', {
755                    href: methods.cateLink(cate),
756                    text: cate.name
757                }).addClass('mun-menu-nav__link');
758
759                methods.isActive($a);
760
761                $li.append($a);
762                $ul.append($li);
763            });
764
765            $navBox.append($ul);
766        },
767
768        getMenuTitleText: function (currentCateNo) {
769
770            const cur = methods.aCategoryByNo[String(currentCateNo)] || null;
771            if (!cur) return '';
772
773            const depth = methods.getDepth(currentCateNo);
774
775            const parent = cur.parent_cate_no ? (methods.aCategoryByNo[String(cur.parent_cate_no)] || null) : null;
776
777            const children = methods.aSubCategory[String(currentCateNo)] || [];
778
779            const parentNo = parent ? String(parent.cate_no) : '';
780            const siblings = parentNo ? (methods.aSubCategory[parentNo] || []) : [];
781
782            if (depth === 1) return cur.name || '';
783            
784            if (depth === 2) {
785                const hasChildren = children.length > 0;
786                const opt = methods.menuOpt || {};
787
788                if (opt.showParentTitleOnDepth2WhenEmpty === true && !hasChildren) {
789                    return parent ? (parent.name || '') : (cur.name || '');
790                }
791                return cur.name || '';
792            }
793
794            if (depth === 3) {
795                const hasSiblings = siblings.length > 1;
796                const hasChildren = children.length > 0;
797
798                if (hasSiblings && !hasChildren) {
799                    return parent ? (parent.name || '') : (cur.name || '');
800                }
801                return cur.name || '';
802            }
803
804            if (depth >= 4) {
805                const hasSiblings = siblings.length > 1;
806                if (hasSiblings) {
807                    return parent ? (parent.name || '') : (cur.name || '');
808                }
809                return cur.name || '';
810            }
811
812            return cur.name || '';
813        },
814
815        getDepth: function (cateNo) {
816            let depth = 0;
817            let cur = String(cateNo || '');
818
819            while (cur && methods.aCategoryByNo[cur]) {
820                depth += 1;
821
822                const parent = methods.aCategoryByNo[cur].parent_cate_no;
823                if (!parent || String(parent) === '0') break;
824
825                cur = String(parent);
826
827                if (depth > 20) break;
828            }
829
830            return depth;
831        },
832
833        cateLink: function (cate) {
834
835            const listLink = cate.link_product_list || '';
836            let prefix = '';
837
838            const m = String(listLink).match(/^\/(shop\d+)(?:\/(skin-[^\/]+))?\//);
839            if (m && m[1]) {
840                prefix = '/' + m[1];
841                if (m[2]) {
842                    prefix = prefix + '/' + m[2];
843                }
844            } else {
845                const m2 = String(listLink).match(/^\/(skin-[^\/]+)\//);
846                if (m2 && m2[1]) {
847                    prefix = '/' + m2[1];
848                }
849            }
850
851            const d = String(cate.design_page_url || '').replace(/^\//, '');
852
853            if (!d || d === 'product/list.html') {
854                return listLink;
855            }
856
857            let base = '/' + d;
858
859            if (prefix) {
860                base = prefix + base;
861            }
862
863            return base + (cate.param || '');
864        },
865
866        getParam: function (sUrl, sKey) {
867            let s = String(sUrl || '');
868
869            if (s.charAt(0) === '?') {
870                s = s.substring(1);
871            }
872
873            const aUrl = s.split('?');
874            const query = aUrl.length > 1 ? aUrl[1] : aUrl[0];
875            if (!query) return null;
876
877            const aFields = query.split('&');
878            for (let i = 0; i < aFields.length; i++) {
879                const aField = aFields[i].split('=');
880                if (aField[0] === sKey) return aField[1];
881            }
882            return null;
883        },
884
885        getParamSeo: function (sUrl) {
886
887            const aUrl = String(sUrl || '').split('/');
888            const seg = aUrl[aUrl.length - 2] || '';
889
890            if (/^\d+$/.test(seg)) return seg;
891
892            return null;
893        },
894
895        getPathname: function (href) {
896            if (!href) return '';
897            const a = document.createElement('a');
898            a.href = href;
899            return a.pathname || '';
900        }
901    };
902
903    window.MUNCategory = methods;
904
905    methods.get();
906
907    $('[data-active-scope] a').each(function () {
908        methods.isActive($(this));
909    });
910
911});
912
913/* =========================
914 * © MUNDANE
915 * 본 파일은 먼데인이 본 스킨을 위해 제작/구성한 커스텀 JavaScript 코드입니다.
916 * 무단 복제, 수정, 재배포 및 타 프로젝트 사용을 금합니다.
917 * ※ 본 스킨은 jQuery, Swiper 등 제3자 라이브러리를 사용할 수 있으며,
918 * 해당 라이브러리의 권리/라이선스는 각 저작권자에게 있습니다.
919========================= */
920
921
922$(function () {
923
924    const methods = window.MUNCategory;
925    if (!methods) return;
926
927    $(document)
928        .off('mun:categoryRendered.munSkinUI')
929        .on('mun:categoryRendered.munSkinUI', function () {
930
931        methods.applyMobileCateUI = function (userOpt) {
932
933            const opt = $.extend({
934                layerBreakpoint: 1024,
935                layerMaxDepth: 3,               
936                autoOpenOnMenuOpen: true,
937                autoOpenMaxListDepth: 2,        
938                storageKeyAuto: 'MUN_MOBILE_CATE_AUTOOPEN'
939            }, (userOpt || {}));
940
941            const $root = $('.mobile-category');
942            if (!$root.length) return;
943
944            const $section3 = $root.find('.section3');
945            if (!$section3.length) return;
946
947            const stack = [];
948
949            function isMobile() {
950                return $(window).width() < opt.layerBreakpoint;
951            }
952
953            function getChildContainer($a) {
954                const $sub = $a.siblings('.middle-category, .small-category, .sub-category');
955                if ($sub.length && $sub.find('> ul > li').length > 0) return $sub.first();
956
957                const $fallback = $a.siblings().filter(function () {
958                    return $(this).find('> ul > li').length > 0 || $(this).find('> ul.cate-ul > li').length > 0;
959                }).first();
960
961                return $fallback;
962            }
963
964            function getClickDepth($a) {
965                const $sub = getChildContainer($a);
966                if ($sub.length) {
967                    const m = String($sub.attr('class') || '').match(/\bdepth-(2|3|4)\b/);
968                    if (m && m[1]) return Number(m[1]) - 1;
969                }
970                return 1;
971            }
972
973            function cleanText($a) {
974                const $copy = $a.clone();
975                $copy.find('.arrows, .arrow').remove();
976                return $.trim($copy.text());
977            }
978
979            function buildShellIfNeeded() {
980                if ($section3.find('.mun-layer-shell').length) return;
981
982                const html = [
983                    '<div class="mun-layer-shell" aria-hidden="true">',
984                    '<div class="mun-layer-head">',
985                    '<button type="button" class="mun-layer-back" aria-label="Back"><strong></strong><span></span></button>',
986                    '<p class="mun-layer-title"></p>',
987                    '</div>',
988                    '<div class="mun-layer-panels">',
989                    '<div class="mun-layer-track"></div>',
990                    '</div>',
991                    '</div>'
992                ].join('');
993
994                $section3.empty().append(html);
995            }
996
997            function setSection3Active(on) {
998                if (on) {
999                    $section3.addClass('active').attr('aria-hidden', 'false');
1000                    $section3.find('.mun-layer-shell').attr('aria-hidden', 'false');
1001                } else {
1002                    $section3.removeClass('active').attr('aria-hidden', 'true');
1003                    $section3.find('.mun-layer-shell').attr('aria-hidden', 'true');
1004                }
1005            }
1006
1007            function renderPanels() {
1008                buildShellIfNeeded();
1009
1010                const $shell = $section3.find('.mun-layer-shell');
1011                const $track = $shell.find('.mun-layer-track');
1012                const $title = $shell.find('.mun-layer-title');
1013                const $back = $shell.find('.mun-layer-back');
1014
1015                $track.empty();
1016
1017                for (let i = 0; i < stack.length; i += 1) {
1018                    const item = stack[i];
1019                    const $panel = $('<div class="mun-layer-panel"></div>');
1020                    $panel.append(item.$content);
1021                    $track.append($panel);
1022                }
1023
1024                const idx = stack.length - 1;
1025                $track.css({ transform: 'translateX(-' + String(idx * 100) + '%)' });
1026
1027                $title.text(stack.length ? (stack[stack.length - 1].title || '') : '');
1028                $back.toggle(stack.length > 0);
1029
1030                setSection3Active(stack.length > 0);
1031            }
1032
1033            function pushPanelFromAnchor($a) {
1034                const $sub = getChildContainer($a);
1035                if (!$sub.length) return false;
1036
1037                const depth = getClickDepth($a);
1038
1039                if (depth >= opt.layerMaxDepth) return false;
1040
1041                const $content = $('<div class="mun-layer-content"></div>');
1042                $content.append($sub.children().clone(true, true));
1043
1044                if (!$content.children().length) return false;
1045
1046                stack.push({
1047                    title: cleanText($a),
1048                    $content: $content
1049                });
1050
1051                renderPanels();
1052                return true;
1053            }
1054
1055            function popPanel() {
1056                if (!stack.length) return;
1057                stack.pop();
1058                renderPanels();
1059            }
1060
1061            function closeAll() {
1062                stack.length = 0;
1063                setSection3Active(false);
1064                $section3.empty();
1065            }
1066
1067            function markAutoOpenOnNextOpen() {
1068                try {
1069                    sessionStorage.setItem(opt.storageKeyAuto, '1');
1070                } catch (e) {}
1071            }
1072
1073            function clearAutoOpen() {
1074                try {
1075                    sessionStorage.removeItem(opt.storageKeyAuto);
1076                } catch (e) {}
1077            }
1078
1079            function shouldAutoOpen() {
1080                if (!opt.autoOpenOnMenuOpen) return false;
1081                try {
1082                    return sessionStorage.getItem(opt.storageKeyAuto) === '1';
1083                } catch (e) {}
1084                return false;
1085            }
1086
1087            function findDeepestActiveAnchorInSection1() {
1088                const $cands = $root.find('.section1 a.is-active');
1089                if (!$cands.length) return $();
1090
1091                let $best = $();
1092                let bestDepth = -1;
1093
1094                $cands.each(function () {
1095                    const $a = $(this);
1096                    const $li = $a.closest('li');
1097                    if (!$li.length) return;
1098
1099                    let d = 1;
1100                    $li.parents('li').each(function () { d += 1; });
1101
1102                    if (d > bestDepth) {
1103                        bestDepth = d;
1104                        $best = $a;
1105                    }
1106                });
1107
1108                return $best;
1109            }
1110
1111            function autoOpenToActivePath() {
1112                if (!isMobile()) return;
1113                if (!shouldAutoOpen()) return;
1114
1115                const $active = findDeepestActiveAnchorInSection1();
1116                if (!$active.length) return;
1117
1118                const anchors = [];
1119                let $li = $active.closest('li');
1120
1121                while ($li.length) {
1122                    const $a = $li.children('a').first();
1123                    if ($a.length && getChildContainer($a).length) {
1124                        if ($.inArray($a.get(0), $.map(anchors, function (x) { return x.get(0); })) === -1) {
1125                            anchors.push($a);
1126                        }
1127                    }
1128                    $li = $li.parent().closest('li');
1129                }
1130
1131                if (!anchors.length) {
1132                    const $middle = $active.closest('.middle-category');
1133                    if ($middle.length) {
1134                        const $parentA = $middle.prev('a');
1135                        if ($parentA.length && getChildContainer($parentA).length) {
1136                            anchors.push($parentA);
1137                        }
1138                    }
1139                }
1140
1141                anchors.reverse(); 
1142
1143                closeAll();
1144
1145                for (let i = 0; i < anchors.length; i += 1) {
1146                    const $a = anchors[i];
1147                    const depth = getClickDepth($a);
1148
1149                    if (depth >= opt.layerMaxDepth) break;
1150                    if (depth >= opt.autoOpenMaxListDepth) break;
1151
1152                    const ok = pushPanelFromAnchor($a);
1153                    if (!ok) break;
1154                }
1155
1156                const $shell = $section3.find('.mun-layer-shell');
1157                if ($shell.length) {
1158                    const $last = $shell.find('.mun-layer-panel').last();
1159                    const $cur = $last.find('a.is-active').first();
1160                    if ($cur.length && $cur.get(0) && $cur.get(0).scrollIntoView) {
1161                        $cur.get(0).scrollIntoView({ block: 'center' });
1162                    }
1163                }
1164            }
1165
1166            $root
1167                .off('click.munMobileCateLayer')
1168                .on('click.munMobileCateLayer', '.section1 .category-Area a, .section3 .mun-layer-panel a', function (e) {
1169
1170                if (!isMobile()) return;
1171
1172                const $a = $(this);
1173
1174                const pushed = pushPanelFromAnchor($a);
1175                if (pushed) {
1176                    e.preventDefault();
1177                    e.stopImmediatePropagation();
1178                    return;
1179                }
1180
1181                markAutoOpenOnNextOpen();
1182            });
1183
1184            $root
1185                .off('click.munMobileCateLayerBack')
1186                .on('click.munMobileCateLayerBack', '.section3 .mun-layer-back', function () {
1187                if (!isMobile()) return;
1188
1189                clearAutoOpen();
1190
1191                if (stack.length <= 1) {
1192                    closeAll();
1193                    return;
1194                }
1195                popPanel();
1196            });
1197
1198            $(window)
1199                .off('resize.munMobileCateLayer')
1200                .on('resize.munMobileCateLayer', function () {
1201                if (!isMobile()) closeAll();
1202            });
1203
1204            methods.openMobileCateLayerAuto = function () {
1205                autoOpenToActivePath();
1206            };
1207
1208            methods.closeMobileCateLayer = function () {
1209                closeAll();
1210            };
1211        };
1212
1213
1214
1215        methods.applyMobileCateAnimation = function () {
1216
1217            const $mobile = $('.mobile-category');
1218            if (!$mobile.length) return;
1219
1220            const $sec1 = $mobile.find('.section1').first();
1221            const $sec2 = $mobile.find('.section2').first();
1222
1223            if (!$sec1.length && !$sec2.length) return;
1224
1225            let order = 1;
1226
1227            if ($sec1.length) {
1228                $sec1.addClass('animation-list').css({ '--animation-order': order });
1229                order += 1;
1230            }
1231
1232            if ($sec2.length) {
1233
1234                const attrStart1 = $sec2.attr('data-anim-start');
1235                const attrStart2 = $sec2.attr('animation_order');
1236                const startRaw = (attrStart1 != null ? attrStart1 : attrStart2);
1237
1238                let start = order;
1239                if (startRaw != null && !isNaN(Number(startRaw))) {
1240                    start = Number(startRaw);
1241                }
1242
1243                const $targets = $sec2.find('.group');
1244
1245                let idx = 0;
1246                $targets.each(function () {
1247
1248                    const $el = $(this);
1249
1250                    if ($el.hasClass('displaynone')) return;
1251                    if ($el.is(':hidden')) return;
1252
1253                    $el.addClass('animation-list').css({ '--animation-order': start + idx });
1254                    idx += 1;
1255                });
1256            }
1257        };
1258
1259
1260        methods.applyMobileCateUI();
1261        //methods.applyMobileCateAnimation();
1262    });
1263
1264});
1265
1266/* =========================
1267 * © MUNDANE
1268 * 본 파일은 먼데인이 본 스킨을 위해 제작/구성한 커스텀 JavaScript 코드입니다.
1269 * 무단 복제, 수정, 재배포 및 타 프로젝트 사용을 금합니다.
1270 * ※ 본 스킨은 jQuery, Swiper 등 제3자 라이브러리를 사용할 수 있으며,
1271 * 해당 라이브러리의 권리/라이선스는 각 저작권자에게 있습니다.
1272========================= */
1273
1274$(function () {
1275
1276    if (!window.MUN) window.MUN = {};
1277    if (!window.MUN.product) window.MUN.product = {};
1278
1279    const H = window.MUN.helper || {};
1280
1281    const Product = {
1282
1283        init: function () {
1284            Product.bindModal();
1285            Product.bindSort();
1286            Product.bindThumbHover();
1287
1288            Product.applyTo($('.ec-base-product'));
1289
1290            Product.observeMoreProducts();
1291        },
1292
1293        applyTo: function ($scope) {
1294            if (!$scope || !$scope.length) return;
1295
1296            Product.applySoldout($scope);
1297
1298            if (window.MUN && window.MUN.ui && typeof window.MUN.ui.runFadeLight === 'function') {
1299                window.MUN.ui.runFadeLight();
1300            }
1301            if (window.MUN && window.MUN.ui && typeof window.MUN.ui.collectFadeSections === 'function') {
1302                window.MUN.ui.collectFadeSections();
1303                if (typeof window.MUN.ui.runFadeSection === 'function') {
1304                    window.MUN.ui.runFadeSection();
1305                }
1306            }
1307        },
1308
1309        bindModal: function () {
1310
1311            const $modal = $('#M_modal');
1312            if (!$modal.length) return;
1313
1314            $(document).off('click.munModalOpen')
1315            .on('click.munModalOpen', '.M_modal .mun-prd-thumb a', function (e) {
1316                e.preventDefault();
1317
1318                const href = $(this).attr('href') || '';
1319                if (!href) return;
1320
1321                $modal.scrollTop(0);
1322
1323                $modal.load(href, function () {
1324                    $('html').addClass('modal');
1325                });
1326            });
1327
1328            $(document).off('click.munModalClose')
1329            .on('click.munModalClose', '#M_modal', function (e) {
1330                if (e.target !== this) return;
1331                $('html').removeClass('modal');
1332            });
1333        },
1334
1335        bindSort: function () {
1336
1337            $(document).off('click.munSortToggle')
1338            .on('click.munSortToggle', '.product-sort.title', function (e) {
1339                e.preventDefault();
1340                $(this).toggleClass('state');
1341            });
1342
1343            $(document).off('click.munSortLink')
1344            .on('click.munSortLink', '.product-sort.link a', function (e) {
1345                e.preventDefault();
1346
1347                const link = $(this).attr('link') || $(this).attr('href') || '';
1348                if (!link) return;
1349
1350                const base = (location.href.split('&')[0] || '').replace('#;', '');
1351                location.replace(base + link);
1352            });
1353        },
1354
1355        applySoldout: function ($scope) {
1356
1357            const $targets = $scope.find('.mun-prd-list');
1358
1359            $targets.each(function () {
1360                const $root = $(this);
1361
1362                if ($root.data('munSoldoutDone') === 1) return;
1363
1364                if ($root.find('.mun-prd-sold_out img').length) {
1365                    $root.addClass('soldout');
1366                    $root.find('.mun-prd-sold_out img').remove();
1367                }
1368
1369                $root.data('munSoldoutDone', 1);
1370            });
1371        },
1372
1373        bindThumbHover: function () {
1374
1375            const $list = $('.ec-base-product');
1376            if (!$list.length) return;
1377
1378            $(document).off('mouseenter.munPrdHover mouseleave.munPrdHover')
1379            .on('mouseenter.munPrdHover', '.mun-prd-thumb', function () {
1380                $(this).closest('.mun-prd-list').addClass('hover');
1381            })
1382            .on('mouseleave.munPrdHover', '.mun-prd-list-cover', function () {
1383                $(this).closest('.mun-prd-list').removeClass('hover');
1384            });
1385
1386            $(document).off('touchstart.munPrdHover')
1387            .on('touchstart.munPrdHover', '.mun-prd-thumb img', function () {
1388                if (typeof H.winW === 'function' && H.winW() >= 1024) return;
1389                if (!H.winW && $(window).width() >= 1024) return;
1390
1391                const $li = $(this).closest('.mun-prd-list');
1392                if ($li.hasClass('hover')) return;
1393
1394                $('.mun-prd-list').removeClass('hover');
1395                $li.addClass('hover');
1396            });
1397        },
1398
1399        observeMoreProducts: function () {
1400
1401            if (!H || typeof H.observeAddedNodes !== 'function') return;
1402
1403            const $root = $('.ec-base-product .prdList');
1404            if (!$root.length) return;
1405
1406            H.observeAddedNodes($root, function ($node) {
1407
1408                const $li = $node.is('li') ? $node : $node.find('li').first();
1409                if (!$li.length) return;
1410
1411                Product.applyTo($li.closest('.ec-base-product').length ? $li.closest('.ec-base-product') : $li);
1412            });
1413        }
1414    };
1415
1416    window.MUN.product = Product;
1417
1418    Product.init();
1419
1420});
1421/* =========================
1422 * © MUNDANE
1423 * 본 파일은 먼데인이 본 스킨을 위해 제작/구성한 커스텀 JavaScript 코드입니다.
1424 * 무단 복제, 수정, 재배포 및 타 프로젝트 사용을 금합니다.
1425 * ※ 본 스킨은 jQuery, Swiper 등 제3자 라이브러리를 사용할 수 있으며,
1426 * 해당 라이브러리의 권리/라이선스는 각 저작권자에게 있습니다.
1427========================= */
1428
1429$(function () {
1430
1431    if (!window.MUN) window.MUN = {};
1432    const H = window.MUN.helper || {};
1433
1434    const MUNMultiPopup = {
1435
1436        sel: {
1437            openBtn: '.multi_popup_btn',
1438            closeBtn: '.multi_popup_close_btn',
1439            popup: '#multi_popup',
1440            listLink: '.multi_popup_list a',
1441            listItem: '.multi_popup_list li',
1442            globalBtnLi: '.group.sub.multi'
1443        },
1444
1445        textMap: {
1446            '한국어': '한국어 (KR | KRW)',
1447            'English': 'English (EN | USD)',
1448            '日本語': '日本語 (JP | JPY)',
1449            '中文': '中文 (CN | CNY)'
1450        },
1451
1452        init: function () {
1453            MUNMultiPopup.bind();
1454            MUNMultiPopup.renameListText();
1455            MUNMultiPopup.toggleGlobalButton();
1456        },
1457
1458        bind: function () {
1459
1460            $(document).off('click.munMultiPopupOpen')
1461                .on('click.munMultiPopupOpen', MUNMultiPopup.sel.openBtn, function (e) {
1462                e.preventDefault();
1463                $(MUNMultiPopup.sel.popup).addClass('active');
1464            });
1465
1466            $(document).off('click.munMultiPopupClose')
1467                .on('click.munMultiPopupClose', MUNMultiPopup.sel.closeBtn, function (e) {
1468                e.preventDefault();
1469                $(MUNMultiPopup.sel.popup).removeClass('active');
1470            });
1471        },
1472
1473        renameListText: function () {
1474
1475            const map = MUNMultiPopup.textMap;
1476
1477            $(MUNMultiPopup.sel.listLink).each(function () {
1478
1479                const $a = $(this);
1480                const t = $.trim($a.text());
1481
1482                if (map[t]) {
1483                    $a.text(map[t]);
1484                    return;
1485                }
1486
1487                for (const key in map) {
1488                    if (t.indexOf(key) > -1) {
1489                        $a.text(map[key]);
1490                        break;
1491                    }
1492                }
1493            });
1494        },
1495
1496        toggleGlobalButton: function () {
1497
1498            const $items = $(MUNMultiPopup.sel.listItem);
1499            const $globalLi = $(MUNMultiPopup.sel.globalBtnLi);
1500
1501            if ($items.length <= 1) {
1502                $globalLi.addClass('displaynone');
1503            } else {
1504                $globalLi.removeClass('displaynone');
1505            }
1506        }
1507    };
1508
1509    const UI = {
1510
1511        fadeLightState: {
1512            ticking: false
1513        },
1514
1515        fadeSectionState: {
1516            ticking: false,
1517            sections: []
1518        },
1519
1520        init: function () {
1521            MUNMultiPopup.init();
1522
1523            UI.applyBackgroundType();
1524            UI.replaceRequiredDot();
1525            UI.replacePaginateIcons();
1526            UI.applyPlaceholderFromTitle();
1527            UI.applyAddOptionPlaceholder();
1528            UI.applyOptionSelectTitle();
1529            UI.applyFormTextWrap();
1530            UI.bindToggleList();
1531            UI.applyDetailAddOptionTitleCut();
1532            UI.applyMunCut();
1533            UI.hidePromotionDate();
1534            UI.fixQuantityDummy();
1535            UI.initFadeLight();
1536            UI.initFadeSection();
1537            UI.observeMoreFadeTargets();
1538        },
1539
1540        initFadeLight: function () {
1541            UI.bindFadeLight();
1542            UI.runFadeLight();
1543
1544            $(window).off('load.munFadeLight').on('load.munFadeLight', function () {
1545                UI.runFadeLight();
1546            });
1547        },
1548
1549        bindFadeLight: function () {
1550
1551            const onScrollResize = function () {
1552                if (UI.fadeLightState.ticking) return;
1553                UI.fadeLightState.ticking = true;
1554
1555                window.requestAnimationFrame(function () {
1556                    UI.fadeLightState.ticking = false;
1557                    UI.runFadeLight();
1558                });
1559            };
1560
1561            $(window).off('scroll.munFadeLight resize.munFadeLight')
1562            .on('scroll.munFadeLight resize.munFadeLight', onScrollResize);
1563        },
1564
1565        runFadeLight: function () {
1566
1567            const offsetRatio = 1.1;
1568            const activeClass = 'fade-in';
1569
1570            const st = $(window).scrollTop();
1571            const wh = $(window).height();
1572            const triggerY = st + (wh / offsetRatio);
1573
1574            $('.fade').each(function () {
1575
1576                const $el = $(this);
1577
1578                if ($el.data('munFaded') === 1) return;
1579                if ($el.hasClass(activeClass)) {
1580                    $el.data('munFaded', 1);
1581                    return;
1582                }
1583
1584                const top = $el.offset().top;
1585
1586                if (triggerY >= top) {
1587                    $el.addClass(activeClass);
1588                    $el.data('munFaded', 1);
1589                }
1590            });
1591        },
1592
1593        initFadeSection: function () {
1594            UI.collectFadeSections();
1595            UI.bindFadeSection();
1596            UI.runFadeSection();
1597
1598            $(window).off('load.munFadeSectionInit').on('load.munFadeSectionInit', function () {
1599                UI.collectFadeSections();
1600                UI.runFadeSection();
1601            });
1602        },
1603
1604        collectFadeSections: function () {
1605
1606            UI.fadeSectionState.sections = [];
1607
1608            $('.fade_section').each(function () {
1609
1610                const $section = $(this);
1611                const items = [];
1612
1613                $section.find('.fade-list').each(function () {
1614
1615                    const $el = $(this);
1616
1617                    const prop = $el.attr('transition_property') || '';
1618                    const move = Number($el.attr('fade_set_top') || 0);
1619                    const delay = Number($el.attr('fade_set_delay') || 0);
1620                    const speed = Number($el.attr('fade_set_speed') || 0.6);
1621                    const sizePct = Number($el.attr('fade_set_size') || 0);
1622
1623                    if (!$el.data('munFadeInit')) {
1624                        $el.data('munFadeInit', 1);
1625
1626                        if (!prop || prop === 'top') {
1627                            $el.css({
1628                                'opacity': '0',
1629                                'top': move + 'px',
1630                                'transition-property': 'opacity,top',
1631                                'transition-duration': speed + 's',
1632                                'transition-delay': delay + 's',
1633                                'transition-timing-function': 'ease'
1634                            });
1635                        } else if (prop === 'left') {
1636                            $el.css({
1637                                'opacity': '0',
1638                                'left': move + 'px',
1639                                'transition-property': 'opacity,left',
1640                                'transition-duration': speed + 's',
1641                                'transition-delay': delay + 's',
1642                                'transition-timing-function': 'ease'
1643                            });
1644                        } else {
1645                            $el.css({
1646                                'opacity': '0',
1647                                'transition-property': 'opacity',
1648                                'transition-duration': speed + 's',
1649                                'transition-delay': delay + 's',
1650                                'transition-timing-function': 'ease'
1651                            });
1652                        }
1653
1654                        if (sizePct > 0) {
1655                            const wh = window.innerHeight || $(window).height();
1656                            $el.height(wh * (sizePct / 100));
1657                        }
1658                    }
1659
1660                    items.push({ $el: $el, prop: prop });
1661                });
1662
1663                if (items.length) {
1664                    UI.fadeSectionState.sections.push({ $section: $section, items: items });
1665                }
1666            });
1667        },
1668
1669        bindFadeSection: function () {
1670
1671            const onScrollResize = function () {
1672                if (UI.fadeSectionState.ticking) return;
1673                UI.fadeSectionState.ticking = true;
1674
1675                window.requestAnimationFrame(function () {
1676                    UI.fadeSectionState.ticking = false;
1677                    UI.runFadeSection();
1678                });
1679            };
1680
1681            $(window).off('scroll.munFadeSection resize.munFadeSection')
1682            .on('scroll.munFadeSection resize.munFadeSection', onScrollResize);
1683        },
1684
1685        runFadeSection: function () {
1686
1687            const sections = UI.fadeSectionState.sections;
1688            if (!sections.length) return;
1689
1690            const offsetRatio = 1.1;
1691            const sectionOffset = -120;
1692
1693            const st = $(window).scrollTop();
1694            const wh = $(window).height();
1695            const triggerY = st + (wh / offsetRatio);
1696
1697            for (let i = 0; i < sections.length; i++) {
1698
1699                const sec = sections[i];
1700                const secTop = sec.$section.offset().top + sectionOffset;
1701
1702                if (triggerY < secTop) continue;
1703
1704                for (let j = 0; j < sec.items.length; j++) {
1705
1706                    const it = sec.items[j];
1707                    const $el = it.$el;
1708
1709                    if ($el.data('munFadedSection') === 1) continue;
1710                    $el.data('munFadedSection', 1);
1711
1712                    if (!it.prop || it.prop === 'top') {
1713                        $el.css({ 'opacity': '1', 'top': '0px' });
1714                    } else if (it.prop === 'left') {
1715                        $el.css({ 'opacity': '1', 'left': '0px' });
1716                    } else {
1717                        $el.css({ 'opacity': '1' });
1718                    }
1719                }
1720            }
1721        },
1722
1723        observeMoreFadeTargets: function () {
1724
1725            if (!H || typeof H.observeAddedNodes !== 'function') return;
1726
1727            const $roots = $('.ec-base-product .prdList, #contents, #wrap');
1728
1729            $roots.each(function () {
1730
1731                const $root = $(this);
1732                if (!$root.length) return;
1733
1734                H.observeAddedNodes($root, function ($node) {
1735
1736                    if ($node.find('.fade').length || $node.hasClass('fade')) {
1737                        UI.runFadeLight();
1738                    }
1739
1740                    if ($node.find('.fade_section').length || $node.hasClass('fade_section')) {
1741                        UI.collectFadeSections();
1742                        UI.runFadeSection();
1743                    }
1744                });
1745            });
1746        },
1747
1748        applyBackgroundType: function () {
1749            $('.background-type').each(function () {
1750                const $el = $(this);
1751                const $img = $el.find('img').first();
1752                const src = $img.attr('src') || '';
1753
1754                if (src) {
1755                    $el.css('background-image', 'url(' + src + ')');
1756                    $img.remove();
1757                }
1758
1759                const pct = Number($el.attr('data-bg-height-percent') || 0);
1760                if (pct > 0) {
1761                    const h = (window.innerHeight || $(window).height()) * (pct / 100);
1762                    $el.height(h);
1763                }
1764            });
1765        },
1766
1767        replaceRequiredDot: function () {
1768            const dot = '/web/upload/mundane/grey_dot.png';
1769
1770            $('img').each(function () {
1771                const $img = $(this);
1772                const src = $img.attr('src') || '';
1773
1774                if (
1775                    src === '//img.echosting.cafe24.com/skin/base/order/ico_required.gif' ||
1776                    src === '//img.echosting.cafe24.com/skin/base_ko_KR/order/ico_required.gif' ||
1777                    src === '//img.echosting.cafe24.com/skin/base/common/ico_required_blue.gif'
1778                ) {
1779                    $img.attr('src', dot);
1780                }
1781            });
1782        },
1783
1784        replacePaginateIcons: function () {
1785            const prev = '/web/upload/mundane/i_arrival_prev.png';
1786            const next = '/web/upload/mundane/i_arrival_next.png';
1787
1788            const $p = $('.ec-base-paginate');
1789            if (!$p.length) return;
1790
1791            $p.find('> a:nth-of-type(1) img').attr('src', prev);
1792            $p.find('> a:nth-of-type(2) img').attr('src', next);
1793        },
1794
1795        applyPlaceholderFromTitle: function () {
1796            $('.ePlaceholder input, .ePlaceholder textarea').each(function () {
1797                const $inp = $(this);
1798                const title = $inp.parents('[title]').first().attr('title') || '';
1799                if (title) $inp.attr('placeholder', title);
1800            });
1801        },
1802
1803        applyAddOptionPlaceholder: function () {
1804            $('.ePlaceholder_addoption input').each(function () {
1805                const $inp = $(this);
1806                const t = $inp.closest('.mun-detail-desc').find('.mun-detail-title').first().text() || '';
1807                const v = $.trim(t);
1808                if (v) $inp.attr('placeholder', v);
1809            });
1810        },
1811
1812        applyOptionSelectTitle: function () {
1813            $('#mun_option .mun-option select').each(function () {
1814                const $sel = $(this);
1815                const t = $sel.attr('option_title') || '';
1816                if (!t) return;
1817                $sel.children('option:first-child').text(t);
1818            });
1819        },
1820
1821        applyFormTextWrap: function () {
1822            const $targets = $('.mun-formSP, .mun-formSE, .mun-formcalendar');
1823            if (!$targets.length) return;
1824
1825            $targets.each(function () {
1826                if (typeof H.wrapTextNodes === 'function') {
1827                    H.wrapTextNodes($(this), 'mun-formText');
1828                } else {
1829                    $(this).contents().filter(function () {
1830                        return this.nodeType === 3;
1831                    }).wrap('<span class="mun-formText"></span>');
1832                }
1833            });
1834        },
1835
1836        bindToggleList: function () {
1837            $(document).off('click.munToggleList')
1838            .on('click.munToggleList', '.ec-base-table.toggleList .toggleList-btn', function (e) {
1839                e.preventDefault();
1840                $(this).closest('.ec-base-table.toggleList').toggleClass('view');
1841            });
1842        },
1843
1844        applyDetailAddOptionTitleCut: function () {
1845            $('.mun-option-addoption .mun-detail-title').each(function () {
1846                const $t = $(this);
1847                const s = $t.text() || '';
1848                const head = s.split('[')[0];
1849                $t.text($.trim(head));
1850            });
1851        },
1852
1853        applyMunCut: function () {
1854            $('.mun_cut').each(function () {
1855                const $el = $(this);
1856                const n = Number($el.attr('data-cut') || $el.attr('mun_cut') || 0);
1857                if (!n) return;
1858
1859                const t = $el.text() || '';
1860
1861                if (typeof H.cutText === 'function') {
1862                    $el.text(H.cutText(t, n));
1863                } else {
1864                    if (t.length > n) $el.text(t.substr(0, n) + '...');
1865                }
1866            });
1867        },
1868
1869        hidePromotionDate: function () {
1870            const $t = $('.mun-detail-desc .product_promotion_date');
1871            if ($t.length) {
1872                $t.parent().css('display', 'none');
1873            }
1874        },
1875
1876        fixQuantityDummy: function () {
1877            if ($('#NewProductQuantityDummy').length > 0 && $('#totalProducts').length > 0) {
1878                $('#NewProductQuantityDummy').parents('li.mun-detail-list').remove();
1879            }
1880        }
1881    };
1882
1883    window.MUN.ui = UI;
1884
1885    UI.init();
1886
1887});
1888/* =========================
1889 * © MUNDANE
1890 * 본 파일은 먼데인이 본 스킨을 위해 제작/구성한 커스텀 JavaScript 코드입니다.
1891 * 무단 복제, 수정, 재배포 및 타 프로젝트 사용을 금합니다.
1892 * ※ 본 스킨은 jQuery, Swiper 등 제3자 라이브러리를 사용할 수 있으며,
1893 * 해당 라이브러리의 권리/라이선스는 각 저작권자에게 있습니다.
1894========================= */
1895
1896(function (window, $) {
1897
1898    if (!window.MUN) window.MUN = {};
1899
1900    const MUNHelper = {
1901
1902        trim: function (v) {
1903            return $.trim(String(v || ''));
1904        },
1905
1906        winW: function () {
1907            return window.innerWidth || $(window).width();
1908        },
1909
1910        cutText: function (text, maxLen) {
1911            const s = String(text || '');
1912            const n = Number(maxLen || 0);
1913            if (!n || n <= 0) return s;
1914            if (s.length <= n) return s;
1915            return s.substr(0, n) + '...';
1916        },
1917
1918        wrapTextNodes: function ($root, wrapClass) {
1919            const cls = String(wrapClass || 'mun-formText');
1920            $root.contents().filter(function () {
1921                return this.nodeType === 3 && $.trim(this.nodeValue).length > 0;
1922            }).wrap('<span class="' + cls + '"></span>');
1923        },
1924
1925        nsOffOn: function ($el, onType, ns, handler) {
1926            $el.off(onType + '.' + ns).on(onType + '.' + ns, handler);
1927        }
1928    };
1929
1930    window.MUN.helper = MUNHelper;
1931
1932})(window, jQuery);
1933
1934/* =========================
1935 * © MUNDANE
1936 * 본 파일은 먼데인이 본 스킨을 위해 제작/구성한 커스텀 JavaScript 코드입니다.
1937 * 무단 복제, 수정, 재배포 및 타 프로젝트 사용을 금합니다.
1938 * ※ 본 스킨은 jQuery, Swiper 등 제3자 라이브러리를 사용할 수 있으며,
1939 * 해당 라이브러리의 권리/라이선스는 각 저작권자에게 있습니다.
1940========================= */
1941
1942$(function () {
1943
1944    if (!window.MUN) window.MUN = {};
1945    const H = window.MUN.helper;
1946
1947    const Layout = {
1948
1949        sel: {
1950            logoBox: '.logo .app-box',
1951            logoImg: '.logo_img img',
1952            mobileBtn: '.mobile-btn',
1953            searchBtn: '.search-btn',
1954            bgOpacity: '#background-opacity',
1955
1956            headerNotice: '#header_notice',
1957            headerNoticeClose: '.header-notice-close',
1958            headerNoticeMargin: '.header_notice_margin',
1959            headerNoticePadding: '.header_notice_padding',
1960
1961            winHeight: '.window-height',
1962            winHeightLayout: '.window-height-layout',
1963            winHeightLayoutN: '.window-height-layoutN',
1964            winHeightLayoutNC: '.window-height-layoutNC',
1965            winHeightLayoutMH: '.window-height-layoutMH',
1966            winHeightContent: '.window-height-content',
1967            winHeightMargin: '.window-height-margin',
1968            stickyTopLayout: '.sticky-top-layout',
1969            stickyTopNoticeH: '.sticky-top-noticeH',
1970
1971            header: '#header',
1972            headerPadding: '.header_layout_padding',
1973            headerMargin: '.header_layout_margin'
1974        },
1975
1976        key: {
1977            headerNotice: 'header_notice'
1978        },
1979
1980        init: function () {
1981            Layout.applyLogoRule();
1982            Layout.bindMobileSlide();
1983            Layout.bindSearchPopup();
1984
1985            Layout.initHeaderNoticeSwiper();
1986            Layout.applyHeaderNoticeHeight();
1987            Layout.applyMediaSize();
1988
1989            Layout.bindResize();
1990            Layout.bindPageshowFix();
1991
1992            $(window).on('load.munLayout', function () { Layout.applyMediaSize(); });
1993        },
1994
1995        applyLogoRule: function () {
1996            $(Layout.sel.logoBox).each(function () {
1997                const $box = $(this);
1998                const $img = $box.find(Layout.sel.logoImg);
1999                const src = $img.attr('src') || '';
2000
2001                if (src && src.length > 0) {
2002                    $box.find('.logo_text').remove();
2003                } else {
2004                    $box.find('.logo_img').remove();
2005                }
2006            });
2007        },
2008
2009        opt: {
2010            // 모바일 슬라이드 열 때 검색을 닫을지
2011            closeSearchWhenOpenMobileSlide: true,
2012
2013            // 검색 열 때 모바일 슬라이드를 닫을지
2014            closeMobileSlideWhenOpenSearch: true,
2015
2016            // bgOpacity 클릭 시 모바일 슬라이드 닫을지
2017            closeMobileSlideOnBg: true,
2018
2019            // bgOpacity 클릭 시 검색 닫을지
2020            closeSearchOnBg: true
2021        },
2022        
2023        bindMobileSlide: function () {
2024
2025            $(document).off('click.munMobileSlideOpen')
2026                .on('click.munMobileSlideOpen', Layout.sel.mobileBtn, function (e) {
2027                e.preventDefault();
2028
2029                // 옵션: 모바일 슬라이드 열릴 때 검색 닫기
2030                if (Layout.opt.closeSearchWhenOpenMobileSlide) {
2031                    $('html').removeClass('search');
2032                }
2033
2034                $('html').toggleClass('mobile-slide');
2035
2036                const methods = window.MUNCategory;
2037
2038                if ($('html').hasClass('mobile-slide')) {
2039                    if (methods && typeof methods.openMobileCateLayerAuto === 'function') {
2040                        methods.openMobileCateLayerAuto();
2041                    }
2042                } else {
2043                    if (methods && typeof methods.closeMobileCateLayer === 'function') {
2044                        methods.closeMobileCateLayer();
2045                    }
2046                }
2047            });
2048
2049            $(document).off('click.munMobileSlideClose')
2050                .on('click.munMobileSlideClose', Layout.sel.bgOpacity, function (e) {
2051                e.preventDefault();
2052
2053                // 옵션: bg 클릭 시 모바일 슬라이드 닫기
2054                if (Layout.opt.closeMobileSlideOnBg) {
2055                    $('html').removeClass('mobile-slide');
2056
2057                    const methods = window.MUNCategory;
2058                    if (methods && typeof methods.closeMobileCateLayer === 'function') {
2059                        methods.closeMobileCateLayer();
2060                    }
2061                }
2062
2063                // 옵션: bg 클릭 시 검색 닫기
2064                if (Layout.opt.closeSearchOnBg) {
2065                    $('html').removeClass('search');
2066                }
2067            });
2068        },
2069        
2070        bindSearchPopup: function () {
2071
2072            $(document).off('click.munSearchOpen')
2073                .on('click.munSearchOpen', Layout.sel.searchBtn, function (e) {
2074                e.preventDefault();
2075
2076                // 옵션: 검색 열릴 때 모바일 슬라이드 닫기
2077                if (Layout.opt.closeMobileSlideWhenOpenSearch) {
2078                    $('html').removeClass('mobile-slide');
2079
2080                    const methods = window.MUNCategory;
2081                    if (methods && typeof methods.closeMobileCateLayer === 'function') {
2082                        methods.closeMobileCateLayer();
2083                    }
2084                }
2085
2086                $('html').toggleClass('search');
2087            });
2088
2089            $(document).off('click.munSearchClose')
2090                .on('click.munSearchClose', '.search-background', function (e) {
2091                e.preventDefault();
2092                $('html').removeClass('search');
2093            });
2094
2095            $(document).off('click.munSearchCloseByBg')
2096                .on('click.munSearchCloseByBg', Layout.sel.bgOpacity, function () {
2097                if (Layout.opt.closeSearchOnBg) {
2098                    $('html').removeClass('search');
2099                }
2100            });
2101
2102            const v = $('.M_search_target').text();
2103            if (v) {
2104                $('#category_no option[value="' + v + '"]').prop('selected', true);
2105            }
2106        },
2107
2108        initHeaderNoticeSwiper: function () {
2109
2110            if (typeof Swiper !== 'function') return;
2111
2112            const $wrap = $('.header_notice_slide');
2113            if (!$wrap.length) return;
2114
2115            const slideCnt = $wrap.find('.swiper-slide').length;
2116
2117            const opt = {
2118                direction: 'vertical',
2119                autoHeight: true,
2120                slidesPerView: 1,
2121                slidesPerGroup: 1,
2122                touchRatio: 0,
2123                autoplay: { delay: 2000, disableOnInteraction: false },
2124                speed: 1000,
2125                watchOverflow: true,
2126                loop: slideCnt > 1
2127            };
2128
2129            try {
2130                new Swiper('.header_notice_slide', opt);
2131            } catch (e) {
2132            }
2133        },
2134
2135        applyHeaderNoticeHeight: function () {
2136
2137            const $notice = $(Layout.sel.headerNotice);
2138            if (!$notice.length) return;
2139
2140            const isClosed = sessionStorage.getItem(Layout.key.headerNotice) === 'close';
2141
2142            if (isClosed) {
2143                $notice.remove();
2144                Layout.applyMediaSize();
2145                Layout.applyHeaderNoticePadding(0);
2146                Layout.applyHeaderNoticeMargin(0);
2147                return;
2148            }
2149
2150            const h = $notice.outerHeight() || 0;
2151            Layout.applyHeaderNoticePadding(h);
2152            Layout.applyHeaderNoticeMargin(h);
2153
2154            $(document).off('click.munHeaderNoticeClose')
2155                .on('click.munHeaderNoticeClose', Layout.sel.headerNoticeClose, function (e) {
2156                e.preventDefault();
2157
2158                sessionStorage.setItem(Layout.key.headerNotice, 'close');
2159
2160                const $n = $(Layout.sel.headerNotice);
2161                $n.stop(true, true).slideUp(200, function () {
2162                    $n.remove();
2163                    Layout.applyHeaderNoticePadding(0);
2164                    Layout.applyHeaderNoticeMargin(0);
2165                    Layout.applyMediaSize();
2166                });
2167            });
2168        },
2169
2170        applyHeaderNoticePadding: function (px) {
2171            const n = Number(px || 0);
2172            const $p = $(Layout.sel.headerNoticePadding);
2173            if ($p.length) $p.css('padding-top', n);
2174        },
2175
2176        applyHeaderNoticeMargin: function (px) {
2177            const n = Number(px || 0);
2178            const $m = $(Layout.sel.headerNoticeMargin);
2179            if ($m.length) $m.css('margin-top', n);
2180        },
2181
2182        applyMediaSize: function () {
2183
2184            const wh = window.innerHeight || $(window).height();
2185
2186            const $header = $(Layout.sel.header);
2187            const headerH = $header.length ? ($header.innerHeight() || $header.height() || 0) : 0;
2188
2189            const $notice = $(Layout.sel.headerNotice);
2190            const noticeH = $notice.length ? ($notice.innerHeight() || $notice.height() || 0) : 0;
2191
2192            const $footerFixed = $('#footer.fixed');
2193            const footerH = $footerFixed.length ? ($footerFixed.innerHeight() || $footerFixed.height() || 0) : 0;
2194
2195            // 기본: 100vh 대체 (모바일 주소창 대응)
2196            $(Layout.sel.winHeight).height(wh);
2197
2198            // 헤더 제외
2199            $(Layout.sel.winHeightLayout).height(wh - headerH);
2200
2201            // 공지띠만 제외 (일부 스킨에서 "notice only" 레이아웃용)
2202            $(Layout.sel.winHeightLayoutN).height(wh - noticeH);
2203
2204            // 헤더 + 공지띠 제외
2205            $(Layout.sel.winHeightLayoutNC).height(wh - headerH - noticeH);
2206
2207            // 헤더 + 공지띠 + 하단고정 제외 (모바일 하단바 같은)
2208            $(Layout.sel.winHeightLayoutMH).height(wh - headerH - noticeH - footerH);
2209
2210            // 컨텐츠 전용(헤더/공지/푸터 모두 제외하고 싶을 때)
2211            $(Layout.sel.winHeightContent).height(wh - headerH - noticeH - footerH);
2212
2213            // 마진용
2214            $(Layout.sel.winHeightMargin).css('margin-top', wh);
2215
2216            // sticky 위치/패딩 보정
2217            if ($(Layout.sel.stickyTopNoticeH).length) {
2218                $(Layout.sel.stickyTopNoticeH).css('padding-top', noticeH);
2219            }
2220            if ($(Layout.sel.stickyTopLayout).length) {
2221                $(Layout.sel.stickyTopLayout).css('top', headerH);
2222            }
2223
2224            // 헤더 패딩/마진 보정
2225            if ($(Layout.sel.headerPadding).length) {
2226                $(Layout.sel.headerPadding).css('padding-top', headerH);
2227            }
2228            if ($(Layout.sel.headerMargin).length) {
2229                $(Layout.sel.headerMargin).css('margin-top', headerH);
2230            }
2231        },
2232
2233        bindResize: function () {
2234
2235            H.nsOffOn($(window), 'resize', 'munLayout', function () {
2236                Layout.applyMediaSize();
2237
2238                // PC 전환 시 모바일 슬라이드 강제 제거 + 검색도 같이 제거
2239                if (H.winW() > 1024) {
2240                    $('html').removeClass('mobile-slide');
2241                    $('html').removeClass('search');
2242
2243                    const methods = window.MUNCategory;
2244                    if (methods && typeof methods.closeMobileCateLayer === 'function') {
2245                        methods.closeMobileCateLayer();
2246                    }
2247                }
2248            });
2249        },
2250
2251        /* ---------------------------
2252         * BFCache 복원 시(뒤로가기) 모바일에서 꼬임 방지
2253         * ------------------------- */
2254        bindPageshowFix: function () {
2255
2256            window.addEventListener('pageshow', function (e) {
2257
2258                if (e.persisted && H.winW() < 1024) {
2259
2260                    document.documentElement.classList.remove('mobile-slide');
2261                    document.documentElement.classList.remove('search');
2262
2263                    Layout.applyMediaSize();
2264                    Layout.applyHeaderNoticeHeight();
2265
2266                    // window.location.reload();
2267                }
2268            });
2269        }
2270    };
2271    
2272    Layout.init();
2273
2274}
2274);
2275$(function () {
2276
2277    const $footer = $('#footer');
2278    if (!$footer.length) return;
2279
2280    const ACTIVE_CLASS = 'active';
2281
2282    function openFooter() {
2283        $footer.addClass(ACTIVE_CLASS);
2284    }
2285
2286    function closeFooter() {
2287        $footer.removeClass(ACTIVE_CLASS);
2288    }
2289
2290    function toggleFooter() {
2291        $footer.toggleClass(ACTIVE_CLASS);
2292    }
2293
2294    // 버튼 클릭
2295    $(document)
2296        .off('click.munFooterInfoOpen')
2297        .on('click.munFooterInfoOpen', '#footer .info-btn', function (e) {
2298        e.preventDefault();
2299        e.stopPropagation();
2300        toggleFooter();
2301    });
2302
2303    // 배경 클릭 닫기
2304    $(document)
2305        .off('click.munFooterInfoClose')
2306        .on('click.munFooterInfoClose', '#footer .footer-bg', function (e) {
2307        e.preventDefault();
2308        closeFooter();
2309    });
2310
2311    // ESC 키로 닫기 (접근성)
2312    $(document)
2313        .off('keydown.munFooterInfoEsc')
2314        .on('keydown.munFooterInfoEsc', function (e) {
2315        if (e.key === 'Escape') {
2316            closeFooter();
2317        }
2318    });
2319
2320});
2321/**
2322 * 움직이는 배너 Jquery Plug-in
2323 * @author  cafe24
2324 */
2325
2326(function($){
2327
2328    $.fn.floatBanner = function(options) {
2329        options = $.extend({}, $.fn.floatBanner.defaults , options);
2330
2331        return this.each(function() {
2332            var aPosition = $(this).position();
2333            var jbOffset = $(this).offset();
2334            var node = this;
2335
2336            $(window).on('scroll', function() {
2337                var _top = $(document).scrollTop();
2338                _top = (aPosition.top < _top) ? _top : aPosition.top;
2339
2340                setTimeout(function () {
2341                    var newinit = $(document).scrollTop();
2342
2343                    if ( newinit > jbOffset.top ) {
2344                        _top -= jbOffset.top;
2345                        var container_height = $("#wrap").height();
2346                        var quick_height = $(node).height();
2347                        var cul = container_height - quick_height;
2348                        if(_top > cul){
2349                            _top = cul;
2350                        }
2351                    } else {
2352                        _top = 0;
2353                    }
2354
2355                    $(node).stop().animate({top: _top}, options.animate);
2356                }, options.delay);
2357            });
2358        });
2359    };
2360
2361    $.fn.floatBanner.defaults = {
2362        'animate'  : 500,
2363        'delay'    : 500
2364    };
2365
2366})(jQuery);
2367
2368/**
2369 * 문서 구동후 시작
2370 */
2371$(function(){
2372    $('#banner:visible, #quick:visible').floatBanner();
2373
2374    //placeholder
2375    $(".ePlaceholder input, .ePlaceholder textarea").each(function(i){
2376        var placeholderName = $(this).parents().attr('title');
2377        $(this).attr("placeholder", placeholderName);
2378    });
2379    /* placeholder ie8, ie9 */
2380    $.fn.extend({
2381        placeholder : function() {
2382            //IE 8 버전에는 hasPlaceholderSupport() 값이 false를 리턴
2383           if (hasPlaceholderSupport() === true) {
2384                return this;
2385            }
2386            //hasPlaceholderSupport() 값이 false 일 경우 아래 코드를 실행
2387            return this.each(function(){
2388                var findThis = $(this);
2389                var sPlaceholder = findThis.attr('placeholder');
2390                if ( ! sPlaceholder) {
2391                   return;
2392                }
2393                findThis.wrap('<label class="ePlaceholder" />');
2394                var sDisplayPlaceHolder = $(this).val() ? ' style="display:none;"' : '';
2395                findThis.before('<span' + sDisplayPlaceHolder + '>' + sPlaceholder + '</span>');
2396                this.onpropertychange = function(e){
2397                    e = event || e;
2398                    if (e.propertyName == 'value') {
2399                        $(this).trigger('focusout');
2400                    }
2401                };
2402                //공통 class
2403                var agent = navigator.userAgent.toLowerCase();
2404                if (agent.indexOf("msie") != -1) {
2405                    $(".ePlaceholder").css({"position":"relative"});
2406                    $(".ePlaceholder span").css({"position":"absolute", "padding":"0 4px", "color":"#878787"});
2407                    $(".ePlaceholder label").css({"padding":"0"});
2408                }
2409            });
2410        }
2411    });
2412
2413    $(':input[placeholder]').placeholder(); //placeholder() 함수를 호출
2414
2415    //클릭하면 placeholder 숨김
2416    $('body').on('click', '.ePlaceholder span', function(){
2417        $(this).hide();
2418    });
2419
2420    //input창 포커스 인 일때 placeholder 숨김
2421    $('body').on('focusin', '.ePlaceholder :input', function(){
2422        $(this).prev('span').hide();
2423    });
2424
2425    //input창 포커스 아웃 일때 value 가 true 이면 숨김, false 이면 보여짐
2426    $('body').on('focusout', '.ePlaceholder :input', function(){
2427        if (this.value) {
2428            $(this).prev('span').hide();
2429        } else {
2430            $(this).prev('span').show();
2431        }
2432    });
2433
2434    //input에 placeholder가 지원이 되면 true를 안되면 false를 리턴값으로 던져줌
2435    function hasPlaceholderSupport() {
2436        if ('placeholder' in document.createElement('input')) {
2437            return true;
2438        } else {
2439            return false;
2440        }
2441    }
2442});
2443
2444/**
2445 *  썸네일 이미지 엑박일경우 기본값 설정
2446 */
2447$(window).on('load', function() {
2448    $("img.thumb,img.ThumbImage,img.BigImage").each(function($i,$item){
2449        var $img = new Image();
2450        $img.onerror = function () {
2451            $item.src="//img.echosting.cafe24.com/thumb/img_product_big.gif";
2452        }
2453        $img.src = this.src;
2454    });
2455});
2456
2457/**
2458 *  tooltip
2459 */
2460$('.eTooltip').each(function(i){
2461    $(this).find('.btnClose').attr('tabIndex','-1');
2462});
2463//tooltip input focus
2464$('.eTooltip').find('input').on('focus', function() {
2465    var targetName = returnTagetName(this);
2466    targetName.siblings('.ec-base-tooltip').show();
2467});
2468$('.eTooltip').find('input').on('focusout', function() {
2469    var targetName = returnTagetName(this);
2470    targetName.siblings('.ec-base-tooltip').hide();
2471});
2472function returnTagetName(_this){
2473    var ePlacename = $(_this).parent().attr("class");
2474    var targetName;
2475    if(ePlacename == "ePlaceholder"){ //ePlaceholder 대응
2476        targetName = $(_this).parents();
2477    }else{
2478        targetName = $(_this);
2479    }
2480    return targetName;
2481}
2482
2483/**
2484 *  eTab
2485 */
2486$("body").on("click", ".eTab a", function(e){
2487    // 클릭한 li 에 selected 클래스 추가, 기존 li에 있는 selected 클래스는 삭제.
2488    var _li = $(this).parent("li").addClass("selected").siblings().removeClass("selected"),
2489    _target = $(this).attr("href"),
2490    _siblings = $(_target).attr("class"),
2491    _arr = _siblings.split(" "),
2492    _classSiblings = "."+_arr[0];
2493
2494    //클릭한 탭에 해당하는 요소는 활성화, 기존 요소는 비활성화 함.
2495    $(_target).show().siblings(_classSiblings).hide();
2496
2497
2498    //preventDefault 는 a 태그 처럼 클릭 이벤트 외에 별도의 브라우저 행동을 막기 위해 사용됨.
2499    e.preventDefault();
2500});
2501
2502
2503
2504//window popup script
2505function winPop(url) {
2506    window.open(url, "popup", "width=300,height=300,left=10,top=10,resizable=no,scrollbars=no");
2507}
2508/**
2509 * document.location.href split
2510 * return array Param
2511 */
2512function getQueryString(sKey)
2513{
2514    var sQueryString = document.location.search.substring(1);
2515    var aParam       = {};
2516
2517    if (sQueryString) {
2518        var aFields = sQueryString.split("&");
2519        var aField  = [];
2520        for (var i=0; i<aFields.length; i++) {
2521            aField = aFields[i].split('=');
2522            aParam[aField[0]] = aField[1];
2523        }
2524    }
2525
2526    aParam.page = aParam.page ? aParam.page : 1;
2527    return sKey ? aParam[sKey] : aParam;
2528};
2529
2530$(document).ready(function(){
2531    // tab
2532    $.eTab = function(ul){
2533        $(ul).find('a').click(function(){
2534            var _li = $(this).parent('li').addClass('selected').siblings().removeClass('selected'),
2535                _target = $(this).attr('href'),
2536                _siblings = '.' + $(_target).attr('class');
2537            $(_target).show().siblings(_siblings).hide();
2538            return false
2539        });
2540    }
2541    if ( window.call_eTab ) {
2542        call_eTab();
2543    };
2544});
2545(function($){
2546$.fn.extend({
2547    center: function() {
2548        this.each(function() {
2549            var
2550                $this = $(this),
2551                $w = $(window);
2552            $this.css({
2553                position: "absolute",
2554                top: ~~(($w.height() - $this.outerHeight()) / 2) + $w.scrollTop() + "px",
2555                left: ~~(($w.width() - $this.outerWidth()) / 2) + $w.scrollLeft() + "px"
2556            });
2557        });
2558        return this;
2559    }
2560});
2561$(function() {
2562    var $container = function(){/*
2563<div id="modalContainer">
2564    <iframe id="modalContent" scroll="0" scrolling="no" frameBorder="0"></iframe>
2565</div>');
2566*/}.toString().slice(14,-3);
2567    $('body')
2568    .append($('<div id="modalBackpanel"></div>'))
2569    .append($($container));
2570    function closeModal () {
2571        $('#modalContainer').hide();
2572        $('#modalBackpanel').hide();
2573    }
2574    $('#modalBackpanel').click(closeModal);
2575    zoom = function ($piProductNo, $piCategoryNo, $piDisplayGroup) {
2576        var $url = '/product/image_zoom.html?product_no=' + $piProductNo + '&cate_no=' + $piCategoryNo + '&display_group=' + $piDisplayGroup;
2577        $('#modalContent').attr('src', $url);
2578        $('#modalContent').bind("load",function(){
2579            $(".header .close",this.contentWindow.document.body).bind("click", closeModal);
2580        });
2581        $('#modalBackpanel').css({width:$("body").width(),height:$("body").height(),opacity:.4}).show();
2582        $('#modalContainer').center().show();
2583    }
2584});
2585})(jQuery);
2586$(function () {
2587
2588    /* ------------------------------------------------------------------
2589   * PRODUCT COLS SWITCH
2590   * ------------------------------------------------------------------ */
2591
2592    var $wrap = $('.mun-prd-wrap');
2593    if ($wrap.length === 0) return;
2594
2595    var storageKey = 'MUN_PRD_COLS';
2596    var colsClassPrefix = 'cols-';
2597
2598    function applyCols(cols) {
2599        cols = String(cols);
2600
2601        $wrap.removeClass(colsClassPrefix + '1 ' + colsClassPrefix + '2 ' + colsClassPrefix + '4');
2602        $wrap.addClass(colsClassPrefix + cols);
2603
2604        $('[data-col-switch] .mun-col-btn').removeClass('is-active');
2605        $('[data-col-switch] .mun-col-btn[data-cols="' + cols + '"]').addClass('is-active');
2606    }
2607
2608    function getSavedCols() {
2609        try { return localStorage.getItem(storageKey); }
2610        catch (e) { return null; }
2611    }
2612
2613    function setSavedCols(cols) {
2614        try { localStorage.setItem(storageKey, String(cols)); }
2615        catch (e) {}
2616    }
2617
2618    var saved = getSavedCols();
2619    var initial = saved ? saved : '4';
2620    applyCols(initial);
2621
2622    $(document).on('click', '[data-col-switch] .mun-col-btn', function () {
2623        var cols = $(this).attr('data-cols');
2624        if (!cols) return;
2625
2626        applyCols(cols);
2627        setSavedCols(cols);
2628    });
2629
2630    /* ------------------------------------------------------------------
2631   * PRODUCT LIST ORDER (MOVE IMAGE BANNER INTO LIST FIRST)
2632   * ------------------------------------------------------------------ */
2633
2634    var $banner = $('.image-banner');
2635    if ($banner.length === 0) return;
2636    if ($banner.find('img').length === 0) return;
2637
2638    var $prdList = $('.mun-prd-wrap').find('.ec-base-product').children('ul');
2639    if ($prdList.length === 0) return;
2640
2641    if ($prdList.children('.mun-prd-banner-item').length > 0) return;
2642
2643    var $bannerLi = $('<li class="mun-prd-banner-item mun-prd-list fade"></li>');
2644    $banner.before($bannerLi);      
2645    $banner.appendTo($bannerLi);    
2646    $prdList.prepend($bannerLi);   
2647
2648});

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.