PageSourceSearch

https://cdn.ccreview.co.kr/script/Bannerpop.js

js ccreview.co.kr collected 2026-10-02 19:09:53 UTC 30,588 bytes, 859 lines download raw bytes

1class Bannerpop {
2    IS_MOBILE_MODE = false;
3    POP_OPTIONS = {
4		bodyWidth:0,
5		bodyLeft:0,
6		screenWidth:0,
7		popname:"popup_",
8		width:{ window:[],layer:[] },
9		height:{ window:[],layer:[] },
10		top:{ window:[],layer:[] },
11		left:{ window:[],layer:[] },
12		order:0,						// z-index용 순차적
13		view:"normal"					// 일반 : normal or 관리자 : manager
14	};
15    constructor() {
16		const userWrap = document.querySelector("#user-wrap");
17		if (userWrap) {
18			this.IS_MOBILE_MODE = userWrap.classList.contains("mobile") ? true : false;
19		}
20    }
21
22    // 배너 append
23	static async append() {
24		const _this = this,
25			status = window.bannerStatus,
26			time = window.___currentTime || window.parent.___currentTime,
27			sTime = window.startTime,
28			eTime = window.endTime,
29			title = typeof window.bannerTitle == "undefined" ? "" : decodeURIComponent(window.bannerTitle),
30			target = document.currentScript,
31			voteUse = typeof bannerVoteUse == "undefined" ? "N" : bannerVoteUse;
32
33		let content = decodeURIComponent(bannerContent);
34
35		if(!target || target.getAttribute("data-append") == true) return false; // 객체가 없거나 시작전,이미 추가되었다면 중단
36
37		// 예정,종료 배너
38		if(sTime > time || time > eTime || status=="0"){
39			const isAdminPage = location.href.includes('/edit/adminSection.html');
40			const isUserView = document.body.classList.contains('ndip_user_body_view');
41			if (!isAdminPage && !isUserView && voteUse === 'Y' && status === "0") {
42				return false; // 종료 메시지 안 띄우기
43			}
44			//
45            let voteAdcClass = "",
46				adcMsg="",
47				adcClass="";
48
49			if(sTime > time && status != "0"){
50				adcMsg = '예약배너';
51				adcClass = "banner-later";
52			}else if(time > eTime || status == "0"){
53				adcMsg = '종료배너';
54				adcClass = "banner-finish";
55				if(voteUse == "Y") voteAdcClass = "vote_banner_box_finish";
56			}
57
58			target.setAttribute("data-append", "true");
59			const div = document.createElement('div');
60
61			if (!isAdminPage) {
62				div.className = "ad-finished " + voteAdcClass;
63			} else {
64				div.className = "ad-finished " + adcClass;
65				div.innerHTML = '<i class="icon-clock-o"></i> ' + adcMsg + ': <strong>"' + title + '"</strong>';
66			}
67			
68			target.insertAdjacentElement('afterend', div);
69
70			bannerTitle = "";  // 초기화'
71
72			return false;
73		}
74
75		const reloadScripts = async (element) => {
76			const scripts = element.querySelectorAll("script[src]");
77			const cacheVersion = Util.getCookie("nx_cache_vm")
78		
79			for (const script of scripts) {
80				await new Promise((resolve, reject) => {
81					const newScript = document.createElement("script");
82					newScript.async = true;
83					let newSrc = script.src;
84					if (cacheVersion === "vnum1") {
85						const separator = newSrc.includes("?") ? "&" : "?";
86						newSrc += separator + "version=" + new Date().getTime();
87					}
88		
89					newScript.src = newSrc;
90					script.replaceWith(newScript);
91					newScript.onload = resolve;
92					newScript.onerror = reject;
93					
94				});
95			}
96		};
97	
98		const setSizeInfo = (_this) => {
99			const idxno = _this.getAttribute("data-idxno"),
100				ul = _this.querySelector(".beb_ul"),
101				boxWidth = _this.clientWidth || _this.closest("#float_side_box").clientWidth; // 윙 사이드의 배너일경우 재측정
102				
103			let lis = ul.querySelectorAll(".beb_li"),
104				liCount = lis.length || 0;
105
106			lis.forEach(li => {
107				const len = li.querySelectorAll(".banner_box").length;
108				if (!len) {
109					li.remove();
110					lis = ul.querySelectorAll(".beb_li");
111					liCount = lis.length;
112				}
113			});
114			
115			// 부모박스 기준으로 ul 최대 넓이 지정
116			ul.style.width = (boxWidth * liCount) + "px";
117	
118			// 배너마다 넓이가 다를수 있으니 부모박스 넓이기준으로함
119			lis.forEach(li => li.style.width = boxWidth + "px");
120			
121			return {
122						idxno : idxno,
123						ul : ul,
124						lis : lis,
125						boxWidth : boxWidth,
126						liCount : liCount
127					};
128		}
129
130		const parser = new DOMParser(),
131			doc = parser.parseFromString(content, "text/html"),
132			contentBox = _this.changeCDNLink(doc.body.firstChild);
133
134		let targetIdxno = null;
135		if (target.src) {
136			const targetMatch = target.src.match(/\/(\d+)\.js/);
137			targetIdxno = (targetMatch!=null)?targetMatch[1]:null;
138		}
139
140		if (targetIdxno!=null && Util.getCookie("delay_banner")==targetIdxno) {
141			setTimeout(()=>{
142				target.after(contentBox);
143				Util.setCookie("delay_banner", "", 0);
144			}, 1000); 
145		} else target.after(contentBox);
146
147		await reloadScripts(contentBox);
148
149		if (!(contentBox.classList.contains("banner_event_box") || contentBox.classList.contains("banner-multi-box"))) return;
150
151		// 기능성 배너
152		if(contentBox.classList.contains("banner_event_box")) {
153			const type = contentBox.getAttribute("data-type");
154			const savePrefix = "banner_order_";
155
156			const ActivityRelatedFunc = {
157				// 순서대로 하나의 배너만 보임
158				order:function(){
159					const info = setSizeInfo(contentBox),
160						idxno = info.idxno,
161						lis = info.lis,
162						liCount = info.liCount - 1,
163						saveKey = savePrefix + idxno,
164						order = Number(localStorage.getItem(saveKey)) || 0;
165					// 랜덤 선택된것만 보임, 버튼 없앰
166					lis.forEach((li, i) => li.style.display = i === order ? "list-item" : "none");
167
168					localStorage.setItem(saveKey, (order >= liCount ? 0 : order + 1));
169				},
170
171				// random banner
172				random:function(){
173					const info = setSizeInfo(contentBox),
174						lis = info.lis,
175						liCount = info.liCount,
176						random = Math.floor(Math.random() * liCount);
177					// 랜덤 선택된것만 보임, 버튼 없앰
178					lis.forEach((li, i) => li.style.display = i === random ? "list-item" : "none");
179				},
180				// random 배너 선택후 슬라이드
181				randomSlide:function(){
182					this.slide(true);
183				},
184
185				// slide banner
186				// rand true or false
187				slide: function(rand){
188					const info = setSizeInfo(contentBox),
189						ul = info.ul,
190						lis = Array.from(info.lis),
191						liCount = info.liCount,
192						btnBox = contentBox.querySelector(".beb_buttons"),
193						btnStop = btnBox.querySelector(".beb_btn_stop"),
194						speed = Number(contentBox.getAttribute("data-speed")) || 0.3,
195						delayInfo = lis.map(li => Number(li.getAttribute("data-delay")) || 5),
196						boxWidth = info.boxWidth;
197					
198					let btnCurrent = null, 														// 현재 선택된 버튼 prev,next,play,stop of buttons
199						count = (rand === true ? Math.floor(Math.random() * (liCount)) : -1),	// 처음부터 +1 하고 시작하기에 -1초기값-random일때는 배너수중 1개
200						left = boxWidth,														// 움직이는 간격
201						delay = null,															// 멈춰잇는 시간(초)
202						si = null,																// setInterval 변수 : animate complete에서 delay로 해결하려 했는데 뭔가 잘 안풀림
203						tmpDelay = null,														// next, prev 시 delay 없이 넘김
204						firstBtnClicked = 0;													// prev,next로 이동하는가 - rotate에서 또한번 +,- 하기에 처음만 실행되어야 함
205
206					/**** function //s ****/
207					/*
208						다음 배너
209						@params
210						 loop : 반복될것인가
211						 mode : + or -
212					*/
213
214					lis.forEach(li => li.style.display = "list-item");
215
216					function rotate(loop, mode){
217						if(!mode) mode = "+";
218						mode === "+" ? count++ : count--;
219
220						if(count >= liCount || count <= 0) count = 0;
221						let front = count + 1;
222						if(count >= (liCount - 1)) front = 0;
223						left = boxWidth * front * -1;
224						delay = tmpDelay === null ? delayInfo[count] : tmpDelay;
225
226						si = setTimeout(() => {
227							ul.style.transition = `margin-left ${speed * 1000}ms`;
228							ul.style.marginLeft = left + "px";
229
230							ul.addEventListener('transitionend', function callback() {
231								if (loop === false) btnCurrent.disabled = false;
232								tmpDelay = null;
233								ul.removeEventListener('transitionend', callback);
234							});
235
236							if (loop !== false) rotate();
237						}, delay * 1000);
238					}
239						
240
241					// stop
242					function stop(){
243						firstBtnClicked++;
244
245						//$ul.stop(true, false);
246						clearTimeout(si);
247						tmpDelay = null;
248						btnStop.classList.add("beb_btn_start");
249						btnStop.textContent = "play";
250					}
251
252					// restart
253					function start(){
254						firstBtnClicked = 0;
255
256						count--;
257						if(count<=0) count=0;
258
259						tmpDelay = null;
260						rotate();
261
262						btnStop.classList.remove("beb_btn_start");
263						btnStop.textContent = "멈춤";
264					}
265
266					// 이전
267					function prev(){
268						stop();
269
270						if(firstBtnClicked === 1) count--;			// 처음만 이미 증가된값을 감소시킴
271						if(count <= 0) count = liCount;
272
273						tmpDelay=0;
274						rotate(false, "-");
275
276						btnCurrent.disabled = true;
277					}
278
279					// 이후
280					function next(){
281						stop();
282
283						if(firstBtnClicked === 1) count--;
284						if(count >= liCount) count=0;
285
286						tmpDelay = 0;
287						rotate(false);
288
289						btnCurrent.disabled = true;
290					}
291					/**** function //e ****/
292
293					// 처음 배너를 보이지 않는다는 것은 랜덤 배너의 슬라이드라는 것-처음보일배너 설정
294					if(count >= 0 && rand === true){
295						let _boxWidth = boxWidth * (count >= liCount ? liCount -1 : count) * -1;
296						count--;
297
298						ul.style.marginLeft = _boxWidth + "px";
299					}
300
301					// 실행
302					rotate();
303
304					// 버튼보임
305					btnBox.addEventListener("click", (e) => {
306						const target = e.target.closest("button.beb_btns");
307						if(!target) return;
308						btnCurrent = target;
309						
310						if(target.classList.contains("beb_btn_prev")) prev();
311						if(target.classList.contains("beb_btn_next")) next();
312						if(target.classList.contains("beb_btn_stop")) target.classList.contains("beb_btn_start") ? start() : stop();
313					});
314
315					// mouseover event
316					if (_this.IS_MOBILE_MODE) {
317						ul.addEventListener('touchstart', stop);
318						ul.addEventListener('touchend', start);
319					} else {
320						ul.addEventListener('mouseenter', stop);
321						ul.addEventListener('mouseleave', start);
322					}
323				},
324			};
325
326			
327			ActivityRelatedFunc[type]();
328
329		}
330
331		// 멀티 기능성 배너
332		if(contentBox.classList.contains("banner-multi-box")) {
333			this.bannerLoad(contentBox);
334		}
335		//$(target).attr("data-append","true").after(content);	// 추가 되었으면 data-append 태그 나김
336	}
337
338	// script, img link cdn 링크로 치환
339	static changeCDNLink(dom) {
340		let cdnDomain = "";
341		if("CDN_DOMAIN" in window) cdnDomain=window.CDN_DOMAIN;
342		else if("CDN_DOMAIN" in window.parent) dnDomain=window.parent.CDN_DOMAIN;
343		else if("CDN_DOMAIN" in window.opener) dnDomain=window.opener.CDN_DOMAIN;
344
345		if(!cdnDomain || !(/^http(s)?:/i.test(cdnDomain) || /^\/\//i.test(cdnDomain))) return dom;
346
347		let els=dom.querySelectorAll("script[src] , img[src]"); //console.log(els)
348		if(els.length<=0) return dom;
349		
350		els.forEach((a)=>{
351			const src = a.getAttribute("src");
352			if(src && !/^http(s)?:/i.test(src) && !/^\/\//i.test(src)) a.src = cdnDomain + src;
353		});
354
355		return dom;
356	}
357
358	static bannerLoad(contentBox) {
359        const effectType = contentBox.getAttribute("data-effect-type"),
360			rowNum = parseInt(contentBox.getAttribute("data-row-num"), 10) || 1,
361			colNum = Number(contentBox.getAttribute("data-column-num")) || 1,
362			scrollNum = parseInt(contentBox.getAttribute("data-scroll-num"), 10) || 1,
363			moveDisplay = contentBox.getAttribute("data-move-display") || 'none',
364			isAutoPlay = contentBox.getAttribute("data-autoplay") == "Y",
365			autoplaySpeed = parseInt(contentBox.getAttribute("data-autoplay-speed"), 10) || 5,
366			speed = parseInt(contentBox.getAttribute("data-speed"), 10) || 300,
367			isRandom = contentBox.getAttribute("data-random") == "Y";
368
369		// 예약배너이거나 종료 배너일 경우 제외 처리.
370		if (location.href.indexOf('/edit/adminSection.html') < 0) {
371			contentBox.querySelectorAll(".slick-slide").forEach(function(slide) {
372				if (slide.querySelectorAll('.banner_box').length <= 0) {
373					slide.remove();
374				}
375			});
376		}
377
378		if(effectType != "none") {
379			const totalSlide = contentBox.querySelectorAll(".slick-slide").length || 0,
380				slideCount = effectType == "horizon" ? (totalSlide / rowNum) || 0 : totalSlide,
381				randomStart = isRandom ? Math.floor(Math.random() * slideCount) : 0;
382			
383			const slickParam = {};
384            slickParam.prevArrow = '<button type="button" class="roll-btns btn-prev"><i class="icon-angle-left-thin"><span class="show-for-sr">prev</span></i></button>';  // 이전버튼
385            slickParam.nextArrow = '<button type="button" class="roll-btns btn-next"><i class="icon-angle-right-thin"><span class="show-for-sr">next</span></i></button>'; // 다음버튼
386            slickParam.infinite = true;                                                                                                                     // 무한 넘기기
387            slickParam.draggable = false;    
388			switch(effectType) {
389				case "vertical" :
390					slickParam.slidesToShow = rowNum;
391					slickParam.vertical = true;
392					slickParam.verticalSwiping = true;
393					if(isRandom && totalSlide > rowNum) slickParam.initialSlide = randomStart;
394					break;
395				case "horizon":
396				default:
397					slickParam.slidesToShow = parseInt(colNum , 10);
398                    if (rowNum > 1) slickParam.rows = rowNum;
399                    if (isRandom) slickParam.initialSlide = randomStart;
400                    break;
401			}
402			slickParam.slidesToScroll = scrollNum;
403            slickParam.arrows = moveDisplay == "arrow" ? true : false;
404            slickParam.dots = moveDisplay == "dot" ? true : false;
405            slickParam.dotsClass = "auto-pager";
406            slickParam.autoplay = isAutoPlay ? true : false;
407            slickParam.autoplaySpeed = isAutoPlay ? autoplaySpeed * 1000 : 0;
408            slickParam.speed = speed;
409            slickParam.centerMode = false;
410            slickParam.variableWidth = false;
411            slickParam.focusOnSelect = true;
412
413            $(contentBox).slick(slickParam);
414		} else {
415			if (isRandom) shuffle($(contentBox));
416		}
417
418		function shuffleArray(d) {
419            for (var c = d.length - 1; c > 0; c--) {
420                var b = Math.floor(Math.random() * (c + 1));
421                var a = d[c];
422                d[c] = d[b];
423                d[b] = a;
424            }
425            return d;
426        }
427        
428		function shuffle(target){
429            var $box = $(target).children(".slick-slide-none")
430                ,$container = $box.children(".row")
431                ,$li = $box.find(".columns")
432                ,total = $li.length
433                ,tmp = [];
434            for(var i=0;i<total;i++) tmp.push(i);
435            $container.empty();
436            setTimeout(
437                shuffleArray(tmp).forEach(function(a,b){
438                    var $bannerBoxs=$li[a].querySelectorAll(".banner_box")
439                        ,length=$bannerBoxs.length
440                        ,div=document.createElement("div");
441                    for(var i=0;i<length;i++){
442                        div.appendChild($bannerBoxs[i]);
443                        div.className = "columns";
444                    }
445                    $container.append(div);
446                })
447            ,0);
448        }
449    }
450
451    float(j) {
452        // json 값
453        const parents = this, 
454			current = window. ___currentTime,
455            start = Number(j.start) || 0,
456            end = Number(j.end) || (new Date().getTime() + 100),
457            status = j.status || "0";
458        
459        if(this.POP_OPTIONS.view != "manager" && (status == "0" || current < start || (current > end && end !== 0))) return false;
460
461        const idxno = j.idxno || "0",
462			popupType = j.popup_type || "window",
463			popupWidth = Number(j.popup_width) || 0,
464			popupHeight = (Number(j.popup_height) || 0),
465			contentType = j.content_type||"FILE",
466			bottomClose = j.bottom_close||"N",
467			bottomCloseExpireCk = j.bottom_close_expire_ck || "none",
468			bottomCloseExpire	= j.bottom_close_expire || 1,
469			layerBorder = j.layer_border || "N",
470			layerMove = j.layer_move || "N",
471			layerScroll = j.layer_scroll || "N",
472			layerClosePosition = j.layer_close_position || "BR",
473			windowScroll = j.window_scroll || "Y",
474			content = decodeURIComponent(j.content) || "",
475			popname = this.POP_OPTIONS.popname + idxno,
476			_type = popupType; 								// default: 각자띄움 - 팝업과 레이어가 위치값을 공유하여 차례로 띄울려면 "window" or 공유하지 않고 각자 띄울려면 popupType;
477
478		let top = 0,
479			left = 0,
480			xPosition = Number(j.x_position) || 0,
481			yPosition = Number(j.y_position) || 0;
482		
483		const type = {
484			calcPosition: function() {
485				// x,y가 0일때는 auto로 간주
486				if((xPosition == "0" && yPosition == "0")) {
487					const maxHeight = parents.arrayMaxMin(parents.POP_OPTIONS.height[_type], "max"),
488						maxTop = parents.arrayMaxMin(parents.POP_OPTIONS.top[_type], "max"),
489						initLeft = popupType == "window" ? 0 : parents.POP_OPTIONS.bodyLeft,
490						prevWidth = parents.POP_OPTIONS.width[_type][parents.POP_OPTIONS.width[_type].length - 1] || 0,
491						prevLeft = parents.POP_OPTIONS.left[_type][parents.POP_OPTIONS.left[_type].length - 1] || initLeft;
492
493					left = prevLeft + prevWidth;
494
495					if(left > parents.POP_OPTIONS[popupType == "window" ? "screenWidth" : "bodyWidth"]) {
496						top += maxHeight;
497						left = initLeft;
498
499						parents.POP_OPTIONS.width[_type] = [];
500						parents.POP_OPTIONS.height[_type] = [];
501						parents.POP_OPTIONS.top[_type] = [];
502						parents.POP_OPTIONS.left[_type] = [];
503					} else {
504						top = (maxTop || 0);
505					}
506
507					// 변화된값 배열에 넣기 위해 조작
508					xPosition = left;
509					yPosition = top;
510
511					// 변수에 담음
512					parents.POP_OPTIONS.width[_type].push(popupWidth || 0);
513					parents.POP_OPTIONS.height[_type].push(popupHeight || 0);
514					parents.POP_OPTIONS.top[_type].push(yPosition || 0);
515					parents.POP_OPTIONS.left[_type].push(xPosition || 0);
516				} else {
517					top = yPosition;
518					left = xPosition;
519				}
520			},
521
522			// 관리자 미리보기시 중앙에
523			setPositionCenter: function(){
524				const _width = (document.body.clientWidth/2)-(popupWidth/2),
525					_scrollTop = document.body.scrollTop;
526
527				top = _scrollTop + 50;
528				left = (_width>0)?_width:0;
529			},
530
531			// 띄울 페이지 applyPage
532			isApplyPage: function() {
533				if(parents.POP_OPTIONS.view == "manager") return true;
534			},
535
536			window:function(){
537				this.calcPosition(); // 위치 계산
538				const winpopupUrl = '/bannerpop/popup.html?win_popup_idxno=' + idxno;
539				window.open(winpopupUrl, popname, "width="+popupWidth+",height="+(popupHeight + ((bottomCloseExpireCk=='none'&&bottomClose=='N')?0:40))+",scrollbars="+(windowScroll=="Y"?"yes":"no")+",resizable=yes,top="+top+",left="+left);
540			},
541
542			layer:function(){
543				this.calcPosition(); // 위치 계산
544
545				// HTML 문자열 DOM 요소로 변환
546				const parser = new DOMParser(),
547					doc = parser.parseFromString(content, 'text/html'),
548					contentBox = parents.constructor.changeCDNLink(doc.body.firstChild);
549
550				contentBox.id = popname;
551				if (layerMove == "Y" && parents.IS_MOBILE_MODE!==true) contentBox.style.setProperty("--nd-popup-transform", "none");
552				contentBox.style.setProperty("--nd-popup-offset-x", left + "px");
553				contentBox.style.setProperty("--nd-popup-offset-y", top + "px");
554				contentBox.style.setProperty("--nd-popup-width", popupWidth + "px");
555				contentBox.style.setProperty("--nd-popup-height", popupHeight + "px");
556				contentBox.style.setProperty("--nd-popup-zindex", "110" + parents.POP_OPTIONS.order);
557				contentBox.classList.add("layer_box");
558
559				if(contentType == "HTML") contentBox.classList.add("for-html");
560
561				if(layerScroll === "Y") contentBox.classList.add("layer_box_fixed");
562
563				if(layerBorder === "Y") contentBox.classList.add("layer_box_border");
564
565				const closeBox = contentBox.querySelector(".popup_close_box");
566				if(closeBox) {
567					closeBox.classList.add("layer_close_box");
568				}
569
570				if(layerMove == "Y" && parents.IS_MOBILE_MODE!==true){
571					contentBox.classList.add("layer_box_cursor_move");
572					parents.enableDraggable(contentBox);
573				}
574
575				// 창닫기-icon 닫기 버튼은 별개다
576				//if(bottomClose=="Y"){
577				const btnClose = contentBox.querySelectorAll(".popup_close, .popup_close_map, .popup_icon_close"),
578					hasPopupCloseElements = contentBox.querySelectorAll(".popup_close, .popup_close_map").length > 0;
579
580				btnClose.forEach(btn => {
581					if (btn.classList.contains("popup_icon_close")) {
582						// 버튼위치 잡는데 불필요해서 주석(2024-05-17)
583						// if ((layerClosePosition == 'BL' || layerClosePosition == 'BR') && hasPopupCloseElements) {
584						// 	btn.style.top = Number(j.popup_height) - 30 + "px";
585						// }
586						if(!hasPopupCloseElements) {
587							contentBox.classList.add("no-footer");
588						}
589						btn.classList.add("layer_position_" + layerClosePosition);
590					}
591				});
592
593				btnClose.forEach(btn => btn.addEventListener("click", () => {
594					parents.evtClose(popupType, idxno);
595					return false;
596				}));
597				//}
598
599				// 이미지내 링크가 창닫기 라면
600				//$content.find("a[href*='javascript:window.close()']").click(function(){
601				const elements = contentBox.querySelectorAll("[href*='javascript:window.close()']");
602				elements.forEach(element => element.addEventListener("click", () => {
603					parents.evtClose(popupType, idxno);
604					return false;
605				}));
606
607				const popupDays = contentBox.querySelectorAll(".popup-days, .popup_day_close_map");
608				// 하루, 몇일동안 열지 않기
609				parents.daysNotOpen(bottomCloseExpireCk, bottomCloseExpire, popupDays, j);
610
611				if(parents.POP_OPTIONS.view == "manager"){
612					document.body.appendChild(contentBox);
613					this.setPositionCenter();
614					contentBox.classList.remove("layer_box_fixed");
615					contentBox.style.setProperty("--nd-popup-transform", "none");
616					contentBox.style.setProperty("--nd-popup-offset-y", top + "px");
617					contentBox.style.setProperty("--nd-popup-offset-x", left + "px");
618				}else {
619					 document.querySelector("#layer-popups").appendChild(contentBox);
620				}
621
622				// 이미지맵 리사이즈
623				$('img[usemap]', contentBox).rwdImageMaps();
624			}
625		};
626
627		type[popupType]();
628    }
629
630	// 팝업띄우기
631	popup() {
632		if(!window.___popup) return;
633		if(Array.isArray(___popup) === false && ___popup.length > 0) return;
634		if(!window.___currentTime) ___currentTime = Math.floor(new Date().getTime() / 1000);
635
636		const content = document.querySelector("#layer-popups");
637
638		if(!content) return false;
639
640		this.POP_OPTIONS.bodyWidth = content.clientWidth;
641		this.POP_OPTIONS.screenWidth = window.screen.width;
642		
643		for(let i = 0, cnt = ___popup.length ; i < cnt ; i++ ){
644			// 쿠키인지 판단후 열기
645			let coo = "";
646			coo = Util.getCookie(this.POP_OPTIONS.popname + ___popup[i].idxno);
647
648			if(!coo){
649				this.POP_OPTIONS.order++;
650				this.float(___popup[i]);
651			}
652		}
653	}
654
655	// 창닫기
656	evtClose(mode, idxno) {
657		if(mode=="layer"){
658			const layerId = this.POP_OPTIONS.popname + idxno;
659
660			$("#"+layerId).fadeOut("fast", function(){
661				$(this).remove();
662			});
663		}else window.close();
664	}
665
666	// cookie
667	evtCookieClose(name, days) {
668		Util.setCookie(name, "popup", days);
669	}
670
671	// 하루, 몇일동안 열지 않기.
672	daysNotOpen(expire, period, btns, p) {
673		const idxno = p.idxno;
674		let isClickedMap = false;
675		const addListenerAndClose = (element, days) => {
676			element.addEventListener("click", () => {
677				this.evtCookieClose(this.POP_OPTIONS.popname + idxno, Number(days)||1);
678				this.evtClose(p.popup_type, idxno);
679				return false;
680			});
681		};
682	
683		if (expire !== "none") {
684			btns.forEach(btn => {
685				if (btn.classList.contains("popup-days")) {
686					// 하루동안 열지 않기
687					if (expire === "day") {
688						addListenerAndClose(btn, "1");
689						if (!btn.hasChildNodes()) {
690							btn.innerHTML = '<a href="#close-to-layer">하루동안 보지 않기</a>';
691						}
692					} 
693					// 지정된 일수 동안 열지 않기
694					else if (expire === "days") {
695						const html = `<a href="#link">${period > 1 ? period + '일 동안 보지 않기' : '하루 동안 보지 않기'}</a>`;
696						btn.insertAdjacentHTML('beforeend', html);
697						addListenerAndClose(btn, period);
698					}
699				} else {
700					addListenerAndClose(btn, "1");
701					isClickedMap = true;
702				}
703			});
704		}
705
706		// expire 값이랑 관계없이 이미지맵을 찾아 처리
707        if (isClickedMap === false) {
708            btns.forEach((btn) =>
709                btn.addEventListener("click", () =>
710                    addListenerAndClose(btn, "1")
711                )
712            );
713        }
714	}
715
716	// window popup control
717	popupControl(){
718		if(!___popup) return ;
719		if((typeof ___popup) !== "object") return ;
720		const p = ___popup,
721			title = decodeURIComponent(p.title)||"",
722			popupType = p.popup_type||"window",
723			bottomClose = p.bottom_close||"Y",
724			bottomCloseExpireCk = p.bottom_close_expire_ck||"day",	// : day,days,none
725			bottomCloseExpire = p.bottom_close_expire||1,	// : 몇일
726			btnClose = document.querySelectorAll(".popup_close, .popup_close_map, .popup_icon_close"),
727			btnDayClose = document.querySelectorAll('.popup-days');
728
729		if(popupType!="window") return ;
730
731		// 윈도우 바 타이틀 교체
732		document.title = title;
733
734		// 창닫기
735		if(bottomClose=="Y"){
736			btnClose.forEach(btn => {
737				btn.addEventListener("click", () => {
738					this.evtClose(p.popup_type, p.idxno);
739					return false;
740				});
741			});
742		}
743
744		// 하루, 몇일동안 열지 않기
745		this.daysNotOpen(bottomCloseExpireCk, bottomCloseExpire, btnDayClose, p);
746	}
747
748	enableDraggable(ele) {
749		let isDragging = false;        
750		let dragStartX, dragStartY;
751		let initTranslateX = 0,  
752			initTranslateY = 0;
753
754		const draggableEle = ele;
755		const linksAndAreas = ele.querySelectorAll('a, area');
756
757		linksAndAreas.forEach(element => {
758			element.style.cursor = 'move';
759		});
760		ele.addEventListener("click", (e) => e.preventDefault());
761		const onPointerDown = (e) => {
762			e.preventDefault();
763			isDragging = true;
764			dragStartX = e.pageX;
765			dragStartY = e.pageY;
766
767			const transform = window.getComputedStyle(draggableEle).transform;
768			if (transform !== 'none') {
769				const matrix = new DOMMatrixReadOnly(transform);
770				initTranslateX = matrix.m41;
771				initTranslateY = matrix.m42;
772			} else {
773				initTranslateX = 0;
774				initTranslateY = 0;
775			}
776		};
777
778		const onPointerMove = (e) => {
779			if (!isDragging) return;                       
780
781			const moveX = e.pageX - dragStartX;
782			const moveY = e.pageY - dragStartY;
783
784			const translateX = initTranslateX + moveX;
785			const translateY = initTranslateY + moveY;
786			draggableEle.style.setProperty("--nd-popup-transform", `translate(${translateX}px, ${translateY}px)`);
787		};
788
789		const onPointerUp = () => {
790			isDragging = false;
791		};
792
793		draggableEle.addEventListener('mousedown', onPointerDown);
794		document.addEventListener('mousemove', onPointerMove);
795		document.addEventListener('mouseup', onPointerUp);
796	}
797
798	// array 최고값
799	arrayMaxMin(arr, mode) {
800		if(Array.isArray(arr) === false) return false;
801
802		if(!mode) mode = "max";
803		arr.sort(function(a, b){
804			return b - a;
805		});
806		return (mode=="max"? arr[0] : arr[arr.length-1]) || 0;
807	}
808
809    // 통계 애널리틱스 이벤트 연결
810    analytics(type, banner, agent) {
811        if (!type||!banner||!agent) return;
812
813        switch (type) {
814            case "view":
815                agent.forEach(function(agt) {
816                    try{
817                        if (agt=="ga" && typeof ga!="undefined") {
818                            ga('send', 'event', '배너뷰', 'NDVIEWBANNER', banner);
819                        }
820                        if (agt=="gtag" && typeof gtag!="undefined") {
821                            gtag('event', 'NDVIEWBANNER', {'event_category': '배너뷰', 'event_label': banner});
822                        }
823                        if (agt=="gtm" && typeof dataLayer!="undefined") {
824                            dataLayer.push({'event':'NDVIEWBANNER','event_category':'배너뷰', 'event_label':banner});
825                        }
826                        if (agt=="wcsnaver" && typeof wcs!="undefined") {
827                            wcs.event(banner, 'NDVIEWBANNER');
828                        }
829                    } catch (e) {}
830                });
831                break;
832
833            case "click":
834                agent.forEach(function(agt) {
835                    try {
836                        if (agt=="ga" && typeof ga!="undefined") {
837                            ga('send', 'event', '배너클릭', 'NDCLICKBANNER', banner);
838                        }
839                        if (agt=="gtag" && typeof gtag!="undefined") {
840                            gtag('event', 'NDCLICKBANNER', {'event_category': '배너클릭', 'event_label': banner});
841                        }
842                        if (agt=="gtm" && typeof dataLayer!="undefined") {
843                            dataLayer.push({'event':'NDCLICKBANNER','event_category':'배너클릭', 'event_label':banner});
844                        }
845                        if (agt=="wcsnaver" && typeof wcs!="undefined") {
846                            wcs.event(banner, 'NDCLICKBANNER');
847                        }
848                    } catch(e) {}
849                });
850                break;
851        }
852
853        // Tip!!
854        // ga('send', 'event', 카테고리, 액션, 라벨)                    // 구글 유니버설 애널리í‹
854±ìФ 태그 사용시 (analytics.js)
855        // gtag('event', event_name, {event_category, event_label})    // 구글 글로벌 사이트 태그 사용시 (gtag.js)
856        // dataLayer.push({var:value});                                // 구글 태그 관리자 데이터 영역 변수 필요시 (GA4 구성 사용)
857        // wcs.event('이벤트카테고리명', '이벤트명')                     // 네이버 애널리틱스 사용시
858    }
859}

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.