PageSourceSearch

https://www.lghellovision.net/front/web/js/ui-page-app.js?ts=202609241908

js lghellovision.net collected 2026-09-24 10:08:41 UTC 44,816 bytes, 1,143 lines download raw bytes

1var isTouchMove = false;  // global var, 커스텀 커서 드래그 방향 탐지를 위한 장치
2var timerTouchMove = null;
3var mySwiperUserReview = null; // 공통 슬라이더 사용자 리뷰
4
5window.pageName = window.pageName || 'page-default';
6
7// Page InView Animation
8var PAGES = {
9    MAIN: {
10        el: '.main-section',
11        onInview: function(_idx, _el) {
12        
13        },
14        offInview: function(_idx, _el) {
15
16        }
17    },
18    SHOPMAIN: {
19        el: '.main-section',
20        onInview: function(_idx, _el) {
21            var _id = _el.getAttribute('id') || '';
22            _id = _id.trim();
23            if (_id == 'mainBenefits') {
24                animSection('#mainBenefitsItems', true);
25            } else if (_id == 'mainProducts'){
26                 animSection('#mainProductsItems', true);
27            }
28        },
29        offInview: function(_idx, _el) {
30            var _id = _el.getAttribute('id') || '';
31            _id = _id.trim();
32            if (_id == 'mainBenefits') {
33                animSection('#mainBenefitsItems', false);
34                $('#mainSimulator').removeClass('is-modal is-detail-view');
35            } else if (_id == 'mainProducts'){
36                animSection('#mainProductsItems', false);
37            }
38        }
39    },
40    COMBINE: {
41        el: '.main-section',
42        onInview: null,
43        offInview: null
44    },
45    COMBINE_MOBILE: {
46        el: '.main-section',
47        onInview: function(_idx, _el) {
48            if (_idx == 1)  {
49                animSection('#eventGraphSave', true);
50            }
51        },
52        offInview: function(_idx, _el) {
53            if (_idx == 1)  {
54                animSection('#eventGraphSave', false);
55            }
56        }
57    },
58    INTERNET: {
59        el: '.main-section',
60        onInview: function(_idx, _el) { // _idx: section index
61            if (_idx == 4) animSection('#moduleOtherPeople', true);
62        },
63        offInview: function(_idx, _el) {
64            if (_idx == 4) animSection('#moduleOtherPeople', false);
65        }
66    },
67    TV: {
68        el: '.main-section',
69        onInview: function(_idx, _el) {
70            if (_idx == 5) animSection('#moduleOtherPeople', true);
71        },
72        offInview: function(_idx, _el) {
73            if (_idx == 5) animSection('#moduleOtherPeople', false);
74        }
75    },
76    EVENT: {
77        el: '.main-section',
78        onInview: function(_idx, _el) {
79            if (_idx == 4)  {
80                animSection('#eventGraphSave', true);
81            } else if (_idx == 5)  {
82                animSection('#eventChart', true);
83            } else if (_idx == 6)  {
84                animSection('#eventCount', true);
85            }
86        },
87        offInview: function(_idx, _el) {
88            if (_idx == 4) {
89                animSection('#eventGraphSave', false);
90            } else if (_idx == 5)  {
91                animSection('#eventChart', false);
92            } else if (_idx == 6)  {
93                animSection('#eventCount', false);
94            }
95        }
96    }
97};
98
99// 스와이퍼 옵션
100var SETTINGS_SWIPER = {
101    userReview:  {
102        slidesPerView: 'auto',
103        speed: 800,
104        spaceBetween: 0,
105        centeredSlides: true,
106        loop: true,
107        autoplay: {
108            disableOnInteraction: false,
109            delay: 2500
110        },
111        on: {
112            // touchStart: onSwiperTouchStart,
113            // touchEnd: onSwiperTouchEnd
114        }
115    },
116    mainUserReview: {
117        slidesPerView: 'auto',
118        speed: 800,
119        spaceBetween: 0,
120        centeredSlides: false,
121        slideToClickedSlide: false,
122        threshold: 30,
123        loop: false,
124        autoplay: {
125            disableOnInteraction: false,
126            delay: 2500
127        },
128        on: {
129            touchStart: onSwiperTouchStart,
130            touchEnd: onSwiperTouchEnd
131        }
132    },
133    modalUserReview: {
134        slidesPerView: 1,
135        speed: 800,
136        loop: false,
137        autoplay: false,
138        navigation: {
139          nextEl: '.next',
140          prevEl: '.prev'
141      }
142    }
143};
144
145function onSwiperTouchStart(_this) {
146    clearTimeout(timerTouchMove);
147    isTouchMove = true;
148    document.body.classList.add('is-touchmove');
149};
150
151function onSwiperTouchEnd(_this) {
152    timerTouchMove = setTimeout(function(){
153        window.isTouchMove = false;
154        document.body.classList.remove('is-touchmove');
155    }, 10);
156};
157
158var UI = (function($) {
159
160    'use strict';
161
162    $.easing.jswing = $.easing.swing;
163    $.extend($.easing, {
164        def: 'easeInOutCubic',
165        swing: function (x, t, b, c, d) {
166    		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
167    	},
168        easeInQuad: function(x, t, b, c, d) {
169            return c * (t /= d) * t + b;
170        },
171        easeInCubic: function(x, t, b, c, d) {
172            return c * (t /= d) * t * t + b;
173        },
174        easeInQuart: function(x, t, b, c, d) {
175            return c * (t /= d) * t * t * t + b;
176        },
177        easeOutQuad: function(x, t, b, c, d) {
178            return -c * (t /= d) * (t - 2) + b;
179        },
180        easeOutCubic: function(x, t, b, c, d) {
181            return c * ((t = t / d - 1) * t * t + 1) + b;
182        },
183        easeOutQuart: function(x, t, b, c, d) {
184            return -c * ((t = t / d - 1) * t * t * t - 1) + b;
185        },
186        easeInOutQuad: function(x, t, b, c, d) {
187            if ((t /= d / 2) < 1) return c / 2 * t * t + b;
188            return -c / 2 * ((--t) * (t - 2) - 1) + b;
189        },
190        easeInOutCubic: function(x, t, b, c, d) {
191            if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
192            return c / 2 * ((t -= 2) * t * t + 2) + b;
193        },
194        easeInOutQuart: function(x, t, b, c, d) {
195            if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
196            return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
197        }
198    });
199
200    var $document = $document || $(document),
201        $window = $window || $(window),
202        $html = $html || $('html'),
203        $body = $('body'); // recache
204
205    var SETTINGS = {
206        pageName: null,
207        debounceDelay: 500, // resize
208        throttleDelay: 200 // scroll
209    };
210    var opts = SETTINGS;
211    var htmlEl = document.documentElement, // html
212        bodyEl = document.body; // body
213
214    var breakpoint = {
215        $el: null,
216        current: null,
217        prev: null,
218        HTML: `<ul id="detector" class="sr-only">
219                <li class="sm-only" data-breakpoint="sm"><span class="sr-only">sm</span></li>
220                <li class="md-only" data-breakpoint="md"><span class="sr-only">md</span></li>
221                <li class="lg-only" data-breakpoint="lg"><span class="sr-only">lg</span></li>
222                <li class="xl-only" data-breakpoint="xl"><span class="sr-only">xl</span></li>
223                <li class="xxl-only" data-breakpoint="xxl"><span class="sr-only">xxl</span></li>
224                </ul>`,
225        onResize: function() {
226            this.current = this.$el.children(':visible').attr('data-breakpoint');
227            if (this.current == this.prev) return false;
228            htmlEl.setAttribute('data-breakpoint', this.current);
229            UI.base.breakpoint = this.prev = this.current; // set base, prev
230        },
231        build: function() {
232            if (document.querySelector('#detector') !== null) return false;
233            document.body.insertAdjacentHTML('beforeend', this.HTML);
234            this.$el = $('#detector');
235        }
236    };
237
238    var handler = {
239        onResizeSetViewportHeight: function(_winHeight) { // set viewport height
240            var _viewportHeight = (_winHeight * 0.01).toFixed(2) + 'px';
241            htmlEl.style.setProperty('--vh', _viewportHeight);
242            UI.base.viewportHeight = _viewportHeight; // set base
243        },
244        onScrollGetScrollDepth: function(_obj) {
245            UI.base.scrollDepth = (function() {
246                var _result = parseInt(_obj.scrollTop / (_obj.scrollHeight - _obj.windowHeight) * 100, 10);
247                return (_result > 100) ? 100 + '%' : _result + '%';
248            })();
249        },
250        getWindowProps: function(_n) {
251            return (_n !== undefined) ? { // is on scroll
252                windowWidth: _n.windowWidth,
253                windowHeight: _n.windowHeight,
254                scrollHeight: _n.scrollHeight,
255                scrollTop: htmlEl.scrollTop
256            } : { // is on resize
257                windowWidth: window.innerWidth || htmlEl.clientWidth,
258                windowHeight: window.innerHeight || htmlEl.clientHeight,
259                scrollHeight: htmlEl.scrollHeight || htmlEl.offsetHeight,
260                scrollTop: htmlEl.scrollTop || window.pageYOffset
261            }
262        },
263        onScroll: function() { // on scroll
264            UI.base.n = this.getWindowProps(UI.base.n); // only on scroll
265            this.onScrollGetScrollDepth(UI.base.n);
266            // console.log('scroll', UI.base);
267        },
268        onResize: function() { // on resize
269            UI.base.n = this.getWindowProps();
270            this.onResizeSetViewportHeight(UI.base.n.windowHeight);
271            htmlEl.setAttribute('data-window-size', `${UI.base.n.windowWidth}x${UI.base.n.windowHeight}`);
272            // console.log('resize', UI.base);
273        }
274    };
275
276    var init = function() {
277        var initSplitting = function() {
278            var target = document.querySelector('#target');
279            var results = Splitting({
280                target: target,
281                by: 'words'
282            });
283        };
284        initSplitting();
285    };
286
287    return {
288        base: {
289            device: (window.orientation !== undefined) ? 'mobile' : 'pc', // window.orientation 은 resize 에 반응하지 않음, 새로고침 필요
290            n: {
291                windowHeight: 0,
292                windowWidth: 0,
293                scrollTop: 0,
294                scrollHeight: 0
295            },
296            scrollDepth: '0%',
297            viewportHeight: '0px',
298            breakpoint: 'sm'
299        },
300        setHandler: function() {
301            var timerResize, timerScroll;
302            window.addEventListener('scroll', function() {
303                if (!timerScroll) { // throttling
304                    timerScroll = setTimeout(function() {
305                        timerScroll = null;
306                        handler.onScroll();
307                    }, opts.throttleDelay);
308                }
309            });
310            window.addEventListener('resize', function() {
311                breakpoint.onResize(); // debouncing 밖에서 실행
312                if (timerResize) clearTimeout(timerResize); // debouncing
313                timerResize = setTimeout(function() {
314                    handler.onResize();
315                }, opts.debounceDelay);
316            });
317            handler.onResize();
318            if (UI.base.n.scrollTop > 0) handler.onScroll(); // 최상단이 아니면 onScroll도 한 번 실행
319        },
320        init: function(params) {
321            opts = { ...SETTINGS, ...params }; // extend
322            htmlEl.setAttribute('data-darkmode', false);
323            htmlEl.setAttribute('data-device', UI.base.device);
324            if (opts.pageName !== null) {
325                document.body.classList.add('pages'); // body class
326                document.body.classList.add(opts.pageName.trim()); // body class
327            }
328            breakpoint.build(); // handler.onResize 밖에 위치하므로 최초 한 번 강제 실행
329            breakpoint.onResize();
330            this.setHandler();
331            init();
332        }
333    };
334})(jQuery);
335
336(function($){
337
338    'use strict';
339
340    var $document = $document || $(document),
341        $window = $window || $(window),
342        $html = $html || $('html'),
343        $body = $('body'); // recache
344
345    function animGraphBar(_el, _bool) {
346        var $el = $(_el);
347        if (!$el.length) return false;
348        $el.each(function () {
349            var $this = $(this),
350                $core = $this.closest('.core'),
351                to = 0,
352                delay;
353            if (_bool) {
354                var ratio = $this.attr('data-bar-ratio') || 1,
355                    delay = $this.attr('data-bar-delay') || 0;
356                to = parseInt(($this.attr('data-bar-to') || 100) * ratio, 10);
357                if (delay !== undefined) {
358                    $this.children().css('transition-delay', delay + 'ms');
359                }
360            } else {
361                $this.children().removeAttr('style');
362            }
363            $this[0].style.setProperty('--bar', to + '%');
364            if ($core.length){
365                $core[0].style.setProperty('--bar', to + '%');
366            }
367            if (to < 30) {
368                $core.attr('data-bar-over30', 'false');
369            } else {
370                $core.removeAttr('data-bar-over30');
371            }
372            setTimeout(function () {
373                $this.toggleClass('in', _bool);
374            }, 1);
375        });
376    }
377
378    function wrapNumbersWithTags(str, _min) {
379        var regex = new RegExp(`\\d{${_min},}`, 'g');
380        var _result = str.replace(regex, function(match) {
381            var _length = match.length;
382            return `<i data-length="${_length}">${match}</i>`;
383        });
384        return _result;
385    }
386
387    function animCountUp(_wrap, _bool) { // anim count up
388		var opts = {
389			duration: 200,
390            delay: 0,
391			minWidth: true // min-width 기능
392		};
393		var $wrap = $(_wrap);
394        if (!$wrap.length) return false;
395        _bool = (_bool === undefined) ? true : _bool;
396        var setDataCountToNum = function(_el){ // data 없으면 text 값으로 설정
397            if (_el.attr('data-count-end') !== undefined) return false;
398            _el.attr('data-count-end', parseFloat(_el.text().replace(/,/g, "")));
399        };
400		var resetWidth = function(_el, _end){
401            if (_el.hasClass('in') !== true && opts.minWidth === true) {
402                var _text = opts.minWidth ? _end.toLocaleString() : '0';
403                _el.text(_text);
404                if (!_el.attr('data-count-width')) {
405                    var _width = Math.ceil(_el.width()) + 3;
406                    _el.css('min-width', _width);
407                    _el.attr('data-count-width', _width);
408                }
409            }
410		};
411        var doAnim = function(_el, _start, _end, _duration, _delay){
412            $({ count: _start }).stop().delay(_delay).animate({
413                count: _end,
414            }, {
415                duration: _duration,
416                easing: 'easeOutCubic',
417                step: function() {
418                    _el.text(Math.floor(this.count).toLocaleString());
419                },
420                complete: function() {
421                    _el.text(this.count.toLocaleString());
422                }
423            });
424        };
425		$wrap.each(function(i){
426            var $that = $(this),
427                $items = null;
428            if (!$that.hasClass('is-init')) {
429                var _min = ($that.attr('data-count-min') || 1) * 1; // 최소 동작 자릿수
430                $that.html(wrapNumbersWithTags($that.text().replace(/,/g, ""), _min)).addClass('is-init');
431            }
432            $items = $that.find('i');
433            for (var i = 0; i < $items.length; i++) {
434                var $this = $items.eq(i),
435                    _end = 0;
436                setDataCountToNum($this); // data 없으면 text 값으로 설정
437                _end = ($this.attr('data-count-end') || 0) * 1;
438                resetWidth($this, _end);
439                $this.text('0').toggleClass('in', _bool);
440                if (_bool === true) {
441                    var _delay = ($that.attr('data-count-delay') || opts.delay) * 1,
442                        _length = ($this.attr('data-length') || _end.toString().length) * 1,
443                        _duration = ($that.attr('data-count-duration') * 1 || opts.duration) * _length,
444                        _start = ($that.attr('data-count-start') || '1' + '0'.repeat(_length - 1)) * 1;
445                    doAnim($this, _start, _end, _duration, _delay);
446                }
447            }
448		});
449    };
450
451    function animInfiniteScroll(_el, options){ // inifinit scroll animation
452        var SETTINGS = {
453            cssvar: '--slider-height',
454            dir: 'vertical',
455            repeatHtml: 4
456        };
457        var opts = { ...SETTINGS, ...options };
458        var $el = $(_el);
459        if (!$el.length) return false;
460        $el.each(function(){
461            var $this = $(this),
462                _var = $this.attr('data-cssvar') || opts.cssvar,
463                _html = $this.html(),
464                _to = $this.attr('data-dir') === 'vertical' || opts.dir ? $this.innerHeight() : $this.innerWidth();
465            _to = -_to + 'px';
466            document.documentElement.style.setProperty(_var, _to);
467    		$this.html(_html.repeat(opts.repeatHtml)).addClass('in');
468    	});
469    };
470
471    var isInview = isInview || function($el, options) { // inview
472        var SETTINGS = {
473            top: 0.25,
474            bottom: 0.25
475        };
476        var opts = { ...SETTINGS, ...options };
477        var _getPercent = function(_int, _percent) {
478            return Math.floor(_int * _percent);
479        };
480        var _el = $el[0],
481            _windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight,
482            _scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop,
483            _scrollBottom = _scrollTop + _windowHeight,
484            _elOffset = _el.getBoundingClientRect(),
485            _elementTop = _elOffset.top + _scrollTop,
486            _elementBottom = _elOffset.bottom + _scrollTop,
487            _marginTop = _getPercent(_windowHeight, opts.top),
488            _marginBottom = _getPercent(_windowHeight, opts.bottom),
489            _boolTop = (_scrollBottom - _marginBottom >= _elementTop),
490            _boolBottom = (_scrollTop + _marginTop <= _elementBottom),
491            _result = (_boolTop && _boolBottom);
492        return _result;
493    };
494
495    var inView2 = function(options) { // inview action
496        var SETTINGS = {
497            el: '.js-inview',
498            className: 'is-inview',
499            classNamePrevious: 'is-inviewed',
500            topMin: 0.2, // 인덱스 2 이하일때 적용
501            bottomMin: 0.2,
502            top: 0.32,
503            bottom: 0.32,
504            onInview: function() {},
505            offInview: function() {}
506        };
507        var opts = { ...SETTINGS, ...options };
508        var view = this;
509        var offsets = [];
510        var timerTrigger = null;
511        var timerRefresh = null;
512
513        function isInview(_el, _windowHeight, _offsetTop, _offsetBottom) { // offsetTop 은 하단에서, offsetBottom 은 상단에서 작동
514            var rect = _el.getBoundingClientRect(),
515                boolTop = (rect.top <= _windowHeight - _offsetTop), // 요소 상단이 화면 밑단 안에 들어오면
516                boolBottom = (rect.bottom >= _offsetBottom); // 요소 하단이 수치 안에 들어오면
517            // return (boolTop && boolBottom);
518            return boolTop; // 스크롤 다운에만 반응
519        }
520
521        view.scrollTop = 0;
522        view.prev = -1;
523        view.dir = 'down';
524
525        var init = function(){
526            view.items = document.querySelectorAll(opts.el);
527            view.length = view.items.length;
528            view.arr = Array(view.length).fill(false); // 배열을 false로 채움
529        };
530        var onScroll = function() {
531            view.scrollTop = window.pageYOffset || document.documentElement.scrollTop;
532            if (view.scrollTop < view.prev) {
533                view.dir = 'up';
534            } else if (view.scrollTop > view.prev) {
535                view.dir = 'down';
536            } else {
537                view.dir = 'equal';
538            }
539            view.prev = view.scrollTop;
540            view.items.forEach(function(_el, j) {
541                var _bool = null,
542                    _offsetTop = (j <= 1) ? view.offsetTopMin : view.offsetTop, // 인덱스 1 이하일 ,
543                    _offsetBottom = (j <= 1) ? view.offsetBottomMin : view.offsetBottom;
544                if (offsets[j] !== null) { //  개별 offset 이 있으면
545                    _offsetTop = offsets[j];
546                    _offsetBottom = offsets[j];
547                }
548                if (view.dir == 'up') {
549                    _bool = isInview(_el, view.windowHeight, 10, _offsetBottom); // scroll up 일때 offsetTop 은 음수
550                } else if (view.dir == 'down'){
551                    _bool = isInview(_el, view.windowHeight, _offsetTop, 10);
552                } else {
553                    _bool = isInview(_el, view.windowHeight, 10, 10);
554                }
555                if (view.arr[j] !== _bool) {
556                    if (_bool === true) {
557                        _el.classList.add(opts.className, opts.classNamePrevious);
558                        if (typeof opts.onInview == 'function') opts.onInview.call(null, j, _el);
559                    } else {
560                        _el.classList.remove(opts.className);
561                        if (typeof opts.onInview == 'function') opts.offInview.call(null, j, _el);
562                    }
563                }
564                view.arr[j] = _bool;
565            });
566        };
567        var onResize = function(){
568            view.windowHeight = window.innerHeight || document.documentElement.clientHeight;
569
570            view.offsetTopMin = Math.round(view.windowHeight * opts.topMin); // 인덱스 1 이하일 때
571            view.offsetBottomMin = Math.round(view.windowHeight * opts.bottomMin);
572            view.offsetTop =  Math.round(view.windowHeight * opts.top); // 벗어낫을때는 음수 offset
573            view.offsetBottom = Math.round(view.windowHeight * opts.bottom);
574
575            view.items.forEach(function(_el, j) { // 개별 offset
576                var _offset = _el.getAttribute('data-inview-offset');
577                offsets[j] = (_offset !== null) ? Math.round(view.windowHeight * _offset) : null;
578            });
579            onScroll();
580        };
581
582        init();
583        onResize();
584
585        window.addEventListener('resize', onResize);
586        window.addEventListener('scroll', onScroll);
587        window.addEventListener('click', onScroll);
588
589        $document.on('click', opts.el, function(e){
590            var $this = $(e.target),
591                _boolFormEl = ($this.is('label') || $this.is('input'));
592            if (_boolFormEl !== true) {
593                clearTimeout(timerTrigger);
594                timerTrigger = setTimeout(function(){
595                    // console.log('scroll');
596                    onScroll();
597                }, 10);
598            }
599        });
600
601        view.refresh = function(){
602            init();
603            onResize();
604        };
605
606        return {
607            refresh: function(_delay){
608                if (_delay !== undefined) {
609                    clearTimeout(timerRefresh);
610                    timerRefresh = setTimeout(function(){
611                        view.refresh();
612                    }, _delay);
613                } else {
614                    view.refresh();
615                }
616            }
617        }
618
619    };
620
621    var animSection = function(_el, _boolOnOff) {
622        if (_boolOnOff === false) {
623            animCountUp(_el + ' .toggle-item.in .js-countup', false); // count up reset
624            animGraphBar(_el + ' .toggle-item.in .js-graph-bar', false);
625            $(_el + ' .toggle-item.anim').removeClass('anim'); // anim
626        } else {
627            animCountUp(_el + ' .toggle-item.not .js-countup', false); // count up
628            animCountUp(_el + ' .toggle-item.in .js-countup', true); // count up
629            animGraphBar(_el + ' .toggle-item.not .js-graph-bar', false);
630            animGraphBar(_el + ' .toggle-item.in .js-graph-bar', true);
631            setTimeout(function(){
632                $(_el + ' .toggle-item.in').addClass('anim');
633            }, 10);
634        }
635    };
636
637    window.animInfiniteScroll = animInfiniteScroll;
638    window.animSection = animSection;
639    window.animCountUp = animCountUp;
640    window.inView2 = inView2;
641
642})(jQuery);
643
644$(function(){
645
646    'use strict';
647
648    var $document = $document || $(document),
649        $window = $window || $(window),
650        $html = $html || $('html'),
651        $body = $('body'); // recache
652
653    /* GA 관련 함수 */
654    function getCleanStr(_str) { // string 정리
655        _str = (_str === undefined) ? '' : _str.trim();
656        _str = _str.replace(/(<([^>]+)>)/gi, ''); // 태그 제거
657        _str = _str.replace(/^\s+|\s+$/g, ''); // 앞뒤 공백 제거
658        _str = _str.replace(/\t/gi, ''); // 탭 제거
659        _str = _str.replace(/\n/gi, ''); // 줄빠꿈 제거
660        _str = _str.replace(/\s{2,}/gi, ' '); // 2칸이상 공백 한칸으로
661        _str = _str.replace('↗', ''); // 새창 아이콘 제거
662        _str = (_str.indexOf('.net/') > -1) ? _str.split('.net')[1] : _str; // 도메인 제거
663        _str = _str.trim();
664        _str = (typeof _str == 'string' && _str.length < 1) ? '_' : _str;
665        return _str;
666    };
667
668    function getAttr($el, _attr) { // 커스텀 데이터에서 값 추출하기
669        var _result = $el.attr(_attr);
670        _result = (_result === undefined) ? '_' : _result;
671        _result = getCleanStr(_result); // string 정리
672        return _result;
673    };
674
675    function _getDataViewItemList($el, _idx) { // ViewItemList 타입 데이터 구하기
676        if (!$el.length) return false;
677        var _result = { // 우선 수집
678            index: _idx * 1,
679            item_id: getAttr($el, 'data-ga4-item-id') * 1,
680            item_list_name: getAttr($el, 'data-ga4-item-list-name'),
681            img_url: '_'
682        };
683        _result.item_name = getAttr($el, 'data-ga4-item-name'); // 값 추출
684        _result.price = getAttr($el, 'data-ga4-price') * 1;
685        _result.original_price = getAttr($el, 'data-ga4-original-price') * 1;
686        _result.item_type = getAttr($el, 'data-ga4-item-type');
687        _result.item_category = getAttr($el, 'data-ga4-item-category');
688        _result.item_category2 = getAttr($el, 'data-ga4-item-category2');
689        _result.item_category3 = getAttr($el, 'data-ga4-item-category3');
690        _result.quantity = 1;
691        return _result;
692    };
693
694    // 요금제 슬라이더
695    var mySwiperPrice = null;
696
697    var initSwiperPrice = function(_el){
698        var $el = $(_el);
699        var boolInview = false;
700        var timerGa = null;
701        if (!$el.length) return false;
702
703        // 복제, swiper11 사용 시 필요함
704        // var $wrapper = $el.find('.swiper-wrapper');
705        // $wrapper.append($wrapper.html().repeat(2));
706
707        var pushedViewItems = []; // 중복 방지
708
709        mySwiperPrice = new Swiper($el[0], {
710            slidesPerView: 3,
711            speed: 800,
712            spaceBetween: 0,
713            centeredSlides: true,
714            watchSlidesVisibility: true,
715            loop: true,
716            autoplay: {
717                disableOnInteraction: false,
718                delay: 2500
719            },
720            on: {
721                touchStart: onSwiperTouchStart,
722                touchEnd: onSwiperTouchEnd,
723                slideChange: function(_this){
724
725                	// GA 관련 기능 시작
726                	clearTimeout(timerGa);
727                	timerGa = setTimeout(function(){
728                    	if (boolInview === true && typeof gtag4 !== 'undefined') {
729
730                        	var arrItems = [];
731                    		var _getElementDataGA = function(_el) {
732                    			var _i = _el.attr('data-idx');
733                    			if (!_el.hasClass('is-ga4-pushed')) {
734                    				var _arr = _getDataViewItemList(_el, _i);
734 // data 가져오기
735                                    var _boolSecond = false; // 중복이면
736                                    pushedViewItems.forEach(function(_item) {
737                                        if (_item == _arr.item_name) {
738                                            _boolSecond = true; // 중복
739                                        }
740                                    });
741                                    if (_boolSecond !== true) { // 중복이 아니면
742                                        pushedViewItems.push(_arr.item_name);
743                                        if (_arr.item_name.indexOf('|') > -1) { // 중복방지를 위해 | 를 포함할 경우 문자열 자름
744                                        	_arr.item_name = _arr.item_name.split('|')[0];
745                                        }
746                                        arrItems.push(_arr);
747                                    }
748                                    _el.addClass('is-ga4-pushed');
749                    			}
750                    		};
751
752                    		var $current = $el.find('.swiper-slide-active').eq(0);
753                        	_getElementDataGA($current);
754                        	_getElementDataGA($current.next());
755                        	_getElementDataGA($current.prev());
756
757                        	if (arrItems.length > 0) {
758                                var _data = {
759                                    event: 'view_item_list',
760                                    ecommerce: {
761                                        currency: 'KRW',
762                                        items: arrItems // 아이템 배열 추가
763                                    }
764                                };
765                        		gtag4.push(_data);
766                        	}
767
768                    	}
769                	}, 2000);
770                	// GA 관련 기능 끝
771
772                }
773            }
774        });
775
776        inView('#swiperPrice').on('enter', function(_el){ // ga 관련 필요 기능
777        	_el.classList.add('inview');
778        	boolInview = true;
779        }).on('exit', function(_el){
780        	_el.classList.remove('inview');
781        	boolInview = false;
782        });
783
784    };
785    initSwiperPrice('#swiperPrice');
786
787
788    // 할인 상품 슬라이더
789    var initSwiperCombineSave = function(_el){
790        var BOOL_LOOP = true; // 루프 조건
791        var $el = $(_el);
792        if (!$el.length) return false;
793        var $slider = $el.find('.slider'),
794            $items = $slider.find('.slider-item'),
795            $tabItems = $el.find('.tab-item');
796        var _visibleLength = BOOL_LOOP ? 3 : 1,
797            _sliderLength = $items.length,
798            _sliderWidth = (470 * _visibleLength) + (20 * _visibleLength),
799            _tabTexts = $tabItems.map(function() {
800                return $(this).text();
801            }).get();
802        var _autoplay = (_sliderLength <= 2) ? false : {
803            disableOnInteraction: false,
804            delay: 2500
805        };
806        $slider.attr('data-length', _sliderLength);
807        if (_sliderLength < 2) { // 1개일 때
808            $items.addClass('swiper-slide-active');
809            $el.attr('data-tab-idx', '0');
810            return false;
811        }
812        var mySwiperCombineSave = new Swiper($slider[0], { // event Larte
813            slidesPerView: _visibleLength,
814            width: _sliderWidth,
815            speed: 1200,
816            spaceBetween: 30,
817            centeredSlides: false,
818            loop: BOOL_LOOP,
819            autoplay: _autoplay,
820            on: {
821                slideChange: function(_this){
822                    $tabItems.eq(_this.realIndex).addClass('in').siblings('.in').removeClass('in');
823                    $el.attr('data-tab-idx', _this.realIndex);
824
825            		if ($slider.hasClass('in-view')){
826        				$(window).trigger('refresh.ga4'); // ui-gtag.js
827            		}
828                },
829            },
830            pagination: {
831              el: '#tabCombineSave',
832              clickable: true,
833              clickableClass: 'reset',
834              horizontalClass: 'reset',
835              bulletClass: 'tab-item',
836              bulletActiveClass: 'in',
837              renderBullet: function (_idx, _className) {
838                  return '<li class="tab-item ' + _className + '"><a href="javascript:;"><span>' + _tabTexts[_idx] +'</span></a></li>';
839              }
840            }
841        });
842        $el.attr('data-tab-idx', 0);
843    };
844    initSwiperCombineSave('#moduleCombineSave');
845});
846
847$(function(){
848
849    'use strict';
850
851    var $document = $document || $(document),
852        $window = $window || $(window),
853        $html = $html || $('html'),
854        $body = $('body'); // recache
855
856    var initBackground = function(_el, _options) { // jumbotron background
857        var settings = {
858            scale: 1,
859            parallax: true,
860            parallaxRatio: 0.1
861        };
862        var $el = $(_el);
863        if (!$el.length) return false;
864        var opts = { ...settings, ..._options };
865        var $window = $(window),
866            $inner = $el.find('.inner'),
867            $items = $el.find('.background-item'),
868            $buttons = $('#mainSimulatorItems .grid-speed input[type="radio"]'),
869            $foreground = $('#mainForeground .item');
870        var setBackgroundImage = function(_el) {
871            var _src = _el.attr('data-background-src');
872            _el.css('background-image', 'url("' + _src + '")');
873        };
874        var setForegroundImage = function(_idx) {
875            var $current = $foreground.eq(_idx);
876            var altText = $current.find('img').attr('alt');
877            $current.addClass('in').siblings().removeClass('in').find('h1').remove();
878            $current.append('<h1 class="sr-only">' + altText + '</h1>');
879        };
880        var toggleItems = function(_idx) {
881            var $current = $items.eq(_idx);
882            setBackgroundImage($current);
883            setForegroundImage(_idx);
884            $current.addClass('in').siblings().removeClass('in anim').addClass('anim');
885        };
886        var doParallax = function() {
887            if (opts.parallax !== true) return false;
888            var _core = function() {
889                var _to = Math.min($window.scrollTop() * opts.parallaxRatio, 100);
890                _to = 0 - _to;
891                $inner.css('transform', 'scale(' + opts.scale + ') translate(0, ' + _to + 'px)');
892            };
893            $inner.addClass('in');
894            $window.on('resize scroll', _core);
895            _core();
896        };
897        $buttons.on('click', function(e) {
898            var _idx = $(e.target).closest('.col').index();
899            toggleItems(_idx);
900        });
901        toggleItems(0);
902        doParallax();
903        if (opts.parallax !== true) { // parallax 아니면 absoltue
904            $el.addClass('pos-absolute');
905        }
906    };
907    
908    if (!$('#mainForeground').length) { // 샵메인이 아닐 경우 호출
909		initBackground('#fixedBackground', { // 샵메인일 경우 구분 호출
910			parallax: true
911		});
912    }
913    
914    window.initBackground = initBackground;
915
916    var initModuleUserReview = function(_el){ // 사용자 리뷰 영역 탭, 목록 토글
917        var opts = {
918            scroll: true
919        };
920        var $el = $(_el);
921        var _scrollTop = 0;
922        var _timerReset = null;
923        if (!$el.length) return false;
924        var collapseList = function(e){
925            e.preventDefault();
926            var $target = $(e.target).closest('.list-item'),
927                $desc = $target.find('.desc'),
928                $summary = $target.find('.summary'),
929                $description = $desc.find('.description');
930            var _height = $summary.outerHeight();
931            var _bool = (!$target.hasClass('in'));
932            $target.toggleClass('in').siblings('.in').removeClass('in').find('.desc').css('height', '50px');
933            _height = (!$target.hasClass('in')) ? _height : $description.outerHeight();
934            $desc.css('height', _height);
935            if (_bool !== true && opts.scroll === true) { // scroll
936                $('html, body').stop().animate({
937                    'scrollTop': _scrollTop
938                }, 300);
939            } else {
940                _scrollTop = $window.scrollTop();
941            }
942        };
943        var activeTab = function(_idx, _isHover){
944            var $tabItems = $el.find('.tab-wrap .tab-item');
945            $tabItems.eq(_idx).addClass('in').siblings('.in').removeClass('in');
946            if (_isHover === true) { // is hover
947                $el.attr('data-tab-idx', _idx);
948            } else {
949                $el.attr('data-current-idx', _idx);
950            }
951        };
952        $document.on('click', _el +' .list-item .anchor', collapseList);
953        $document.on('click', '#moduleUserReviewLinks .tab-item a', function(e){
954            var _idx = $(e.target).closest('.tab-item').index();
955            activeTab(_idx);
956        });
957        $('#moduleUserReviewLinks .tab-item').on('mouseover', function(e){
958            clearTimeout(_timerReset);
959            var _idx = $(e.target).closest('.tab-item').index();
960            activeTab(_idx, true);
961        }).on('mouseleave', function(){
962            _timerReset = setTimeout(function(){
963                var _current = $el.attr('data-current-idx');
964                activeTab(_current, true);
965            }, 500);
966        });
967    };
968    initModuleUserReview('#moduleUserReview');
969
970    var initFaq = function(_el){ // faq toggle item
971        if (!$(_el).length) return false;
972        var _boolInit = ($(_el).attr('data-collapse-init') === 'false') ? false : true; // 펼칠 때 옵션, ajax 영향 장치
973        var toggleFaqItem = function(_idx) {
974            var $this = $(_el + ' .list-item').eq(_idx),
975                $bodyEl = $this.find('.body');
976            var _bool = (!$this.hasClass('in')),
977                _height = (_bool === true && _boolInit === false) ? 'auto' : $this.find('.inner').outerHeight(); //
978            var _collapseSibling = function(_el){
979                var $el = $this.siblings('.in'),
980                    $body = $el.find('.body');
981                $el.removeClass('in');
982                $body.css('height', $body.outerHeight());
983                setTimeout(function(){
984                    $body.css('height', 0);
985                }, 10);
986            };
987            $this.toggleClass('in', _bool);
988            $bodyEl.css('height', _height);
989            if (_bool === true) { // 펼침
990                _collapseSibling($this);
991                setTimeout(function(){
992                    $bodyEl.css('height', 'auto');
993                }, 200);
994            } else { // 접힘
995                setTimeout(function(){
996                    $bodyEl.css('height', 0);
997                }, 1);
998            }
999        };
1000
1001        $document.on('click', _el + ' .head a', function(e){ // faq
1002            var _idx = $(e.target).closest('.list-item').index();
1003            toggleFaqItem(_idx);
1004        });
1005        if (_boolInit === true) {
1006            setTimeout(function(){
1007                toggleFaqItem(0);
1008            }, 100);
1009        }
1010    };
1011    initFaq('#moduleFaqsUpper');
1012    initFaq('#moduleFaqs');
1013
1014    var initCollapse = function(_el){ // 먼저 가입하신 고객님들은 이렇게 사용 중이에요.
1015        var $el = $(_el);
1016        if (!$el.length) return false;
1017        var $items = $(_el + ' .toggle-item');
1018        var _length = $items.length,
1019            _timerCountReset = null,
1020            _timerRepeat = null,
1021            _current = 0,
1022            _isHover = false;
1023        var REPEAT_DELAY = 3000;
1024        var doCollapse = function(_idx){
1025            _current = _idx;
1026            var $current = $items.eq(_idx);
1027            $el.attr('data-idx', _idx);
1028            if (!$current.hasClass('in')) {
1029                $current.addClass('in').removeClass('not').siblings().removeClass('in').addClass('not');
1030                animCountUp(_el + ' .toggle-item.in .js-countup', true); // count up
1031
1032                $window.trigger('refresh.ga4'); // ga4
1033
1034                _timerCountReset = setTimeout(function(){
1035                    animCountUp(_el + ' .toggle-item.not .js-countup', false); // count up
1036                }, 400);
1037            }
1038        };
1039        var _repeat = function(){
1040            clearTimeout(_timerRepeat);
1041            _timerRepeat = setTimeout(function(){
1042                if (!_isHover) {
1043                    _current = (_current + 1) % _length;
1044                    doCollapse(_current);
1045                }
1046                _repeat();
1047            }, REPEAT_DELAY);
1048        };
1049        $el.attr('data-length', _length); // set item length
1050        _repeat();
1051        $document.on('mouseover', _el + ' .module', function(e){
1052            _isHover = true;
1053            doCollapse($(e.target).closest('.toggle-item').index());
1054            clearTimeout(_timerRepeat);
1055        });
1056        $document.on('mouseleave', _el + ' .module', function(e){
1057            _isHover = false;
1058            _repeat();
1059        });
1060        doCollapse(0);
1061    };
1062    initCollapse('#moduleOtherPeople');
1063
1064    // tooltip
1065    var initTooltip = function(){
1066        var $el = $('.pages .help-tooltips');
1067        for (var i = 0; i < $el.length; i++) {
1068            var $this = $el.eq(i);
1069            $this.append('<div class="help-tooltip"><div class="tooltip-inner"><p>' + $this.attr('data-help') || '' + '</p></div></div>');
1070        }
1071    };
1072    initTooltip();
1073
1074    // custom cursor
1075    var setCustomCursor = function(){
1076        var TARGET = '.swiper',
1077            CLASSNAME = 'is-cursor',
1078            HTML = '<div id="customCursor" class="custom-cursor"><span class="cursor"><i class="ico"></i></span></div>';
1079        if (!$(TARGET).length) return false;
1080        var el = document.createElement('div'),
1081            bodyEl = document.body,
1082            containerEl = null,
1083            $container = null;
1084        var _dir = null,
1085            _offset = 0,
1086            _centerX = 0;
1087        var onPointerMove = function(e) {
1088            var target = e.target;
1089            containerEl = e.target.closest(TARGET);
1090            $container = $(containerEl);
1091            _offset = $container.offset();
1092            if (_offset !== undefined) {
1093                _centerX = parseInt(_offset.left + ($container.width() * 0.5), 10);
1094            }
1095            if (containerEl && window.matchMedia('(hover: hover)').matches) {
1096                bodyEl.classList.add(CLASSNAME);
1097                el.style.setProperty('--cursor-x', `${e.clientX}px`);
1098                el.style.setProperty('--cursor-y', `${e.clientY}px`);
1099                if (window.isTouchMove !== true){
1100                    _dir = (e.clientX < _centerX) ? 'next' : 'prev';
1101                }
1102                 document.documentElement.setAttribute('data-cursor-dir', _dir);
1103            } else {
1104                bodyEl.classList.remove(CLASSNAME);
1105            }
1106            if (e.target.closest('.no-custom-cursor')) {
1107                bodyEl.classList.remove(CLASSNAME);
1108            }
1109        };
1110        document.addEventListener('pointermove', onPointerMove);
1111        el.innerHTML = HTML;
1112        bodyEl.append(el);
1113    };
1114    setCustomCursor();
1115
1116    // anchor scroll to
1117    var scrollToSection = function(e){
1118        e.preventDefault();
1119        var $this = $(e.target).closest('a'),
1120            targetID = $this.attr('href').trim(),
1121            $target = $(targetID).eq(0);
1122        if (!$target.length) return false;
1123        var headerHeight = $('#header').height() || $('#dummyHeader').height(),
1124            scrollTo = parseInt($target.offset().top - headerHeight, 10);
1125        window.scrollTo({
1126            top: scrollTo,
1127            behavior: 'smooth'
1128        });
1129    };
1130    $document.on('click', '.js-scroll-to-section', scrollToSection);
1131
1132    var mylistItemInView = new inView2({
1133        el: '.item-inview',
1134        className: 'is-inview',
1135        classNamePrevious: 'is-inviewed',
1136        top: 0.1,
1137        bottom: 0.1,
1138    });
1139
1140    window.mylistItemInView = mylistItemInView;
1141    // window.mylistItemInView.refresh();
1142
1143});

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.