PageSourceSearch

https://contents.kyobobook.co.kr/resources/fo/js/ui_ink.js?t=26917142027

js kyobobook.co.kr collected 2026-09-24 08:29:45 UTC 80,931 bytes, 2,689 lines download raw bytes

1/*
2 * name : ui.js
3 * desc : 공통 자바스크립트
4 * writer : glim
5 * create : 2021/11/12
6 * update : 2022/05/12
7 * -
8 */
9
10if (window.NodeList && !NodeList.prototype.forEach) {
11	NodeList.prototype.forEach = function (callback, thisArg) {
12		thisArg = thisArg || window;
13		for (var i = 0; i < this.length; i++) {
14			callback.call(thisArg, this[i], i, this);
15		}
16	};
17}
18
19Element.prototype._getBoundingClientRect = Element.prototype.getBoundingClientRect
20Element.prototype.getBoundingClientRect = function () {
21	var rect = Element.prototype._getBoundingClientRect.call(this);
22	rect.x = rect.left;
23	rect.y = rect.top;
24	return rect;
25}
26
27var KyoboBookPub = KyoboBookPub || {};
28
29$(function () {
30	$.widget("ui.selectmenu", $.ui.selectmenu, {
31		calcMenuWidth: function () {
32			var instance;
33			instance = this;
34
35			btnWidth = instance.button.outerWidth();
36			menuWidth = instance.menuWrap.outerWidth();
37			// console.log('calcMenuWidth', this, btnWidth, menuWidth);
38			instance.menuWrap.css('width', btnWidth);
39		}
40	});
41
42	// 상품 옵션 커스터마이징
43	$.widget('custom.selectProdOption', $.ui.selectmenu, {
44		_renderItem: function (ul, item) {
45			var li,
46				wrapper,
47				labelBox,
48				priceBox,
49				isPBProd;
50			li = $('<li>');
51			wrapper = $('<div>', {
52				'class': 'prod_option',
53			});
54
55			if (item.disabled) {
56				li.addClass('ui-state-disabled');
57			}
58			isPBProd = item.element.attr('data-prod-pb') !== undefined ? true : false;
59			wrapper.data(item.element.data());
60
61			labelBox = $('<span>', {
62				'class': 'option_label_box',
63				'text': item.label,
64			});
65
66			priceBox = $('<span>', {
67				'class': 'option_price_box',
68			});
69
70			if (item.disabled && isPBProd) {
71				$('<button>', {
72					'class': 'btn_option_restock' + (isPBProd ? ' prod_pb' : ''),
73					'text': '재입고알림',
74				}).appendTo(priceBox);
75			} else if (!item.disabled) {
76				$('<span>', {
77					'class': 'option_price' + (isPBProd ? ' prod_pb' : ''),
78					'text': item.element.attr('data-price'),
79				}).appendTo(priceBox);
80				$('<span>', {
81					'class': 'option_price_unit',
82					'text': item.element.attr('data-unit'),
83				}).appendTo(priceBox);
84			}
85
86			wrapper.append(labelBox).append(priceBox);
87			return li.append(wrapper).appendTo(ul);
88		}
89	});
90});
91
92KyoboBookPub.ink = (function () {
93	var _front = {},
94		_bodyMinWidth = 1440,
95		_dialogCount = 0,
96		_deviceWidth = 0,
97		_deviceHeight = 0,
98		_scrollLeft = 0,
99		saveScrollLeft = 0,
100		_scrollTop = 0,
101		saveScrollTop = 0,
102		_headerWrapper,
103		_flyMenuEl,
104		_floatingEl,
105		_container,
106		_btnGoTop,
107		_btnCurationBot,
108		_loadingAni;
109
110	/**
111	 * GNB 메뉴 엑티브 상태 이벤트 설정
112	 */
113	function setGNB() {
114		if (_headerWrapper === undefined) {
115			return;
116		}
117
118		// console.log(_headerWrapper)
119		var searchIp = $('.search_input_wrap');
120		var anbWrap = $('.anb_wrap');
121		var serviceMore = $('.gnb_sub_list .gnb_sub_item.more_service');
122		var serviceMore2 = $('.gnb_list .gnb_item.more_service'); // 수정 240816 서비스 더보기 버튼 이동
123		var brandMore = $('.service_mall_list .service_mall_item.brand_more');
124		var memberBenefitMore = $('.customer_service_list .customer_service_item.member_benefit');
125		var autoCompleteLayer = $('.auto_complete_wrap', _headerWrapper);
126		var saveScrollLeft = 0;
127		var headerFixedOffset = 0;
128
129		// header sps set
130		if (_headerWrapper.hasClass('sps')) {
131			_headerWrapper.attr('data-sps-offset', Math.round($('.gnb_wrap').offset().top));
132			headerFixedOffset = parseInt(_headerWrapper.attr('data-sps-offset'));
133
134			$(window).off('scroll.uiGnb resize.uiGnb', headerScrollPosX).on('scroll.uiGnb resize.uiGnb', headerScrollPosX);
135
136			function headerScrollPosX() {
137				if (_scrollTop > headerFixedOffset) {
138					if (_bodyMinWidth > _deviceWidth && _deviceWidth > 0) {
139						_headerWrapper.css({
140							'transform': 'translateX(' + -_scrollLeft + 'px)'
141						});
142
143						saveScrollLeft = _scrollLeft;
144					}
145				} else {
146					_headerWrapper.css({
147						'transform': ''
148					});
149				}
150			}
151		}
152
153		if (anbWrap.find('.anb_area .tab_wrap').length > 0) {
154			// 서비스 전체보기 masonry 적용
155			anbWrap.find('.anb_area .tab_wrap').on({
156				'tabsactivate': function (event, ui) {
157					if ($(ui.newPanel).hasClass('anb_service')) {
158						var masonryContainer = $(ui.newPanel).find('.all_service_list');
159						var anbAllService = masonryContainer.masonry({
160							// options기
161							itemSelector: '.anb_service .all_service_list .all_service_item',
162							horizontalOrder: true,
163							transitionDuration: 0,
164							initLayout: false,
165						});
166
167						anbAllService.masonry();
168					}
169				},
170			});
171		}
172
173		// 통합검색 레이어창
174		$('.btn_layer_close, .button_layer_close', autoCompleteLayer).on('click', function () { // 수정 240625 닫기 버튼 수정
175			autoCompleteLayer.removeClass('active');
176		});
177
178		// 브랜드 리스트 height
179		var brandMenu = $('.brand_more_list_box');
180		var brandMenuHeight = 0;
181
182		function setCalcBrandMenuHeight() {
183			if (brandMenuHeight === 0) {
184				brandMenu.css('display', 'block'); // 수정 240710 높이 계산 오류 방지
185				$('.brand_more_list .brand_more_item', brandMenu).each(function (i) {
186					//if (i % 2 === 0 && i < 10) {
187					if (($('.header_wrapper').hasClass('header_v2') || i % 2 === 0) && i < 10) { // 수정 240109 GNB 고객경험 통합 개선
188						brandMenuHeight += $(this).outerHeight(true);
189					}
190				})
191
192				brandMenu.height((brandMenuHeight));
193				brandMenu.css('display', ''); // 수정 240710 높이 계산 오류 방지
194			}
195		}
196
197
198		// 검색어 입력 시 검색창 x버튼(초기화버튼 노출)
199		setSearchInput(searchIp, '.ip_gnb_search');
200
201		// 서비스 더보기 on/off
202		moreListToggle(serviceMore, serviceMore.find('.btn_more_service'));
203		moreListToggle(serviceMore2, serviceMore2.find('.btn_more_service')); // 수정 240816 서비스 더보기 버튼 이동
204
205		// 전체메뉴 on/off
206		moreListToggle(anbWrap, anbWrap.find('.btn_anb'));
207
208		// 브랜드 더보기 on/off
209		moreListToggle(brandMore, brandMore.find('.btn_brand_more'), setCalcBrandMenuHeight);
210
211		// 회원혜택 더보기 on/off
212		moreListToggle(memberBenefitMore, memberBenefitMore.find('.btn_member_benefit'));
213
214		// 커튼배너
215		curtainBannerOnOff();
216
217		function moreListToggle(container, tg, callback) {
218			tg.on({
219				'click': function () {
220					if (container.hasClass('active')) {
221						container.removeClass('active animated');
222					} else {
223						container.addClass('active');
224
225						setTimeout(function () {
226							container.addClass('animated');
227
228							if (callback != null && typeof callback === "function") {
229								callback.apply(null, [container]);
230							}
231						}, 30);
232					}
233				},
234			});
235
236			// 수정 240625 브랜드 더보기, 회원혜택 hover 동작 추가
237			if (container.is(brandMore) || container.is(memberBenefitMore)) {
238				container.on({
239					'mouseenter': function () {
240						container.removeClass('active');
241						tg.click();
242					},
243					'mouseleave': function () {
244						container.addClass('active');
245						tg.click();
246					}
247				})
248			}
249		}
250
251		/* 수정 221006 커튼배너 1회 강제노출 (쿠키 사용) */
252		function curtainBannerOnOff() {
253			var curtainBanner = $('.curtain_banner_wrap');
254			curtainBanner.find('.btn_curtain_expand').on('click', function () {
255				curtainBanner.addClass('active');
256			});
257
258			curtainBanner.find('.btn_curtain_close').on('click', function () {
259				curtainBanner.removeClass('active');
260			});
261
262			// 수정 240625 커튼 배너 hover 동작 추가
263			curtainBanner.on({
264				'mouseenter': function () {
265					curtainBanner.addClass('active');
266				},
267				'mouseleave': function () {
268					curtainBanner.removeClass('active');
269				}
270			})
271
272			function getCookieVal (offset) {
273				var endstr = document.cookie.indexOf (";", offset);
274				if (endstr == -1)
275					endstr = document.cookie.length;
276				return unescape(document.cookie.substring(offset, endstr));
277			}
278			function getCookie (name) {
279				var arg = name + "=";
280				var alen = arg.length;
281				var clen = document.cookie.length;
282				var i = 0;
283				while (i < clen) {
284					var j = i + alen;
285					if (document.cookie.substring(i, j) == arg)
286						return getCookieVal (j);
287					i = document.cookie.indexOf(" ", i) + 1;
288					if (i == 0) break;
289				}
290				return null;
291			}
292			function setCookie(name, value, expiredays) {
293				var todayDate = new Date();
294				todayDate.setDate( todayDate.getDate() + expiredays );
295				document.cookie = name + "=" + escape( value ) + "; path=/; expires=" + todayDate.toGMTString() + ";"
296			}
297
298			if($('.wrapper').is('.welcome') && getCookie('welBigBan') == null){
299				curtainBanner.find('.btn_curtain_expand').trigger('click');
300				var timer = setTimeout(function(){
301					curtainBanner.find('.btn_curtain_close').trigger('click');
302					timer = null;
303				},3000);
304				curtainBanner.find('.btn_curtain_expand').on('click', function(){
305					if(timer) clearTimeout(timer);
306				});
307				setCookie("welBigBan", "done" , 1);
308			}
309		}
310		/* //수정 221006 커튼배너 1회 강제노출 (쿠키 사용) */
311
312		// 추가 260911 Picks AI 아이콘 Lottie
313		$('.header_wrapper .btn_picks_ai .icon.lottie').each(function(){
314			var trendPlus = bodymovin.loadAnimation({
315				container: this,
316				renderer: 'svg',
317				loop: true,
318				autoplay: true,
319				path: KyoboBookPub.ink.lottie.picksAI,
320			});
321		});
322	}
323
324	/**
325	 * 플라이 배너, 탑버튼 컨트롤
326	 */
327	function setFloating() {
328		if (_flyMenuEl.length <= 0 && _floatingEl.length <= 0) {
329			return;
330		}
331
332		var headerFixedOffset = 0;
333		if (!$('.wrapper').hasClass('member_login') && !$('.wrapper').hasClass('member_info') && !$('.wrapper').hasClass('member_kiosk') && !$('.wrapper').hasClass('member_kiosk_main')) {
334			headerFixedOffset = Math.round($('.gnb_wrap').offset().top);
335
336			if (_headerWrapper.hasClass('simple_header')) {
337				headerFixedOffset = 80;
338			}
339			// 수정 220919 웰컴 위치조정(장운주 대리)
340			if ($('.wrapper').hasClass('welcome')) {
341				headerFixedOffset += 642;
342			}
343			// 윙배너 sps set
344			_flyMenuEl.attr('data-sps-offset', headerFixedOffset);
345		}
346
347		setFloatingScrollPos();
348		$(window).off('scroll.uiFloating resize.uiFloating', setFloatingScrollPos).on('scroll.uiFloating resize.uiFloating', setFloatingScrollPos);
349
350		setFlyBannerEvtSwiper();
351
352		function setFloatingScrollPos() {
353			if (_scrollLeft < (_bodyMinWidth - _deviceWidth)) {
354				_floatingEl.css('transform', 'translateX(' + ((_bodyMinWidth - _deviceWidth) - _scrollLeft) + 'px)');
355
356				if (_scrollTop < headerFixedOffset) {
357					_flyMenuEl.css('transform', '');
358				} else {
359					_flyMenuEl.add(_floatingEl).css('transform', 'translateX(' + ((_bodyMinWidth - _deviceWidth) - _scrollLeft) + 'px)');
360				}
361			} else {
362				_flyMenuEl.add(_floatingEl).css('transform', '');
363			}
364
365			if (_headerWrapper.hasClass('sps')) {
366				if (_headerWrapper.hasClass('sps-blw')) {
367					_btnGoTop.addClass('active');
368				} else {
369					_btnGoTop.removeClass('active');
370				}
371			} else {
372				if (_headerWrapper.height() < _scrollTop) {
373					_btnGoTop.addClass('active');
374				} else {
375					_btnGoTop.removeClass('active');
376				}
377			}
378		}
379
380		function setFlyBannerEvtSwiper() {
381			var flyEvtBanner = $('.fly_menu_wrapper .fly_event_banner');
382			if ($('.swiper-slide', flyEvtBanner).length > 1) {
383				var flyBannerEvtSwiper = new CustomSwiper($('.swiper-container', flyEvtBanner), {
384					slidesPerView: '1',
385					speed: 500,
386					navigation: {
387						nextEl: $('.swiper_control_box .swiper-button-next', flyEvtBanner)[0],
388						prevEl: $('.swiper_control_box .swiper-button-prev', flyEvtBanner)[0],
389					},
390					pagination: {
391						el: $('.swiper_control_box .swiper-pagination', flyEvtBanner)[0],
392						type: 'fraction',
393						formatFractionCurrent: function (number) {
394							return KyoboBookPub.ink.setPrependZero(number, 2);
395						},
396						formatFractionTotal: function (number) {
397							return KyoboBookPub.ink.setPrependZero(number, 2);
398						},
399					},
400				});
401			} else {
402				$('.swiper_control_box', flyEvtBanner).remove();
403			}
404		}
405	}
406
407	/**
408	 * footer 패밀리 사이트 더보기
409	 */
410	function setFamilySiteMore() {
411		// 수정 250826 공통 푸터 개편
412		$('.family_site_box').each(function(){
413			var that = $(this);
414			$('.btn_family_site', this).on('click', function () {
415				if (!that.hasClass('active')) {
416					$('.family_site_box').not(that).removeClass('active animated');
417					that.addClass('active');
418
419					setTimeout(function () {
420						that.addClass('animated');
421					}, 30);
422				} else {
423					that.removeClass('active animated');
424				}
425
426			});
427		});
428		// 수정 251021 공통 푸터 개편
429		$(document).on('click', function (e) {
430			$('.family_site_box.active').each(function () {
431				if (!$(e.target).closest('.family_site_box').is(this)) {
432					$(this).removeClass('active animated');
433				}
434			});
435		});
436		/* $('.btn_family_site').on('click', function () {
437			if (!$('.family_site_box').hasClass('active')) {
438				$('.family_site_box').addClass('active');
439
440				setTimeout(function () {
441					$('.family_site_box').addClass('animated');
442				}, 30);
443			} else {
444				$('.family_site_box').removeClass('active animated');
445			}
446
447		}); */
448	}
449
450	/**
451	 * 브래드크럼 메뉴 on/off
452	 */
453	function setBreadCrumb() {
454		$('.breadcrumb_item', '.breadcrumb_wrap').not('.no_sub').each(function () {
455			$(this).on({
456				'mouseenter focusin': function (event) {
457					var tg = $(this);
458					tg.siblings('.breadcrumb_item').removeClass('active');
459					tg.addClass('active');
460
461					setTimeout(function () {
462						tg.addClass('animated');
463					}, 30);
464				},
465				'mouseleave focusout': function (event) {
466					var item,
467						that;
468					that = this;
469					item = $(that).closest('.breadcrumb_item');
470					setTimeout(function () {
471						if ($(item).find('a:focus').length < 1 && $(item).find('button:focus').length < 1) {
472							$(that).removeClass('active animated');
473						}
474					}, 50);
475				},
476			});
477		});
478	}
479
480	/**
481	 * 검색창 input 입력 시 초기화 버튼 노출
482	 * @param wrap 컨테이너 DOM 셀렉터(default : .form_ip_search)
483	 * @param input input 셀렉터(default : .form_ip)
484	 * 한화면에서 동일 구조가 n개인 경우, 별도 처리 필요하므로 클래스명 각각 다르게 처리필요
485	 */
486	function setSearchInput(wrap, input) {
487		wrap = wrap || '.form_ip_search';
488		input = input || '.form_ip';
489
490		var searchWrap,
491			searchIp,
492			clearBtn;
493
494		if ($(wrap).length > 0) {
495			$(wrap).each(function () {
496				searchWrap = $(this);
497				searchIp = $(this).find(input);
498				clearBtn = $(this).find('.btn_ip_clear');
499				// console.log(searchIp);
500
501				if (searchIp.length > 0) {
502					if (searchIp.val().length > 0) searchWrap.addClass('value');
503
504					clearBtn.off('click').on('click', function () {
505						searchWrap = $(this).closest(wrap);
506						searchWrap.find(input).val('').focus();
507						searchWrap.removeClass('value');
508
509					})
510
511					searchIp.data('placeholder', searchIp.attr('placeholder'));
512					searchIp.on({
513						'propertychange change input paste': function () {
514							searchWrap = $(this).closest(wrap);
515							if ($(this).val().length > 0) {
516								searchWrap.addClass('value');
517							} else {
518								searchWrap.removeClass('value');
519							}
520						},
521						'focusin': function () {
522							searchWrap = $(this).closest(wrap);
523
524							if (searchIp.hasClass('ip_gnb_search')) {
525								searchIp.attr('placeholder', '');
526							}
527
528							if (!searchWrap.hasClass('focus')) searchWrap.addClass('focus');
529						},
530						'focusout': function () {
531							searchWrap = $(this).closest(wrap);
532
533							if (searchIp.hasClass('ip_gnb_search')) {
534								searchIp.attr('placeholder', searchIp.data('placeholder'));
535							}
536
537							if (searchWrap.hasClass('focus')) searchWrap.removeClass('focus');
538						}
539					});
540				}
541			});
542
543		}
544
545	}
546
547	/**
548	 * 커스텀 디자인 스크롤
549	 * @param container 컨테이너 DOM 셀렉터(default : .custom_scroll_wrap)
550	 */
551	function setCustomScroll(container) {
552		if (window.SimpleBar !== undefined) {
553			var selector;
554			SimpleBar.defaultOptions.autoHide = false;
555			selector = container !== undefined ? container + ' .custom_scroll_wrap' : '.custom_scroll_wrap';
556
557			$(selector).each(function (index) {
558				if ($(this).closest('.dialog_contents').length === 0) {
559					setCustomScrollObj(this);
560				}
561
562				// var observer = new MutationObserver(function(mutations, observer) {
563				// 	mutations.forEach(function(mutation) {
564				// 		if(mutation.attributeName === 'style'){
565				// 			target = mutation.target;
566				// 			var scrollContWrap = $(target).closest('.custom_scroll_wrap');
567				// 			var scrollCont = $(target).find('.custom_scroll_inner');
568				// 			var currentHeight = scrollCont.height();
569				//
570				// 			if(scrollContWrap.height() < scrollCont.height()){
571				// 				scrollContWrap.addClass('active');
572				// 			} else{
573				// 				scrollContWrap.removeClass('active');
574				// 			}
575				// 		}
576				// 	});
577				// });
578				//
579				// var config = { attributes: true, childList: true, characterData: true };
580				//
581				// if ($(scrollInner[0]).closest('.simplebar-content-wrapper')[0].getAttribute('style').match('overflow: hidden scroll')) {
582				// 	$(this).addClass('active');
583				// }
584				// observer.observe($(scrollInner[0]).closest('.simplebar-content-wrapper')[0], config);
585
586				// console.log(scrollInner[0]);
587				// sensor = new ResizeSensor(scrollInner[0], function () {
588				// 	simpleBar.recalculate();
589				// });
590				// this.sensor = sensor;
591			});
592		}
593	}
594
595	function setCustomScrollObj(target) {
596		var simpleBar,
597			options,
598			child,
599			scrollInner;
600		child = $(target).children();
601		$(target).prepend('<div class="custom_scroll_inner" tabIndex="0"></div>');
602		scrollInner = $(target).find('.custom_scroll_inner');
603		scrollInner.append(child);
604
605		options = SimpleBar.getOptions(target);
606
607		if ($(target).data('force')) {
608			$(target).closest('.custom_scroll_wrap').addClass('active');
609			options.forceVisible = 'y';
610		}
611
612		simpleBar = new SimpleBar(target, options);
613		target.simpleBar = simpleBar;
614
615
616		var observer = new MutationObserver(function (mutations, observer) {
617			mutations.forEach(function (mutation) {
618				if (mutation.attributeName === 'style') {
619					target = mutation.target;
620					var scrollContWrap = $(target).closest('.custom_scroll_wrap');
621					var scrollCont = $(target).find('.custom_scroll_inner');
622					var currentHeight = scrollCont.height();
623
624					scrollCont.get(0).style.removeProperty('height');
625					if (scrollContWrap.height() < scrollCont.height()) {
626						scrollContWrap.addClass('active');
627					} else {
628						scrollCont.height(scrollContWrap.height());
629						scrollContWrap.removeClass('active');
630					}
631					updateChildComponent();
632				}
633			});
634		});
635
636		var config = {
637			attributes: true,
638			childList: true,
639			characterData: true
640		};
641
642		// console.log($(scrollInner[0]).closest('.simplebar-content-wrapper')[0].getAttribute('style'));
643		if ($(scrollInner[0]).closest('.simplebar-content-wrapper')[0].getAttribute('style').match('overflow: hidden scroll') !== null
644			|| $(scrollInner[0]).closest('.simplebar-content-wrapper')[0].getAttribute('style').match('-ms-overflow-y: scroll') !== null) {
645			$(target).addClass('active');
646			updateChildComponent();
647		} else {
648
649		}
650		observer.observe($(scrollInner[0]).closest('.simplebar-content-wrapper')[0], config);
651
652		$(target).off('mousewheel DOMMouseScroll').on('mousewheel DOMMouseScroll', function (event) {
653			openSelectClose();
654		});
655
656		if ($(target).hasClass('horizontal')) {
657			$(target).off('mousewheel DOMMouseScroll').on('mousewheel DOMMouseScroll', function (event) {
658				var originEvent,
659					delta,
660					scrollElement;
661				scrollElement = simpleBar.getScrollElement();
662
663				originEvent = event.originalEvent;
664				if (event.originalEvent.wheelDelta) {
665					delta = event.originalEvent.wheelDelta / 2;
666				} else {
667					delta = -originEvent.detail * 20;
668				}
669
670				if ((scrollElement.scrollLeft -= delta) <= 0
671					|| (scrollElement.getBoundingClientRect().width + scrollElement.scrollLeft - delta) >= scrollElement.scrollWidth) {
672					return;
673				}
674
675				event.preventDefault();
676				scrollElement.scrollLeft -= delta;
677
678			});
679		}
680
681		// 자식 컴포넌트 중 사이즈, 위치 등 업데이트가 필요 한 경우
682		function updateChildComponent() {
683			var uiSelect,
684				spsElement;
685			uiSelect = scrollInner.find('.form_sel select');
686			spsElement = scrollInner.find('.custom_sps');
687			// console.log(uiSelect);
688
689			uiSelect.each(function () {
690				var that;
691				that = this;
692				console.log('updateChildComponent uiSelect');
693				setTimeout(function () {
694					$(that).selectmenu('calcMenuWidth');
695				}, 100);
696			});
697
698			spsElement.each(function () {
699				var element = this;
700
701				var observer = new IntersectionObserver(function (entries, observer) {
702					entries.forEach(function (entry) {
703						var isIntersecting;
704						isIntersecting = entry.isIntersecting;
705						if (isIntersecting) {
706							$(element).removeClass('sps-below').addClass('sps-abv');
707						} else {
708							// console.log('not intersecting');
709							if ($(element).offset().top - scrollInner.closest('.custom_scroll_wrap').offset().top < 0) {
710								$(element).removeClass('sps-abv').addClass('sps-below');
711							} else {
712								$(element).removeClass('sps-below').addClass('sps-abv');
713							}
714						}
715					});
716				}, {
717					root: scrollInner.closest('.custom_scroll_wrap').get(0),
718					threshold: 1.0,
719				});
720				observer.observe(element);
721			});
722		}
723	}
724
725	/**
726	 * 테이블 캡션 생성
727	 */
728	function setTableCaption() {
729		$('table[class*="tbl_col"], table[class*="tbl_row"], table[class*="tbl_prod"], table[class*="tbl_spec_compare"]').each(function (index) {
730			var table,
731				tableClass,
732				captionText,
733				captionComplex,
734				theadHeader,
735				tbodyHeader,
736				bodyToHeadIdxs,
737				hasThead,
738				captionSubFix;
739			table = $(this);
740			tableClass = $(this).attr('class');
741			captionTextOrigin = $(this).find('caption').text();
742			captionComplex = '';
743			captionSubFix = '';
744			theadHeader = [];
745			tbodyHeader = [];
746			bodyToHeadIdxs = [];
747			hasThead = false;
748			// 180123 수정 : match 값 수정
749			if (tableClass.match('tbl-form') && tableClass.match('form-view') !== null) {
750				/* console.log('has _ip!!'); */
751				captionSubFix = '을(를) 입력하는 표입니다.';
752			} else {
753				/* console.log('no _ip!!'); */
754				captionSubFix = '을(를) 나타낸 표입니다.';
755			}
756
757
758			// thead th값 추출
759			if ($(this).find('thead th').length > 0) {
760				$(this).find('thead th').each(function (index) {
761					theadHeader.push($(this).text());
762				});
763			}
764			// tbody th값 추출
765			if ($(this).find('tbody th').length > 0) {
766				$(this).find('tbody th').each(function (index) {
767					// tbody th가 thead th의 서브 헤더인 경우(thead th와 tbody th가 둘 다 존재하는 경우)
768					if (theadHeader.length > 0) {
769						if (tbodyHeader[$(this).index()] === undefined) {
770							tbodyHeader[$(this).index()] = theadHeader[$(this).index()] + ' 컬럼의 하위로';
771						}
772						tbodyHeader[$(this).index()] += ' ' + $(this).text();
773					} else {
774						tbodyHeader.push($(this).text());
775					}
776				});
777
778				tbodyHeader = tbodyHeader.filter(function (n) {
779					return n !== undefined;
780				});
781			}
782			// console.log(theadHeader);
783			// console.log(tbodyHeader);
784
785			if (theadHeader.length > 0 && tbodyHeader.length > 0) {
786				captionComplex += theadHeader.join(', ') + ' ' + tbodyHeader.join(', ');
787			} else if (theadHeader.length > 0) {
788				captionComplex += theadHeader.join(', ');
789			} else if (tbodyHeader.length > 0) {
790				captionComplex += tbodyHeader.join(', ');
791			}
792
793			//console.log(captionTextOrigin + ' 목록이며 ' + captionComplex +  ' 을(를) 나타낸 표입니다.');
794			$(this).find('caption').text(captionTextOrigin + ' 테이블로 ' + captionComplex + captionSubFix);
795		});
796	}
797
798	/**
799	 * 별점 컴포넌트 생성
800	 */
801	function setStarRating() {
802		if ($('.form_rating').length <= 0) return false;
803
804		$('.form_rating').each(function () {
805			var that = $(this);
806
807			that.rating({
808				language: 'ko',
809				theme: 'krajee-gly',
810				clearCaption: '10점 중 0점<span class="val" aria-hidden="true">0</span><span class="total" aria-hidden="true">10</span></span>',
811				stars: 4,
812				min: 0,
813				max: 10,
814				step: 2.5,
815				starCaptions: function (rating) {
816					var strCaption;
817					strCaption = '10점 중 ' + rating + '점';
818					if (that.data('caption') !== undefined) {
819						strCaption += '<span class="val" aria-hidden="true">' + rating + '</span>' + '<span class="total" aria-hidden="true">' + 10 + '</span>';
820					} else {
821						// return rating + ' / 10';
822					}
823					return strCaption;
824				}
825			});
826			// that.on('rating:change', function(event, value, caption) {
827			// 	console.log(`${value}/10`);
828			// });
829
830			if (that.data('caption') !== undefined) {
831				that.prev('.rating-container').addClass('has_caption');
832			}
833		});
834	}
835
836	/**
837	 * 스크롤 동작시 해당 요소에 도달 시 엘리먼트 상단 고정(sps init)
838	 */
839	function setSpsOffsetData(target) {
840		/* 추가 221011 sps 실행 시점 변경 */
841		if(setSpsOffsetData.count){
842			setSpsOffsetData.count++;
843		}else{
844			setSpsOffsetData.count = 1;
845			if (window.ScrollPosStyler) {
846				ScrollPosStyler.init({
847					classAbove: 'sps-abv',
848					classBelow: 'sps-blw',
849				});
850			}
851		}
852		// console.log('sps count:', setSpsOffsetData.count);
853		/* //추가 221011 sps 실행 시점 변경 */
854
855		var ignoreClassList = [];
856		var spsElem;
857		var headerH = $('.header_wrapper').hasClass('sps') || $('.header_wrapper').hasClass('fix_header') ? 80 : 0;
858
859		target = target || '.sps';
860
861		ignoreClassList = [
862			// 'header_wrapper',
863		];
864
865		spsElem = $(target, _container);
866
867		// container_wrapper > sps 엘리먼트 타겟팅
868		$(target, _container).each(function (index) {
869
870			var that,
871				isIgnore;
872			that = this;
873			isIgnore = ignoreClassList.some(function (element) {
874				return $(that).hasClass(element);
875			});
876			if (!isIgnore) {
877				spsElem.push(that);
878			}
879		});
880
881		if (spsElem.length === 0) return false;
882
883		spsElem.each(function (i) {
884			var target = $(this);
885			fixData(target);
886			// heightChangeTarget.push(target.data('height-change'));
887
888			if (i === spsElem.length - 1) {
889				ScrollPosStyler.init(); // 수정 221011
890
891				/* 삭제 221011 sps 실행 시점 변경
892				if (window.ScrollPosStyler) {
893					ScrollPosStyler.init({
894						classAbove: 'sps-abv',
895						classBelow: 'sps-blw',
896					});
897				} */
898			}
899		});
900
901		// heightChangeTarget.forEach(function (target, idx) {
902		// 	var sensor = null;
903		// 	sensor = new ResizeSensor( $('.' + target), function() {
904		// 		fixData( $('.sps[data-height-change='+heightChangeTarget[idx]+']') );
905		// 	});
906		// });
907
908
909		var sensor = null;
910		sensor = new ResizeSensor(_container, function () {
911			$('.sps[data-height-observe]').each(function (index) {
912				var that = this;
913				setTimeout(function () {
914					fixData($(that));
915				}, 100);
916			})
917		});
918
919		// tab active 시, sps fixData 재계산
920		$('.tab_wrap').on('tabsactivate', function (event, ui) {
921			$(ui.newPanel).find('.sps').each(function () {
922				fixData($(this));
923			})
924		});
925
926		function fixData(tg) {
927			var observerCont,
928				addOfs,
929				tgHeight,
930				spsOffset; // 수정 240219 GNB 고객경험 통합 개선
931			if (tg.find('.sps_observer').length === 0) {
932				tg.append('<div class="sps_observer" style="top:' + tg.css('top') + ';"></div>');
933			}
934
935			// console.log('fixData', tg);
936
937			observerCont = tg.find('.sps_observer');
938			addOfs = (tg.data('add-offset') !== undefined && !isNaN(tg.data('add-offset'))) ? tg.data('add-offset') : 0;
939			tgHeight = tg.outerHeight();
940			// console.log(addOfs);
941
942			if (tg.hasClass('sps_ofs_bottom')) {
943				tg.attr('data-sps-offset', Math.round(observerCont.offset().top - headerH + tgHeight - addOfs));
944				tg.data('sps-offset', Math.round(observerCont.offset().top - headerH + tgHeight - addOfs));
945			} else {
946				// 수정 240219 GNB 고객경험 통합 개선
947				spsOffset = Math.round(observerCont.offset().top - headerH - tgHeight - addOfs)
948				spsOffset = spsOffset < headerH ? headerH : spsOffset;
949				tg.attr('data-sps-offset', spsOffset);
950				tg.data('sps-offset', spsOffset);
951			}
952			// console.log(tg.attr('data-sps-offset'));
953			// console.log(observerCont.offset().top, headerH, tgHeight, addOfs);
954		}
955	}
956
957	/**
958	 * fixed 컨텐츠 가로스크롤 시 left값 변경
959	 */
960	function setFixedElementPosX() {
961		var fixedDOMList,
962			forceAddClassList,
963			ignoreClassList;
964		fixedDOMList = [];
965
966		// sps를 가지지 않은 엘리먼트 중 추가할 class
967		forceAddClassList = [
968			'prod_detail_footer',
969			'fix_header',
970			'cart_top_wrap.sps-blw',
971			'cart_calc_wrap.sps-blw .cart_calc_inner', // 추가 240604 장바구니 상품 계산 영역
972			'cart_info_wrap',
973			'floating_event_wrapper', // 통합검색 플로팅 배너(SCR-BIZ03-04-P001)
974			'wrapper .spec_compare_layer_wrap',
975			'wrapper.member_kiosk .count_box', // 무인가입기 서브페이지 타이머 공통
976			'event_sticky_banner', // 이벤트 플로팅 배너(SCR-BIZ04-01-P002)
977			'burst_banner_wrap', // 베스트 마케팅 팝업(SCR-BIZ15-03-P002)
978			'list_result_sps .sps_inner', // 전시 사은품(SCR-BIZ15-06-P001)
979			'store_direction_wrap .scroll_fixed_target.scroll_fixed', // 매장안내(SCR-BIZ16-01-P001)
980		];
981
982		// 제외할 class
983		ignoreClassList = [
984			'fly_menu_wrapper',
985			'floating_wrapper',
986			'tab_content',
987		];
988
989		forceAddClassList.forEach(function (element) {
990			// console.log(element);
991			$('.' + element).each(function (index) {
992				this.isForceTransformX = true;
993				fixedDOMList.push(this);
994			});
995		});
996
997		// sps.sps_scroll_fixed 가진 엘리먼트 중 ignoreClassList에 없는 경우 타겟팅
998		$('.sps.sps_scroll_fixed').each(function (index) {
999			var that,
1000				isIgnore;
1001			that = this;
1002			isIgnore = ignoreClassList.some(function (element) {
1003				return $(that).hasClass(element);
1004			});
1005			if (!isIgnore) {
1006				fixedDOMList.push(that);
1007			}
1008		});
1009
1010		// 해상도 영역이 최소 넓이 값보다 작은 경우
1011		if (_bodyMinWidth > _deviceWidth && _deviceWidth > 0) {
1012			// 해상도 영역 작은 경우 : left 스크롤 변경시 작동
1013			if (saveScrollLeft !== _scrollLeft) {
1014				fixedDOMList.forEach(function (element) {
1015					if (!$(element).hasClass('sps_scroll_fixed')) {
1016						$(element).css({
1017							'transform': 'translateX(' + -_scrollLeft + 'px)'
1018						});
1019					} else {
1020						if ($(element).attr('data-sps-offset') <= _scrollTop) {
1021							$(element).css({
1022								'transform': 'translateX(' + -_scrollLeft + 'px)'
1023							});
1024						}
1025					}
1026
1027				});
1028				// 고정 컨텐츠 left change
1029				saveScrollLeft = _scrollLeft;
1030			}
1031
1032			// 해상도 영역 작은 경우 : top 스크롤 변경시 작동
1033			if (saveScrollTop !== _scrollTop) {
1034				fixedDOMList.forEach(function (element) {
1035					if ($(element).attr('data-sps-offset') <= _scrollTop && element.is
1035ForceTransformX) {
1036						$(element).css({
1037							'transform': 'translateX(' + -_scrollLeft + 'px)'
1038						});
1039						element.isForceTransformX = false;
1040					} else if ($(element).attr('data-sps-offset') > _scrollTop && !element.isForceTransformX) {
1041						element.isForceTransformX = true;
1042					} else if ($(element).attr('data-sps-offset') > _scrollTop && element.isForceTransformX) {
1043						$(element).css('transform', '');
1044					}
1045				});
1046
1047				saveScrollTop = _scrollTop;
1048			}
1049
1050
1051		}
1052	}
1053
1054	/**
1055	 * sps init
1056	 */
1057	/* 삭제 221004 sps 실행 시점 변경
1058	if (window.ScrollPosStyler) {
1059		ScrollPosStyler.init({
1060			classAbove: 'sps-abv',
1061			classBelow: 'sps-blw',
1062		});
1063	}
1064	*/
1065
1066	/**
1067	 * 레이어 팝업 설정 (jquery UI Dialog)
1068	 * @param selector {string} 레이어 팝업으로 생성할 컨테이너 셀렉터(default: '.dialog_wrap')
1069	 * @param btnOpen {string} 레이어 팝업을 띄우기 위한 버튼 셀렉터(default: [data-role=btn-dialog])
1070	 * @param btnClose {string} 레이어 팝업을 띄우기 위한 버튼 셀렉터(default: [data-dialog-close])
1071	 */
1072	var dialogHeight = {};
1073
1074	function setUIDialog(selector, btnOpen, btnClose) {
1075		selector = selector || '.dialog_wrap';
1076		btnOpen = btnOpen || '[data-role=btn-dialog]';
1077		btnClose = btnClose || '[data-dialog-close]';
1078
1079		if ($(selector).length > 0) {
1080			var dialogClass,
1081				containerId,
1082				dialogId,
1083				containerClasses;
1084
1085			$(selector).each(function () {
1086				if ($(this).parents('.ui-dialog').length > 0) return false;
1087				var dialogWrap = this;
1088
1089				containerId = 'body';
1090				containerClasses = 'dialog_wrapper';
1091				dialogClass = '';
1092
1093				// dialog multi class 추가
1094				if ($(dialogWrap).data('class') !== undefined) {
1095					if (isNaN(parseInt($(this).data('class')))) {
1096						dialogClass = $(this).data('class');
1097					} else {
1098						dialogClass = 'auto';
1099					}
1100				}
1101				$(dialogWrap).data('dialogClass', dialogClass);
1102
1103				// resize시, popup 가운데 정렬 css제어를 위해 container append
1104				dialogId = containerId.replace('#', '') + 'Dialog' + _dialogCount;
1105				$(containerId).append('<div id="' + dialogId + '" class="' + containerClasses + '"></div>');
1106
1107				_dialogCount++;
1108
1109				// 팝업 기본 설정
1110				$(dialogWrap).dialog({
1111					appendTo: containerId + ' #' + dialogId, // resize시, popup 가운데 정렬 css제어를 위해 container append
1112					autoOpen: $(dialogWrap).is('[data-opened]'), // false,
1113					width: 'none',
1114					minHeight: 'none',
1115					closeText: "닫기",
1116					modal: true,
1117					resize: false,
1118					resizable: false,
1119					draggable: false,
1120					position: null,
1121					classes: {
1122						'ui-dialog': dialogClass, // popup case multi class 추가
1123					},
1124					open: function (event, ui) {
1125						var that = $(this);
1126						var papa = that.closest('.ui-dialog');
1127						var container = that.closest('.' + containerClasses);
1128
1129						if (that.data('nodim') !== undefined) {
1130							var dialogNoDim = true;
1131						}
1132
1133						// 팝업 닫기 시, 기존 스크롤 위치로 이동위해 현재 스크롤값 저장(상단 이동 막기)
1134						if (!dialogNoDim) {
1135							var scrollTop = $(document).scrollTop();
1136
1137							if (!$('html').hasClass('dialog_open')) {
1138								container.css({'top': scrollTop,});
1139								$('body').addClass('dialog_open');
1140							}
1141						} else {
1142							container.addClass('no_dim');
1143						}
1144
1145						// 팝업 2개 이상 노출 시 z-index 지정(팝업 위 팝업 미구현시 삭제)
1146						var zNum = 999;
1147						if ($('.dialog_wrapper:visible').length > 0) {
1148							$('.dialog_wrapper:visible').each(function () {
1149								var dialog;
1150								dialog = $(this);
1151								zNum = Math.max(zNum, parseInt(dialog.css('z-index')));
1152							});
1153						}
1154						if (that.data('z-index') !== undefined) {
1155							container.addClass('open').css('z-index', that.data('z-index'));
1156						} else {
1157							container.addClass('open').css('z-index', zNum + 2);
1158						}
1159						// console.log(container);
1160
1161						// popup 최소 높이보다 작은경우 100vh 처리
1162						if (!dialogNoDim) {
1163							setTimeout(function () {
1164								dialogHeight[container.attr('id')] = papa.outerHeight();
1165								dialogAutoHeight();
1166							}, 50)
1167						}
1168
1169						// 팝업 내 swiper 업데이트
1170						if ($(this).parent().find('.swiper-container:visible').length > 0) { // 수정 221009 화면에 보일때만 실행
1171							$(this).parent().find('.swiper-container:visible').each(function (index) { // 수정 221009 화면에 보일때만 실행
1172								updateDialogSwiper(this);
1173							});
1174						}
1175
1176						if ($(this).parent().find('.custom_scroll_wrap').length > 0) {
1177							$(this).parent().find('.custom_scroll_wrap').each(function (index) {
1178								// console.log('!!', this.simpleBar);
1179								if (this.simpleBar !== undefined) {
1180									this.simpleBar.recalculate();
1181								} else {
1182									setCustomScrollObj(this);
1183								}
1184							});
1185						}
1186
1187						// select 열려있으면 닫기
1188						openSelectClose();
1189
1190						KyoboBookPub.ink.autoOverflowContents('.dialog_wrapper');
1191
1192						// 상품 리뷰 팝업 이미지 비율 체크 재실행
1193						if ($(this).hasClass('dialog_review')) {
1194							// 리뷰 이미지 비율 체크
1195							$('.comment_wrap .comment_swiper_wrap .portrait_img_box').each(function () {
1196								var imgTg = $(this);
1197								KyoboBookPub.ink.checkImagePortrait(imgTg);
1198							});
1199						}
1200
1201						// 수정 240625 Dim 레이어 클릭 시 닫기
1202						if (!$(this).find('.dialog_footer').length) {
1203							$('.ui-widget-overlay', container).click(function () {
1204								// $(dialogWrap).dialog('close');
1205								dialogOnOff().popClose('#' + $(dialogWrap).attr('id')); // 수정 240708 최근 본 콘텐츠 닫기 애니메이션
1206							});
1207						}
1208					},
1209					close: function (event, ui) {
1210						var that = $(this);
1211						var container = that.closest('.dialog_wrapper')
1212						var scrollTopPos = container.css('top');
1213						var dialogNoDim;
1214
1215						if ($('.dialog_wrapper.no_dim.open').length !== 0) {
1216							dialogNoDim = true;
1217						}
1218
1219						// z-index style 삭제
1220						container.removeClass('open').removeAttr('style');
1221						container.find('.ui-dialog').removeClass('h_auto');
1222
1223						// 팝업 닫기 시, 기존 스크롤 위치로 이동(상단 이동 막기)
1224						if ($('.ui-dialog-content:visible').length === 0 || $('[data-nodim]:visible').length > 0) {
1225							container.removeAttr('style');
1226							$(containerId).removeClass('dialog_open');
1227
1228							if (!dialogNoDim) $(window).scrollTop(parseInt(scrollTopPos));
1229						}
1230
1231						container.removeClass('no_dim');
1232
1233						if (!dialogNoDim) delete dialogHeight[container.attr('id')];
1234					},
1235					create: function (event, ui) {
1236						$(this).get(0).style.display = '';
1237						$(this).addClass('initialized');
1238					}
1239				});
1240
1241				// dim 없는경우 modal false 처리
1242				if ($(dialogWrap).data('nodim') !== undefined) {
1243					var noDimPopupPos;
1244					noDimPopupPos = {};
1245					$(dialogWrap).dialog({modal: false});
1246
1247					if ($(dialogWrap).data('top')) {
1248						noDimPopupPos.top = parseInt($(this).data('top'));
1249					}
1250					if ($(dialogWrap).data('left')) {
1251						noDimPopupPos.left = parseInt($(this).data('left'));
1252					}
1253					if ($(dialogWrap).data('content-margin') !== undefined) {
1254						console.log($(this).data('content-margin'));
1255						$(dialogWrap).closest('.dialog_wrapper').addClass('content_margin');
1256					}
1257					$(dialogWrap).closest('.ui-dialog').css(noDimPopupPos);
1258				}
1259
1260				if ($(btnOpen).length > 0) {
1261
1262					$(btnOpen).each(function (index) {
1263						if (($(this).data('target') === '#' + $(dialogWrap).attr('id')) && !$(this).data('initialized')) {
1264							$(this).data('initialized', true);
1265							$(this).on('click', function (event) {
1266								var openTgId = $(this).data('target');
1267
1268								event.preventDefault();
1269								dialogOnOff().popOpen(openTgId);
1270							});
1271						}
1272					});
1273				}
1274
1275				if ($(btnClose, selector).length > 0) {
1276					$(btnClose, selector).each(function (index) {
1277						$(this).off('click').on('click', function (event) {
1278							var openTgId,
1279								closeTgId;
1280							closeTgId = $(this).closest(selector).attr('id');
1281							if (closeTgId === undefined) {
1282								closeTgId = $(this).closest('.dialog_wrap').attr('id');
1283							}
1284
1285							event.preventDefault();
1286							dialogOnOff().popClose('#' + closeTgId);
1287
1288							if ($(this).data('role') === 'btn-dialog') {
1289								openTgId = $(this).data('target');
1290								dialogOnOff().popOpen(openTgId);
1291							}
1292						});
1293					});
1294				}
1295			});
1296		}
1297	}
1298
1299	/**
1300	 * 레이어 팝업 최소 높이 지정
1301	 */
1302	function dialogAutoHeight() {
1303		if ($('.dialog_wrapper.open').length > 0) {
1304			$('.dialog_wrapper.open').each(function () {
1305				var containerId = $(this).attr('id');
1306				if ($(window).height() < dialogHeight[containerId]) {
1307					$(this).find('.ui-dialog').addClass('h_auto');
1308
1309					if ($(this).find('.custom_scroll_wrap').length > 0) {
1310						$(this).find('.custom_scroll_wrap').each(function (index) {
1311							this.simpleBar.recalculate();
1312						});
1313					}
1314
1315				} else {
1316					$(this).find('.ui-dialog').removeClass('h_auto');
1317				}
1318			})
1319		}
1320	}
1321
1322	/**
1323	 * 레이어 팝업 On/Off(외부 호출용)
1324	 */
1325	function dialogOnOff() {
1326		var control = {
1327			/**
1328			 * 레이어팝업 open
1329			 * @param tgId {string} 팝업 타겟 id
1330			 * @param callback {string} 팝업 open 후 callback 함수
1331			 */
1332			popOpen: function (tgId, callback) {
1333				$(tgId).dialog('open');
1334				if (callback != null && typeof callback === "function") {
1335					callback.apply(null, [tgId]);
1336				}
1337
1338				// console.log($('.form_sel select', $(tgId)).selectmenu);
1339				$('.form_sel select', $(tgId)).selectmenu('calcMenuWidth');
1340			},
1341
1342			/**
1343			 * 레이어팝업 close
1344			 * @param tgId {string} 팝업 타겟 id
1345			 */
1346			popClose: function (tgId) {
1347				// 수정 240708 최근 본 콘텐츠 닫기 애니메이션
1348				if ($(tgId).data('class') === 'dialog_history') {
1349					$(tgId).closest('.ui-dialog').addClass('vanish');
1350					setTimeout(function(){
1351						$(tgId).dialog('close');
1352						$(tgId).closest('.ui-dialog').removeClass('vanish');
1353					}, 230);
1354				} else {
1355					$(tgId).dialog('close');
1356				}
1357			},
1358		}
1359
1360		return control;
1361	}
1362
1363
1364	/**
1365	 * 팝업이 오픈된 뒤 실제 브라우저 렌더링이 된 후 swiper 업데이트를 위한 재귀함수
1366	 */
1367	function updateDialogSwiper(dialog) {
1368		console.log('updateDialogSwiper');
1369		if (dialog.clientWidth > 0) {
1370			if (dialog.swiper !== undefined) {
1371				if ($(dialog.swiper.$el[0]).find('.custom_scroll_wrap').length > 0) {
1372					$(dialog.swiper.$el[0]).find('.custom_scroll_wrap').each(function (index) {
1373						this.simpleBar.recalculate();
1374						// console.log(this.simpleBar);
1375					});
1376				}
1377
1378				// 썸네일 swiper update
1379				if (dialog.swiper.params.thumbs.swiper !== null) {
1380					dialog.swiper.params.thumbs.swiper.update();
1381				}
1382				dialog.swiper.update();
1383
1384				// setTimeout(function () {
1385				// 	updateDialogSwiper(dialog);
1386				// }, 10);
1387			}
1388		} else {
1389			setTimeout(function () {
1390				// console.log('2');
1391				updateDialogSwiper(dialog);
1392			}, 10);
1393		}
1394	}
1395
1396
1397	/**
1398	 * togglePassword : 비밀번호 숨김/보임 toggle
1399	 * @param selector {string} 실행 대상 element
1400	 * @param btnSelector {string} 실행 button
1401	 */
1402	function togglePassword(wrap, btnSelector) {
1403		wrap = wrap || '.form_ip_pw';
1404		btnSelector = btnSelector || '.btn_toggle_pw';
1405
1406		var that,
1407			toggleInput,
1408			btnBeforeText,
1409			btnAfterText;
1410		$(btnSelector).each(function (index) {
1411			that = $(this);
1412
1413			if (that.closest(wrap).find('input').prop('disabled')) {
1414				that.attr("disabled", true);
1415			}
1416
1417			that.off('click').on('click', function () {
1418				toggleInput = $(this).closest(wrap).find('input');
1419				btnBeforeText = $(this).text();
1420
1421				if ($(this).hasClass('active') && toggleInput.attr('type') === 'text') {
1422					$(this).removeClass('active');
1423					toggleInput.attr('type', 'password');
1424
1425					btnAfterText = btnBeforeText.replace('보임', '숨김');
1426					$(this).find('.hidden').text(btnAfterText);
1427				} else {
1428					$(this).addClass('active');
1429					toggleInput.attr('type', 'text');
1430
1431					btnAfterText = btnBeforeText.replace('숨김', '보임');
1432					$(this).find('.hidden').text(btnAfterText);
1433				}
1434			});
1435		});
1436	}
1437
1438	/**
1439	 * select init
1440	 * @param selector {string} 실행 element
1441	 */
1442	function setUISelect(selector) {
1443		selector = selector || '.form_sel';
1444		if ($(selector).length > 0) {
1445			$(selector).each(function () {
1446				var selectMenuOption,
1447					selectClass,
1448					selectPosition,
1449					isArwType,
1450					isCalendarType;
1451				isArwType = ($(this).data('class') !== undefined && $(this).data('class').search('type_arw') !== -1);
1452				isCalendarType = ($(this).data('class') !== undefined && $(this).data('class').search('type_calendar') !== -1);
1453				selectMenuOption = {};
1454				selectClass = '';
1455				selectPosition = {
1456					my: 'left top',
1457					at: 'left bottom'
1458				};
1459
1460				if (isArwType) {
1461					selectPosition = {
1462						my: 'right top+6',
1463						at: 'right bottom'
1464					};
1465				} else if (isCalendarType) {
1466					selectPosition = {
1467						my: 'right top+6',
1468						at: 'right bottom'
1469					};
1470				}
1471				selectMenuOption.position = selectPosition;
1472
1473				if ($(this).data('append-to') !== undefined) {
1474					selectMenuOption.appendTo = $(this).data('append-to');
1475				}
1476
1477				// custom select 일 경우
1478				if ($(this).data('renderer')) {
1479					setCustomSelect($(this), selectMenuOption);
1480					return;
1481				}
1482
1483				selectMenuOption.create = function (event) {
1484					var that,
1485						instance,
1486						btnWidth,
1487						menuWidth;
1488					that = this;
1489
1490					instance = $(that).selectmenu('instance');
1491					selectClass = $(that).closest(selector).data('class');
1492
1493					if (selectClass) {
1494						$(that).closest(selector).addClass(selectClass);
1495						instance.menuWrap.addClass(selectClass);
1496					}
1497
1498
1499					$(that).selectmenu('open');
1500
1501					btnWidth = instance.button.outerWidth();
1502					menuWidth = instance.menuWrap.outerWidth();
1503
1504					if (btnWidth !== menuWidth) {
1505
1506						if (selectClass !== undefined) {
1507							if (selectClass.search('type_arw') !== -1) { // arw 타입은 버튼 크기 크기와 옵션 크기 다름
1508								$(that).selectmenu('close');
1509								return false;
1510							} else if (selectClass.search('type_calendar') !== -1) {
1511								$(that).selectmenu('close');
1512								return false;
1513							}
1514						}
1515
1516						$(that).selectmenu('calcMenuWidth');
1517					}
1518
1519					sensor = new ResizeSensor(instance.button, function () {
1520						if (selectClass !== undefined) {
1521							if (selectClass.search('type_arw') === -1) {
1522								$(that).selectmenu('calcMenuWidth');
1523							} else if (selectClass.search('type_calendar') !== -1) {
1524								$(that).selectmenu('calcMenuWidth');
1525							}
1526						}
1527					});
1528					$(that).selectmenu('close');
1529				};
1530
1531				$(this).find('select').selectmenu(selectMenuOption);
1532				setTimeout(() => $(this).find('[area-owns]').removeAttr('area-owns')); // 수정 240424 크롬 셀렉트박스 오류 대응
1533			});
1534		}
1535
1536		// custom select
1537		function setCustomSelect(target, defaultOption) {
1538			var rendererName,
1539				widget,
1540				widgetClass;
1541			rendererName = target.data('renderer');
1542			widgetClass = target.data('widgetClass');
1543
1544			defaultOption.open = function (event, ui) {
1545				widget.css('width', target.width());
1546
1547				if (rendererName === 'selectProdOption') {
1548					target.css('padding-bottom', widget.outerHeight());
1549				}
1550			};
1551
1552			defaultOption.close = function (event, ui) {
1553				if (rendererName === 'selectProdOption') {
1554					target.css('padding-bottom', 0);
1555				}
1556			}
1557
1558			widget = target.find('select')[rendererName](defaultOption)[rendererName]('menuWidget').addClass(widgetClass);
1559		}
1560	}
1561
1562	/**
1563	 * openSelectClose : 열려있는 select 닫기 처리
1564	 */
1565	function openSelectClose() {
1566		$('.form_sel .ui-selectmenu-button-open').each(function (index) {
1567			if ($(this).closest('.form_sel').attr('data-renderer') === 'selectProdOption') {
1568				$(this).closest('.form_sel').find('select').selectProdOption('close');
1569			} else {
1570				$(this).closest('.form_sel').find('select').selectmenu('close');
1571			}
1572		});
1573	}
1574
1575	/**
1576	 * setUISpinner : spinner set
1577	 * @param selector {string} 실행 element
1578	 */
1579	function setUISpinner(selector) {
1580		selector = selector || '.form_spinner';
1581
1582		if ($(selector).length > 0) {
1583			$(selector).each(function (index) {
1584				var isDisabled = $(this).attr('disabled');
1585
1586				$(this).spinner({
1587					decreseText: '상품 수량 한 개 줄이기',
1588					increseText: '상품 수량 한 개 늘리기',
1589					min: $(this).data('min') === undefined ? 1 : $(this).data('min'),
1590					max: $(this).data('max'),
1591					disabled: isDisabled,
1592				});
1593			});
1594
1595			// 한글 입력 막기
1596			$(selector).off('input').on('input', function (event) {
1597				var val,
1598					regExVal;
1599				val = $(this).spinner('value');
1600				if (val === null) {
1601					val = 0;
1602				}
1603				regExVal = val.toString().replace(/[^\d+$]/g, '');
1604				$(this).spinner('value', regExVal);
1605			});
1606		}
1607	}
1608
1609	/**
1610	 * jQuery UI 탭 설정
1611	 * @param selector Tab 생성 DOM 셀렉터(default : .tab_wrap)
1612	 */
1613	function setTabs(selector) {
1614		selector = selector || '.tab_wrap';
1615
1616		if ($(selector).length > 0) {
1617			$(selector).each(function (index) {
1618				var disabledTabs;
1619				disabledTabs = [];
1620
1621				if ($(this).data('type-btn') !== undefined) {
1622					return;
1623				}
1624
1625				$(this).find('> .tab_list_wrap .tabs .tab_link').each(function (index) {
1626					if ($(this).hasClass('tab_disabled')) {
1627						disabledTabs.push(index);
1628					}
1629				});
1630
1631				$(this).tabs({
1632					disabled: disabledTabs,
1633					beforeActivate: function (event, ui) {
1634						if ($(ui.newTab).find('a').attr('href').indexOf('#') !== 0) {
1635							var tg = $(ui.newTab).find('a').attr('target') === undefined ? '_self' : $(ui.newTab).find('a').attr('target');
1636							event.preventDefault();
1637
1638							// a 태그에 onclick 선언되어 있는 경우 onclick만 실행
1639							if ($(ui.newTab).find('a').attr('onclick') !== undefined) {
1640								// console.log('onClick first');
1641								return false;
1642							}
1643
1644							window.open($(ui.newTab).find('a').attr('href'), tg);
1645							event.preventDefault();
1646						}
1647					},
1648					activate: function (event, ui) {
1649						if ($(event.target).closest('.custom_scroll_wrap').length > 0) {
1650							$(event.target).closest('.custom_scroll_wrap').get(0).simpleBar.recalculate();
1651						}
1652						if (ui.newPanel.find('.swiper-container').length > 0) {
1653							ui.newPanel.find('.swiper-container').each(function (index) {
1654								if (this.swiper === undefined || this.swiper === null) return;
1655								this.swiper.update();
1656							});
1657						}
1658						if (ui.newPanel.find('.form_sel').length > 0) {
1659							$('.form_sel:not(.type_arw) select', $(ui.newPanel)).selectmenu('calcMenuWidth');
1660						}
1661					},
1662					// create: function( event, ui ) {
1663					// 	$(this).addClass()
1664					// }
1665				});
1666
1667			});
1668		}
1669	}
1670
1671	/**
1672	 * tag tab swiper type인 경우
1673	 * update : 20220512 activeSwiper 함수 추가 (선택된 카테고리 있을때 active 기능 추가)
1674	 */
1675	function tabListFolding(selector) {
1676		var tagWrap = selector || $('.tab_wrap.type_tag.type_fold .tab_list_wrap');
1677		if (tagWrap.length === 0) return;
1678		tagWrap.each(function () {
1679
1680			tagWrapTg = $(this);
1681			var tagSwiperEl = $('.tab_swiper_wrap', tagWrapTg);
1682
1683			// 연관검색어 더보기 버튼 노출 체크
1684			function contOverflowCheck(el) {
1685				return el !== undefined && (el.offsetWidth < el.scrollWidth);
1686			}
1687
1688			if (!contOverflowCheck(tagSwiperEl.get(0)) || tagSwiperEl.get(0).swiper !== undefined) return;
1689
1690			tagWrapTg.addClass('active');
1691
1692			var tagSwiper;
1693
1694			function tagSwiperInit() {
1695				if (tagSwiperEl.length > 0 && tagSwiperEl.get(0).swiper === undefined) {
1696					tagSwiper = new CustomSwiper(tagSwiperEl, {
1697						slidesPerView: 'auto',
1698						observer: true,
1699						observeParents: true,
1700						speed: 500,
1701						threshold: 10, // 10px 이상 드래그해야 swiper 처리
1702					});
1703
1704					activeSwiper();//20220512 activeSwiper 추가
1705				}
1706			}
1707
1708			tagSwiperInit();
1709
1710			/* 20220512 activeSwiper 추가, 선택된 탭 있을때 활성화 추가  */
1711			function activeSwiper() {
1712				var activeIndex = $(tagWrap).find('.ui-state-active').index();
1713				tagSwiper.slideTo(activeIndex);
1714			}
1715
1716			$('.btn_tag_more', tagWrap).off().on('click.uiTagMore', function () {
1717				var papa = $(this).parent();
1718				if (papa.hasClass('more')) {
1719					$(this).find('.hidden').text('더보기');
1720					papa.removeClass('more');
1721
1722					console.log('tagSwiperInit');
1723					tagSwiperInit();
1724				} else {
1725					$(this).find('.hidden').text('접기');
1726					papa.addClass('more');
1727
1728					tagSwiper.destroy();
1729					console.log('tagSwiper', tagSwiper);
1730					tagSwiper = tagSwiperEl.get(0).swiper = undefined;
1731				}
1732			});
1733		});
1734	}
1735
1736	/**
1737	 * jQuery UI Datepicker 생성
1738	 * @날짜표기 마지막 . 삭제 by han 220426
1739	 */
1740	function setDatepicker() {
1741		$.datepicker.setDefaults({
1742			dateFormat: 'yy. mm. dd',
1743			monthNames: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
1744			monthNamesShort: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
1745			dayNamesMin: ['일', '월', '화', '수', '목', '금', '토'],
1746			showMonthAfterYear: true,
1747			showOn: 'button',
1748			buttonImage: 'https://contents.kyobobook.co.kr/resources/fo/images/common/ink/[email protected]',
1749			buttonImageOnly: true,
1750			buttonText: '날짜 선택',
1751			currentText: '오늘',
1752			// showOtherMonths: true,
1753			// selectOtherMonths: false,
1754			// yearSuffix: '년',
1755			changeMonth: true,
1756			changeYear: true,
1757		});
1758
1759		if ($('.date_box').length > 0) {
1760
1761			$('.date_box input').each(function (index) {
1762				var minDate,
1763					maxDate,
1764					isDisabled;
1765				minDate = $(this).data('minDate') !== undefined ? $(this).data('minDate') : null;
1766				maxDate = $(this).data('maxDate') !== undefined ? $(this).data('maxDate') : null;
1767				isDisabled = $(this).attr('disabled');
1768
1769				$(this).off('input').on('input', function (event) {
1770					this.value = this.value.replace(/[\ㄱ-ㅎㅏ-ㅣ가-힣]/g, '');
1771				});
1772
1773				$(this).datepicker({
1774					minDate: minDate,
1775					maxDate: maxDate,
1776					disabled: isDisabled,
1777					beforeShow: function (input, inst) {
1778						setTimeout(function () {
1779							inst.dpDiv.position({
1780								my: 'right top+6',
1781								at: 'right bottom',
1782								collision: 'none',
1783								of: input
1784							});
1785						}, 1);
1786					},
1787					onClose: function (dateText, inst) {
1788						// 20190908 형태의 날짜 입력에 대한 대응
1789						if (dateText && dateText.length === 8) {
1790							$(this).datepicker('setDate', new Date(dateText.substring(0, 4), dateText.substring(4, 6) - 1, dateText.substring(6, 8)));
1791						}
1792						// onClose 시 날짜형식을 유지하도록 하는 트릭
1793						$(this).datepicker('option', 'dateFormat', $(this).datepicker('option', 'dateFormat'));
1794					},
1795				});
1796			})
1797		}
1798	}
1799
1800	/**
1801	 * fold 설정
1802	 * @param selector fold 생성 DOM 셀렉터(default : .fold_box_wrap)
1803	 */
1804	function setFoldBox(selector) {
1805		selector = selector ? selector : '.fold_box_wrap';
1806		if ($(selector).length > 0) {
1807			$(selector).find('.fold_box .fold_box_header').each(function (index) {
1808				$(this).closest('.fold_box').data('btn', $(this).find('.btn_fold')); // 220427 폴드 다중구조 이슈 해결을 위한 스크립트 수정 by do
1809				$(this).find('.btn_fold').off('click.uiFold').on('click.uiFold', function (event) {
1810					if ($(event.target).is('a') || $(event.currentTarget).closest('.fold_box').is('.no_fold') || $(event.target).is('input')) {
1811						// console.log('setFoldBox', $(event.target).is('a'), $(event.target).is('button'))
1812						// event.preventDefault();
1813						return;
1814					}
1815
1816					if ($(event.target).is('label')) {
1817						if ($(event.target).is('label') || $(event.target).is('input')) {
1818							return;
1819						}
1820					}
1821
1822					var foldBox = $(this).closest('.fold_box');
1823					foldBox.btn = $(this);
1824
1825					var isExpanded;
1826					isExpanded = foldBox.hasClass('expanded');
1827
1828					if (!($(event.currentTarget).closest('.fold_box_wrap').data('type') === 'multi')) {
1829						var allFoldBox;
1830						if (isExpanded) {
1831							allFoldBox = $(this).closest('.fold_box_wrap').find('.fold_box').not('.expanded');
1832						} else {
1833							allFoldBox = $(this).closest('.fold_box_wrap').find('.fold_box');
1834						}
1835
1836						allFoldBox.removeClass('expanded');
1837						allFoldBox.each(function (index) {
1838							$(this).data('btn').find('.hidden').text('컨텐츠 열기');
1839						})
1840						// allFoldBox.find('.hidden').text('컨텐츠 열기');
1841
1842						foldTransition(allFoldBox);
1843					}
1844
1845					if (isExpanded) {
1846						foldOnOff().foldClose(foldBox);
1847					} else {
1848						foldOnOff().foldOpen(foldBox);
1849					}
1850
1851					var evtData = {
1852						index: $(event.currentTarget).closest('.fold_box').index(),
1853						isExpanded: $(event.currentTarget).closest('.fold_box').hasClass('expanded'),
1854					};
1855					var evt = new CustomEvent('headerClick', {'detail': evtData});
1856
1857
1858					$(event.currentTarget).closest('.fold_box')[0].dispatchEvent(evt);
1859				});
1860			});
1861		}
1862	}
1863
1864	/**
1865	 * fold On/Off
1866	 */
1867	function foldOnOff() {
1868		var control = {
1869			/**
1870			 * fold open
1871			 * @param selector {string} 타겟 foldbox
1872			 * @param callback {string} fold open 후 callback 함수
1873			 */
1874			foldOpen: function (selector, callback) {
1875				selector.addClass('expanded');
1876				selector.data('btn').find('.hidden').text('컨텐츠 닫기');
1877
1878				if (!selector.hasClass('type_floating') && !selector.hasClass('no_fold')) {
1879					foldTransition(selector);
1880				}
1881
1882				if (callback != null && typeof callback === "function") {
1883					callback.apply(null, [tgId]);
1884				}
1885			},
1886
1887			/**
1888			 * fold close
1889			 * @param tgId {string} 타겟 foldbox
1890			 */
1891			foldClose: function (selector) {
1892				selector.removeClass('expanded');
1893				selector.data('btn').find('.hidden').text('컨텐츠 열기');
1894
1895				if (!selector.hasClass('type_floating') && !selector.hasClass('no_fold')) {
1896					foldTransition(selector);
1897				}
1898			},
1899		}
1900
1901		return control;
1902	}
1903
1904	/**
1905	 * fold transition
1906	 * @param selector - foldbox
1907	 */
1908	function foldTransition(selector, isForce) {
1909		if ($(selector).closest('.fold_box_wrap').hasClass('type_reservation')) return;
1910		var curHeight,
1911			changeHeight = 0;
1912		isForce = isForce || false;
1913		curHeight = selector.outerHeight();
1914
1915		selector.css('height', 'auto');
1916
1917		changeHeight = selector.outerHeight();
1918		selector.css('height', curHeight).stop().animate({height: changeHeight}, (isForce ? 0 : 150), function () {
1919			var that;
1920			that = $(this);
1921
1922			if (that.closest('.fold_box_wrap').closest('.custom_scroll_wrap').length > 0
1923				&& that.closest('.fold_box_wrap').closest('.custom_scroll_wrap')[0].simpleBar !== undefined) {
1924				that.closest('.fold_box_wrap').closest('.custom_scroll_wrap')[0].simpleBar.recalculate();
1925			}
1926			// fold_box_contents 내부 높이가 사이즈가 달라질 수 있어 모션 적용 후 height 제거
1927			if (that.hasClass('expanded')) {
1928				that.get(0).style.removeProperty('height');
1929			}
1930
1931			setTimeout(function () {
1932				if ((that.find('.fold_box_header').outerHeight() + that.find('.fold_box_contents').outerHeight() + 2) !== changeHeight) {
1933					foldTransition(that, true);
1934				} else {
1935					if (that.closest('.custom_scroll_inner').outerHeight() > that.closest('.custom_scroll_wrap').outerHeight()) {
1936						that.closest('.custom_scroll_wrap').addClass('active');
1937					} else {
1938						that.closest('.custom_scroll_wrap').removeClass('active');
1939					}
1940				}
1941			}, 200);
1942		});
1943	}
1944
1945	/**
1946	 * max-height 영역 안에 요소가 넘치는 경우 auto overflow 처리
1947	 * @param wrap 컨테이너 DOM 셀렉터 (default: '.auto_overflow_wrap')
1948	 * @param contents 늘어나는 컨텐츠 영역 (default: '.auto_overflow_contents')
1949	 * @param inner 늘어나는 요소 셀렉터 (default: '.auto_overflow_inner')
1950	 * @param btn 영역 펼침 버튼 셀렉터 (default: '[data-btn-toggle]')
1951	 * @param container 컨텐츠영역 / 팝업영역 제어(default: '.wrapper', popup: '.dialog_wrapper')
1952	 */
1953	function autoOverflowContents(container, wrap, contents, inner, btn) {
1954		wrap = wrap || '.auto_overflow_wrap';
1955		contents = contents || '.auto_overflow_contents';
1956		inner = inner || '.auto_overflow_inner';
1957		btn = btn || '> .auto_overflow_footer [data-btn-toggle]';
1958		container = container || '.wrapper';
1959
1960		if ($(wrap, container).length > 0) {
1961			$(wrap, container).each(function () {
1962				var isToggle,
1963					isOpened,
1964					wrapMaxHeight,
1965					innerHeight,
1966					btnBeforeText,
1967					btnAfterText;
1968				wrapMaxHeight = parseInt($(this).find(contents).css('max-height').replace('px', ''));
1969				innerHeight = Math.max($(this).find(inner).outerHeight(), $(this).find(inner).get(0).scrollHeight);
1970				btnBeforeText = $(this).find(btn).text();
1971
1972				if (innerHeight <= wrapMaxHeight) {
1973					return;
1974				}
1975				$(this).addClass('overflow');
1976
1977				if ($(this).hasClass('active')) {
1978					isOpened = true;
1979				}
1980				if ($(this).find(btn).data('btn-toggle') !== undefined) {
1981					isToggle = true;
1982				}
1983				if (isToggle) {
1984					$(this).find(btn).off('.click.overflow').on('click.overflow', function (event) {
1985						if (Boolean(btnBeforeText.match('펼치기'))) {
1986							btnAfterText = btnBeforeText.replace('펼치기', '접기');
1987						} else if (Boolean(btnBeforeText.match('더보기'))) {
1988							btnAfterText = btnBeforeText.replace('더보기', '닫기');
1989						} else if (Boolean(btnBeforeText.match('접기'))) {
1990							btnAfterText = btnBeforeText.replace('접기', '펼치기');
1991						} else if (Boolean(btnBeforeText.match('닫기'))) {
1992							btnAfterText = btnBeforeText.replace('닫기', '더보기');
1993						}
1994
1995						if ($(this).closest(wrap).hasClass('active')) {
1996							$(this).closest(wrap).removeClass('active');
1997							$(this).removeClass('active');
1998
1999							if (isOpened) {
2000								$(this).find('.text').text(btnAfterText);
2001							} else {
2002								$(this).find('.text').text(btnBeforeText);
2003							}
2004						} else {
2005							$(this).closest(wrap).addClass('active');
2006							$(this).addClass('active');
2007
2008							if (isOpened) {
2009								$(this).find('.text').text(btnBeforeText);
2010							} else {
2011								$(this).find('.text').text(btnAfterText);
2012							}
2013						}
2014					});
2015				}
2016			});
2017		}
2018	}
2019
2020	/**
2021	 * selectmenu refresh
2022	 */
2023	function callSelectRefresh(tgId) {
2024		// console.log($(tgId).selectmenu('instance'))
2025		$(tgId).selectmenu('refresh');
2026
2027		// if($(tgId).parent().data('renderer') === 'selProdOpt') {
2028		// 	$(tgId).selProdOpt('refresh');
2029		// }else if($(tgId).parent().data('renderer') === 'selInteriorOpt') {
2030		// 	$(tgId).selInteriorOpt('refresh');
2031		// }else{
2032		// 	$(tgId).selectmenu('refresh');
2033		// }
2034	}
2035
2036	/**
2037	 * 숫자 number에 대해 n 자릿수 문자열로 치환하여 반환
2038	 * @param number {number} 정수 숫자 값
2039	 * @param digits {number} 자릿수(defalut: 2)
2040	 * @returns {string} 치환 된 문자열
2041	 */
2042	function setPrependZero(number, digits) {
2043		number = number + '';
2044		digits = digits || 2;
2045		return number.length >= digits ? number : new Array(digits - number.length + 1).join('0') + number;
2046	}
2047
2048	/**
2049	 * toast message
2050	 * @param msg 노출되는 메세지 내용
2051	 * @param timer toast 노출 시간 밀리세컨드로 계산(default: 2000)
2052	 * @param link 토스트 팝업 우측 링크
2053	 */
2054	function setToastMessage(msg, link, timer) {
2055		if (!timer) {
2056			timer = 2000;
2057		}
2058
2059		let toastHtml = "<span class='toast_message'>" + msg;
2060
2061		// 링크 추가
2062		if (typeof link === 'string' && link.trim() !== '') {
2063			let linkText = '바로가기';
2064
2065			// notice_complete 버튼일 경우 출력 내용 다르게
2066			const activeEl = document.activeElement;
2067			if (activeEl && activeEl.classList.contains('notice_complete')) {
2068				linkText = '신청 내역 보기';
2069			}
2070
2071			toastHtml += "<a href='" + link + "' class='toast_link'>" + linkText + "</a>";
2072		}
2073		toastHtml += "</span>";
2074
2075		let toastCont = $("<div class='toast_wrap'>" + toastHtml + "</div>");
2076
2077		if ($('body').find('.toast_wrap').length < 1) {
2078			$('body').append(toastCont);
2079		}
2080		toastPopupCalaPos();
2081
2082		toastCont.slideToggle(200, function () {
2083			if (!isNaN(timer)) {
2084				setTimeout(function () {
2085					toastCont.fadeOut(function () {
2086						$(this).remove();
2087					});
2088				}, timer);
2089			}
2090		});
2091
2092		$(window).off('scroll.uiToast resize.uiToast', toastPopupCalaPos)
2093			.on('scroll.uiToast resize.uiToast', toastPopupCalaPos);
2094
2095		function toastPopupCalaPos() {
2096			if (_bodyMinWidth > _deviceWidth) {
2097				$('.toast_wrap').css({
2098					left: '600px',
2099					transform: 'translateX(' + -_scrollLeft + 'px)'
2100				});
2101			} else {
2102				$('.toast_wrap').css({
2103					left: '',
2104					transform: ''
2105				});
2106			}
2107		}
2108	}
2109
2110	/**
2111	 * tooltip hover type on off
2112	 * @param container tooltip 컨테이너 영역 DOM 셀렉터 (default : .tooltip_wrap)
2113	 */
2114	function tooltipOnOff(container) {
2115		container = container || '.tooltip_wrap';
2116
2117		if ($(container).length > 0) {
2118			$(container).each(function () {
2119				var that,
2120					isToggle;
2121				that = $(this);
2122
2123				$(this).find('.btn_tooltip').on('click', function () {
2124					if ($(this).data('btn-toggle') !== undefined) {
2125						isToggle = true;
2126					}
2127
2128					if (isToggle) {
2129						if (that.hasClass('active')) {
2130							that.removeClass('active').addClass('hide');
2131							$(this).find('.hidden').text('툴팁열기');
2132						} else {
2133							$('.tooltip_wrap.active').removeClass('active').addClass('hide');
2134							that.removeClass('hide').addClass('active');
2135							$(this).find('.hidden').text('툴팁닫기');
2136						}
2137						return;
2138					}
2139
2140					if (that.hasClass('active')) return;
2141					$('.tooltip_wrap.active').removeClass('active').addClass('hide');
2142					that.removeClass('hide').addClass('active');
2143
2144					// 수정 241210 툴팁 레이어 열리면 스크롤바 업데이트
2145					if ($(this).closest('.custom_scroll_wrap').length > 0) {
2146						$(this).closest('.custom_scroll_wrap').get(0)?.simpleBar.recalculate();
2147					}
2148				});
2149
2150				if (!isToggle) {
2151					$(this).find('.btn_tooltip_close').on('click', function () {
2152						that.removeClass('active').addClass('hide');
2153					});
2154				}
2155
2156				$(this).on('transitionend', function () {
2157					$(this).removeClass('hide');
2158				});
2159			});
2160		}
2161	}
2162
2163
2164	/**
2165	 * optMenuOnOff type on off
2166	 * @param container tooltip 컨테이너 영역 DOM 셀렉터 (default : .opt_menu_wrap)
2167	 */
2168	function optMenuOnOff(container) {
2169		container = container || '.opt_menu_wrap';
2170
2171		if ($(container).length > 0) {
2172			$(container).each(function () {
2173				var that,
2174					isToggle;
2175				that = $(this);
2176
2177				$(this).find('.btn_opt_menu').on('click', function () {
2178					if ($(this).data('btn-toggle') !== undefined) {
2179						isToggle = true;
2180					}
2181
2182					if (isToggle) {
2183						if (that.hasClass('active')) {
2184							that.removeClass('active').addClass('hide');
2185							$(this).find('.hidden').text('메뉴열기');
2186						} else {
2187							$(container + '.active').removeClass('active').addClass('hide');
2188							that.removeClass('hide').addClass('active');
2189							$(this).find('.hidden').text('메뉴닫기');
2190						}
2191						return;
2192					}
2193
2194					if (that.hasClass('active')) return;
2195					$('.opt_menu_wrap.active').removeClass('active').addClass('hide');
2196					that.removeClass('hide').addClass('active');
2197				});
2198
2199				if (!isToggle) {
2200					$(this).find('.opt_menu_link').on('click', function () {
2201						that.removeClass('active').addClass('hide');
2202					});
2203				}
2204
2205				$(this).on('transitionend', function () {
2206					$(this).removeClass('hide');
2207				});
2208			});
2209		}
2210	}
2211
2212	/**
2213	 * img 가로형/세로형 체크
2214	 * @param container imgTg : $(this)
2215	 * @param container container : addClass되는 container 타겟
2216	 */
2217	function checkImagePortrait(imgTg, container) {
2218		container === undefined ? container = imgTg : container;
2219		var chkImg = imgTg.find('img').get(0);
2220
2221		if (chkImg !== undefined) {
2222			container.removeClass('landscape portrait even');
2223
2224			if (chkImg.naturalWidth > chkImg.naturalHeight) { // 가로형
2225				container.addClass('landscape');
2226			} else if (chkImg.naturalWidth < chkImg.naturalHeight) { //세로형
2227				container.addClass('portrait');
2228			} else { // 정사각형
2229				container.addClass('even');
2230			}
2231		}
2232	}
2233
2234	/**
2235	 * sns 공유하기 공통
2236	 */
2237	function shsShareToggle() {
2238		$('.btn_share', '.sns_share_wrap:has(.sns_share_box)').on('click', function () { // 수정 251105 공유하기 개선
2239			$(this).closest('.sns_share_wrap').addClass('active');
2240		});
2241
2242		$('.btn_sns_share_close').on('click', function () {
2243			$(this).closest('.sns_share_wrap').removeClass('active');
2244		});
2245	}
2246
2247	/**
2248	 * 우편번호 검색 결과 상세주소보기 영역 on/off
2249	 */
2250	function addressDetailAreaOnOff() {
2251		var btnRoad = $('.btn_road_name');
2252		var btnLand = $('.btn_land_number');
2253		var targetDetail = $('.success_detail')
2254
2255		function DetailOpenClose(btn) {
2256			btn.on('click', function (v) {
2257				targetDetail.removeClass('active');
2258				targetDetail.eq(btn.index($(this))).addClass('active');
2259			});
2260		}
2261
2262		// 수정 211126 상세검색 영역 없는 경우 조건 처리
2263		if (targetDetail.length > 0) {
2264			DetailOpenClose(btnRoad)
2265			DetailOpenClose(btnLand)
2266		}
2267	}
2268
2269	/**
2270	 * tag button on/off
2271	 */
2272	function setTagToggle() {
2273		$('.tag_wrap').each(function () {
2274			if ($(this).data('tag-toggle') !== undefined) {
2275				$(this).find('.tag').on('click', function () {
2276					$(this).closest('.tag_wrap').find('.tag').removeClass('active');
2277					$(this).addClass('active');
2278				})
2279			}
2280		});
2281	}
2282
2283	/**
2284	 * tag multi button on/off
2285	 */
2286	function setTagToggleMulti() {
2287		$('.tag_wrap').each(function () {
2288			if ($(this).data('tag-multi') !== undefined) {
2289				$(this).find('.tag').on('click', function () {
2290					$(this).toggleClass('active');
2291				});
2292			}
2293		});
2294	}
2295
2296	/**
2297	 * 상품 리스트로보기/텍스트로보기 토글
2298	 */
2299	function setSwitchListBtn(callback) {
2300		$('.switch_list_btn_wrap').each(function (index) {
2301			var btns,
2302				target;
2303			btns = $(this).find('button');
2304			target = $($(this).data('target'));
2305
2306			btns.on('click.switch', function (event) {
2307				var type;
2308				btns.removeClass('active');
2309				$(this).addClass('active');
2310				type = 'view_type_' + $(this).data('type');
2311				// console.log(type);
2312				target.removeClass('view_type_img view_type_txt view_type_list').addClass(type);
2313				// console.log(target, type);
2314
2315				if (callback != null && typeof callback === "function") {
2316					callback(target, type);
2317				}
2318			});
2319		});
2320	}
2321
2322	/**
2323	 * 도메인 자동완성
2324	 */
2325	function setDomainAutoComplete() {
2326		if ($('.form_ip[type="email"]').length > 0) {
2327			$('.form_ip[type="email"][data-autocomplete]').each(function () {
2328				var tg,
2329					wrapStr;
2330				tg = $(this);
2331
2332				var awesomplete = new Awesomplete(tg.get(0), {
2333					list: ['naver.com', 'hanmail.net', 'gmail.com', 'nate.com', 'yahoo.co.kr', 'hotmail.com', 'paran.com', 'dreamwiz.com', 'empal.com', 'korea.com', 'freechal.com'],
2334					data: function (text, input) {
2335						return input.slice(0, input.indexOf("@")) + "@" + text;
2336					},
2337					sort: false, // 수정 221009 길이순 정렬 비활성화
2338					maxItems: 20, // 수정 221009 표시할 최대 제안 수
2339				});
2340
2341				if (isNaN(parseInt(tg.data('autocomplete')))) {
2342					wrapStr = '<div class="auto_complete_box"><div class="custom_scroll_wrap"></div></div>';
2343				} else {
2344					var boxHeight;
2345					boxHeight = parseInt(tg.data('autocomplete')) + 'px';
2346					wrapStr = '<div class="auto_complete_box"><div class="custom_scroll_wrap" style="max-height: ' + boxHeight + '"></div></div>';
2347				}
2348
2349
2350				tg.closest('.awesomplete').find('ul').wrap(wrapStr);
2351
2352				tg.on('awesomplete-open', function (e) {
2353					// The popup just appeared.
2354					tg.closest('.awesomplete').addClass('active');
2355
2356					// 수정 250409 회원정보 수정 마스킹 처리 개선
2357					var scrollWrap = tg.closest('.awesomplete').find('.custom_scroll_wrap').get(0);
2358					if (scrollWrap.clientHeight < 1) {
2359						scrollWrap.simpleBar.recalculate();
2360					}
2361				});
2362
2363				tg.on('awesomplete-close', function (e) {
2364					// The popup just closed.
2365					tg.closest('.awesomplete').removeClass('active');
2366				});
2367
2368				tg.on('awesomplete-highlight', function (e) {
2369					var lists,
2370						scrollWrap,
2371						scrollTop;
2372					lists = tg.closest('.awesomplete').find('ul');
2373					scrollWrap = lists.closest('.custom_scroll_wrap').get(0);
2374					scrollTop = lists.find('li[aria-selected="true"]').offset().top - lists.offset().top;
2375					$(scrollWrap.simpleBar.getScrollElement()).scrollTop(scrollTop);
2376					// console.log($(scrollWrap.simpleBar.getScrollElement()).scrollTop(), scrollTop);
2377				});
2378			});
2379
2380			setCustomScroll('.awesomplete');
2381		}
2382	}
2383
2384	// dropdown 토글
2385	function dropdownToggle() {
2386		var toggleBoxEl = $('.btn_dropdown_toggle_box');
2387
2388		$('.btn_dropdown_toggle', toggleBoxEl).on('click', function () {
2389			if (toggleBoxEl.hasClass('active')) {
2390				toggleBoxEl.removeClass('active');
2391				$(this).find('.hidden').text('닫기');
2392			} else {
2393				toggleBoxEl.addClass('active');
2394				$(this).find('.hidden').text('열기');
2395			}
2396		});
2397	}
2398
2399	// switch on off
2400	function setSwitchOnOff() {
2401		$('.btn_switch').on('click.uiSwitch', function () {
2402			var tgCont = $(this).attr('data-switch-tg');
2403			var allCont = $(this).closest('.switch_toggle_wrap').find('.switch_toggle_content');
2404
2405			$(this).addClass('active');
2406			$(this).siblings('.btn_switch').removeClass('active');
2407
2408			allCont.removeClass('active');
2409			$(tgCont).addClass('active');
2410
2411			var evt = new CustomEvent('switchChange', {detail: tgCont});
2412
2413			$(this).get(0).dispatchEvent(evt);
2414		});
2415	}
2416
2417	_front.setSpsOffsetData = setSpsOffsetData;
2418	_front.setCustomScroll = setCustomScroll;
2419	_front.setTableCaption = setTableCaption;
2420	_front.setStarRating = setStarRating;
2421	_front.setUIDialog = setUIDialog;
2422	_front.dialogOnOff = dialogOnOff;
2423	_front.setUISelect = setUISelect;
2424	_front.setUISpinner = setUISpinner;
2425	_front.setDatepicker = setDatepicker;
2426	_front.callSelectRefresh = callSelectRefresh;
2427	_front.togglePassword = togglePassword;
2428	_front.setTabs = setTabs;
2429	_front.tabListFolding = tabListFolding;
2430	_front.setFoldBox = setFoldBox;
2431	_front.setGNB = setGNB;
2432	_front.setFloating = setFloating;
2433	_front.setPrependZero = setPrependZero;
2434	_front.setToastMessage = setToastMessage;
2435	_front.tooltipOnOff = tooltipOnOff;
2436	_front.autoOverflowContents = autoOverflowContents;
2437	_front.checkImagePortrait = checkImagePortrait;
2438	_front.addressDetailAreaOnOff = addressDetailAreaOnOff;
2439	_front.setSwitchListBtn = setSwitchListBtn;
2440	_front.foldOnOff = foldOnOff;
2441	_front.setDomainAutoComplete = setDomainAutoComplete;
2442	_front.dropdownToggle = dropdownToggle;
2443	_front.setSwitchOnOff = setSwitchOnOff;
2444	_front.setSearchInput = setSearchInput;
2445	_front.setBreadCrumb = setBreadCrumb;
2446	_front.setFamilySiteMore = setFamilySiteMore;
2447
2448	$(window).on('load.uiCommon', function () {
2449		if (/Mac|iPhone|iPad|iPod/i.test(navigator.platform)) {
2450			$('html').addClass('ios');
2451		}
2452		if (/Edge\/\d./i.test(navigator.userAgent)) {
2453			$('html').addClass('edge');
2454		} else if (/trident\/\d./i.test(navigator.userAgent)) {
2455			$('html').addClass('ie');
2456		}
2457	});
2458	$(window).on('scroll.uiCommon resize.uiCommon', function () {
2459		_scrollLeft = Math.round(document.documentElement.scrollLeft || window.pageXOffset);
2460		_scrollTop = Math.round(document.documentElement.scrollTop || window.pageYOffset);
2461
2462		setFixedElementPosX();
2463		openSelectClose();
2464	});
2465
2466	$(window).on('resize.uiCommon', function () {
2467		_deviceWidth = $(window).width() || window.innerWidth || document.body.clientWidth;
2468		_deviceHeight = $(window).height() || window.innerHeight || document.body.clientHeight;
2469		_deviceHeight = $(window).height() || window.innerHeight || document.body.clientHeight;
2470
2471		dialogAutoHeight();
2472	});
2473
2474	// 페이지 공통 스크립트
2475	_front.page = {};
2476
2477	// event swiper
2478	function setEventSwiper() {
2479		if ($('.event_swiper_wrap').length > 0) {
2480			$('.event_swiper_wrap').each(function () {
2481				var eventSwiperEl = $(this);
2482				if ($('.swiper-slide', eventSwiperEl).length > 1) {
2483					var eventSwiper = new CustomSwiper(eventSwiperEl.find('.swiper-container').get(0), {
2484						slidesPerView: 'auto',
2485						speed: 500,
2486						scrollbar: {
2487							el: $('.swiper-scrollbar', eventSwiperEl)[0],
2488						},
2489					});
2490				} else {
2491					$('.swiper-scrollbar', eventSwiperEl).remove();
2492				}
2493			});
2494		}
2495	}
2496
2497	// 리뷰 내 리뷰 썸네일 swiper
2498	function setReviewThumbnailSwiper(len) {
2499		len = len ? len : 2;
2500		$('.comment_swiper_wrap .swiper-container').each(function () {
2501			if ($(this).find('.swiper-slide').length > len) {
2502				var reviewSwiper = new CustomSwiper(this, {
2503					observer: true,
2504					observeParents: true,
2505					slidesPerView: 'auto',
2506					navigation: {
2507						nextEl: $(this).siblings('.swiper-button-next'),
2508						prevEl: $(this).siblings('.swiper-button-prev'),
2509					},
2510				});
2511			} else {
2512				$(this).siblings('.swiper-button-next, .swiper-button-prev').css('display', 'none');
2513			}
2514		});
2515	}
2516
2517	// 문장수집
2518	function setKillingPartSwiper() {
2519		if ($('.killing_part_swiper').length > 0) {
2520
2521			$('.killing_part_swiper').each(function () {
2522				var killingPartSwiperEl = $(this);
2523				var killingPartSwiper = new CustomSwiper($('.swiper-container', killingPartSwiperEl), {
2524					slidesPerView: 'auto',
2525					loop: killingPartSwiperEl.find('.swiper-slide').length > 1,
2526					speed: 500,
2527					observer: true,
2528					observeParents: true,
2529					navigation: {
2530						nextEl: $('.swiper-button-next', killingPartSwiperEl).get(0),
2531						prevEl: $('.swiper-button-prev', killingPartSwiperEl).get(0),
2532					},
2533				});
2534			});
2535		}
2536	}
2537
2538	function setCommentList() {
2539		var reviewContents,
2540			reviewText,
2541			contentsOverflow,
2542			textOverflow,
2543			btnToggle;
2544		if ($('.comment_wrap').closest('.dialog_wrap.dialog_review').length > 0) return false; // 리뷰 팝업 내에선 실행 X
2545
2546		if ($('.comment_wrap .comment_item').length > 0) {
2547			$('.comment_wrap .comment_item').each(function () {
2548				var that = $(this);
2549				btnToggle = $(this).find('.comment_footer .btn_more_body');
2550				reviewContents = $(this).find('.comment_contents .comment_contents_inner');
2551
2552				// 리뷰 목록 toggle overflow
2553				if (reviewContents.length > 0) {
2554					reviewText = reviewContents.find('.comment_text');
2555					textOverflow = reviewText[0].scrollHeight > reviewText.height();
2556					contentsOverflow = reviewContents[0].scrollHeight > reviewContents.height();
2557
2558					// console.log($(this).index(), 'Contents : ', reviewContents[0].scrollHeight, reviewContents.height(), contentsOverflow, '///', 'Text : ', reviewText[0].scrollHeight, reviewText.height(), textOverflow);
2559					if (contentsOverflow || textOverflow) {
2560						that.addClass('overflow');
2561
2562						btnToggle.off('click').on('click', function () {
2563							if (that.hasClass('active')) {
2564								that.removeClass('active');
2565								$(this).removeClass('active').find('.text').text('펼치기');
2566							} else {
2567								that.addClass('active');
2568								$(this).addClass('active').find('.text').text('접기');
2569							}
2570						});
2571					} else {
2572						that.removeClass('overflow');
2573					}
2574				}
2575
2576				// 리뷰 이미지 비율 체크
2577				$(this).find('.comment_swiper_wrap .portrait_img_box').each(function () {
2578					var imgTg = $(this);
2579					KyoboBookPub.ink.checkImagePortrait(imgTg);
2580				});
2581			});
2582		}
2583	}
2584
2585	_front.page.setEventSwiper = setEventSwiper;
2586	_front.page.setReviewThumbnailSwiper = setReviewThumbnailSwiper;
2587	_front.page.setKillingPartSwiper = setKillingPartSwiper;
2588	_front.page.setCommentList = setCommentList;
2589	// e : 페이지 공통 스크립트
2590
2591	// s : Lottie Animation Data
2592	_front.lottie = {};
2593	_front.lottie.loading = '/cdn/data/loading_onk.json';
2594	_front.lottie.couponDownload = '/cdn/data/coupon_download_onk.json';
2595	_front.lottie.heartCasting = '/cdn/data/heart_casting_h20_onk.json';
2596	_front.lottie.heartDetail = '/cdn/data/heart_detail_h20_onk.json';
2597	_front.lottie.heartGray16 = '/cdn/data/heart_gray_h16_onk.json';
2598	_front.lottie.heartGray18 = '/cdn/data/heart_gray_h18_onk.json';
2599	_front.lottie.heartGray22 = '/cdn/data/heart_gray_h22_onk.json';
2600	_front.lottie.heart14 = '/cdn/data/heart_h14_onk.json';
2601	_front.lottie.heart18 = '/cdn/data/heart_h18_onk.json';
2602	_front.lottie.heartPurple18 = '/cdn/data/heart_purple_h18_onk.json';
2603	_front.lottie.liveBadge = '/cdn/data/live_badge_ink.json';
2604	_front.lottie.hotLine = '/cdn/data/hot_line_ink.json';
2605	_front.lottie.hotDeal = '/cdn/data/hot_deal_ink.json'; // 추가 231123 핫딜 아이콘 Lottie
2606	_front.lottie.picksAI = '/cdn/data/picks_ai_onk.json'; // 추가 260911 Picks AI 아이콘 Lottie
2607	// e : Lottie Animation Data
2608
2609
2610	$(document).ready(function () {
2611		_deviceWidth = $(window).width() || window.innerWidth || document.body.clientWidth;
2612		_deviceHeight = $(window).height() || window.innerHeight || document.body.clientHeight;
2613		_scrollLeft = Math.round(document.documentElement.scrollLeft || window.pageXOffset);
2614		_scrollTop = Math.round(document.documentElement.scrollTop || window.pageYOffset);
2615
2616		_btnGoTop = $('.btn_go_top');
2617		_headerWrapper = $('.header_wrapper');
2618		_flyMenuEl = $('.fly_menu_wrapper');
2619		_floatingEl = $('.floating_wrapper');
2620		_container = $('.container_wrapper');
2621		_btnCurationBot = $('.btn_curation_bot');
2622
2623		_btnGoTop.off('click').on('click', function (e) {
2624			e.preventDefault();
2625			$('html, body').animate({
2626				scrollTop: 0
2627			}, 200, function () {
2628				_btnGoTop.removeClass('active');
2629			});
2630		});
2631
2632		setGNB();
2633		setFloating();
2634		setSpsOffsetData();
2635		setFixedElementPosX()
2636		setCustomScroll();
2637		setTableCaption();
2638		setStarRating();
2639		setUIDialog();
2640		setBreadCrumb();
2641		setUISelect();
2642		togglePassword();
2643		setUISpinner();
2644		setDatepicker();
2645		setTabs();
2646		setFoldBox();
2647		addressDetailAreaOnOff();
2648		setFamilySiteMore();
2649		setSearchInput();
2650		tooltipOnOff();
2651		shsShareToggle();
2652		autoOverflowContents();
2653		setTagToggle();
2654		setTagToggleMulti();
2655		setDomainAutoComplete();
2656		dropdownToggle();
2657		setSwitchOnOff();
2658		optMenuOnOff();
2659	});
2660
2661	return _front;
2662})() || KyoboBookPub.ink;
2663
2664// Custom Swiper
2665var CustomSwiper = function (selector, options) {
2666	options = $.extend({
2667		// s: 220822 최적화 관련 이미지 lazy 로드 추가 요청 반영
2668		lazy: {
2669			checkInView: true,
2670			loadOnTransitionStart: true,
2671		},
2672		watchSlidesProgress: true,
2673		watchSlidesVisibility: true,
2674		// e: 220822 최적화 관련 이미지 lazy 로드 추가 요청 반영
2675
2676		keyboard: false,
2677		on: {
2678			destroy: function () {
2679				$(selector).off('focusin.swiper').off('focusout.swiper');
2680			}
2681		}
2682	}, options);
2683	$(selector).on('focusin.swiper', function (event) {
2684		this.swiper.keyboard.enable();
2685	}).on('focusout.swiper', function (event) {
2686		this.swiper.keyboard.disable();
2687	})
2688	return new Swiper(selector, options);
2689};

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.