PageSourceSearch

https://rentcar.jejupass.com/pc/js/p_common.js

js jejupass.com collected 2026-10-01 14:16:58 UTC 85,456 bytes, 2,679 lines download raw bytes

1(function($, window) {
2  // project default object !!!
3  var common = {
4    Swiper: null,
5    el: {
6      doc: $(document),
7      win: $(window),
8      body: null
9    },
10    selector: {
11      body: 'body',
12      html: 'html',
13      bh: 'body, html',
14      wrapper: '#wrapper',
15      header: '#wrapper > header',
16      footer: 'footer',
17      swiperWrap: '.swiperWrap',
18      scriptScroll: '.scriptScroll',
19      popupBtn: '.layPopBtn',
20      tab: '[class^="tabType"]',
21      accordion: '.toggleList, #snbList',
22      datepicker: '.multiCalendar',
23      dimmed: '.dimmed',
24      floatingCon: '#filterWrap',
25      slider: '.slider',
26      sortable: '.ui-sortable',
27      tabAhcnor: '#tabAhcnor',
28      tooltip: '.btnTool,aside .btNoti'
29    },
30    setting: {
31      device: null,
32      browser: null
33    },
34    handler: {
35      ready: function() {
36        common.el.body = $(common.selector.body);
37        common.Swiper = window.Swiper;
38
39        const varUA = navigator.userAgent.toLowerCase(); // userAgent 값 얻기
40        let device = null;
41        let browser = null;
42        // 모바일 환경 체크
43        if (varUA.indexOf('android') > -1) {
44          device = 'android';
45        } else if (
46          varUA.indexOf('iphone') > -1 ||
47					varUA.indexOf('ipad') > -1 ||
48					varUA.indexOf('ipod') > -1
49        ) {
50          device = 'ios';
51        } else {
52          device = 'other';
53        }
54        common.setting.device = device;
55        // 브라우저 체크
56        if (varUA.indexOf('chrome') !== -1 || varUA.indexOf('crios') !== -1) {
57          browser = 'Chrome';
58        } else if (varUA.indexOf('opera') !== -1) {
59          browser = 'Opera';
60        } else if (varUA.indexOf('firefox') !== -1) {
61          browser = 'Firefox';
62        } else if (varUA.indexOf('safari') !== -1) {
63          browser = 'Safari';
64        }
65        common.setting.browser = browser;
66
67        // 디자인 스크롤로 인한 추가
68        const oldSelf = $.fn.andSelf || $.fn.addBack;
69        $.fn.andSelf = function() {
70          return oldSelf.apply(this, arguments);
71        };
72
73        // 디자인 스크롤
74        common.el.doc
75          .find(common.selector.scriptScroll)
76          .each(function(idx, el) {
77            myScroll.init(el);
78          });
79
80        // 스와이프
81        common.el.doc.find(common.selector.swiperWrap).each(function(idx, el) {
82          mySwiper.init(el);
83        });
84
85        // 팝업
86        common.el.doc.find(common.selector.popupBtn).each(function(idx, el) {
87          popup.init(el);
88        });
89
90        // 헤더 영역
91        common.el.doc.find(common.selector.header).each(function(idx, el) {
92          header.init(el);
93        });
94
95        // 탭
96        common.el.doc.find(common.selector.tab).each(function(idx, el) {
97          tab.init(el);
98        });
99
100        // 아코디언
101        common.el.doc.find(common.selector.accordion).each(function(idx, el) {
102          accordion.init(el);
103        });
104
105        // 플로팅 컨텐츠
106        common.el.doc
107          .find(common.selector.floatingCon)
108          .each(function(idx, el) {
109            floating.init(el);
110          });
111
112        // 툴팁
113        common.el.doc.find(common.selector.tooltip).each(function(idx, el) {
114          tooltip.init(el);
115        });
116
117        // 빠른정렬 선택
118        common.el.doc.find(common.selector.tabAhcnor).each(function(idx, el) {
119          tabAhcnor.init(el);
120        });
121
122        // 달력
123        common.el.doc.find(common.selector.datepicker).each(function(idx, el) {
124          datepicker.init(el);
125        });
126
127        // 슬라이더
128        common.el.doc.find(common.selector.slider).each(function(idx, el) {
129          slider.init(el);
130        });
131
132        // 정렬
133        common.el.doc.find(common.selector.sortable).each(function(idx, el) {
134          sortable.init(el);
135        });
136
137        // 기타
138        etc.init();
139
140        common.el.win.trigger('scroll');
141        common.el.win.trigger('resize');
142      },
143      load: function() {}
144    }
145  };
146
147  // window ready event
148  // $(document).on('DOMContentLoaded', common.handler.ready);
149  common.el.doc.ready(common.handler.ready);
150
151  // window load event
152  // string: single quotation
153  common.el.win.on('load', common.handler.load);
154  // common.el.win.load(common.handler.load);
155
156  // 유틸
157  const utils = {
158    // 스크롤 비활성화
159    scrollDisabled: function() {
160      const body = common.el.body;
161      body.css({
162        overflow: 'hidden',
163        position: 'fixed',
164        height: '100%',
165        width: '100%',
166        marginTop: parseInt(body.css('margin-top')) || -common.el.win.scrollTop()
167      });
168    },
169    // 스크롤 활성화
170    scrollEnabled: function() {
171      const body = common.el.body;
172      const scrollTop = -parseInt(body.css('margin-top'));
173      body.css({
174        overflow: '',
175        position: '',
176        height: '',
177        width: '',
178        marginTop: ''
179      });
180      common.el.win.scrollTop(scrollTop);
181    },
182    // 딤 show
183    dimmedShow: function() {
184      const dimmed = $(common.selector.dimmed).not(
185        $('.laySearch').find('.dimmed')
186      );
187      let maxIndex = 0;
188      dimmed.css('transition', 'auto');
189      common.el.doc.find('.layPop:visible').each(function() {
190        const $this = $(this);
191        const zIndex = parseInt($this.css('z-index'));
192        maxIndex = maxIndex < zIndex ? zIndex : maxIndex;
193      });
194      if (dimmed.is(':visible')) {
195        dimmed.css('z-index', maxIndex - 1);
196        dimmed.addClass('depth2');
197      } else {
198        dimmed.show().stop().animate({
199          opacity: 1
200        }, 500);
201      }
202    },
203    // 딤 hide
204    dimmedHide: function() {
205      const dimmed = $(common.selector.dimmed).not(
206        $('.laySearch').find('.dimmed')
207      );
208      dimmed.css('transition', 'auto');
209      if (dimmed.hasClass('depth2')) {
210        dimmed.removeClass('depth2').css('z-index', '');
211      } else {
212        dimmed.stop().animate({
213          opacity: 0
214        }, 500, function() {
215          dimmed.hide();
216        });
217      }
218    }
219  };
220
221  // 스와이프
222  var mySwiper = {
223    swiper: null,
224    el: {
225      swiperWrap: null,
226      container: null,
227      wrapper: null,
228      cont: null,
229      prevBtn: null,
230      nextBtn: null,
231      pagination: null,
232      paging: null
233    },
234    methodes: {
235      init: function() {
236        // 기본 옵션
237        const options = {
238          allowTouchMove: true,
239          loop: false,
240          autoplay: false,
241          spaceBetween: 0,
242          navigation: false,
243          pagination: false,
244          observer: true,
245          direction: 'horizontal',
246          freeMode: false,
247          centeredSlides: false,
248          slidesPerView: 1,
249          effect: 'slide',
250          on: {},
251          lazy: {
252            loadPrevNext: true,
253          }
254        };
255        const optionData = mySwiper.el.swiperWrap.data('options') || {};
256        const container = mySwiper.el.container;
257        const pagination = mySwiper.el.pagination;
258        let defaultPaging = '';
259
260        // 내부 스와이퍼
261        if (mySwiper.el.swiperWrap.hasClass('innerSwiper')) {
262          options.nested = true;
263        }
264
265        pagination.find('.swiperMore').each(function() {
266          const $this = $(this);
267          defaultPaging += $this[0].outerHTML;
268          $this.remove();
269        });
270
271        // 터치 이동 허용/불가
272        if (optionData.touchMove) {
273          options.allowTouchMove = optionData.touchMove;
274
275          if (optionData.touchMove === 'false') {
276            options.allowTouchMove = false;
277          }
278        }
279
280        // 루프
281        if (optionData.loop) {
282          options.loop = true;
283        }
284
285        // 간격
286        if (optionData.Spacebetween > 0) {
287          options.spaceBetween = optionData.Spacebetween;
288        }
289
290        // 오토플레이
291        if (optionData.autoplay > 0) {
292          options.autoplay = {
293            delay: optionData.autoplay,
294            disableOnInteraction: false
295          };
296
297          // 마우스 오버 시 오토 멈춤
298          container
299            .closest('.swiperWrap')
300            .off('mouseenter mouseleave')
301            .on('mouseenter mouseleave', function(e) {
302              const data = container.data('swiper');
303              if (e.type === 'mouseenter') {
304                data.autoplay.stop();
305              } else {
306                const playBtn = pagination.find('.btPlay');
307
308                if (playBtn.is(':visible')) {
309                  return false;
310                }
311                data.autoplay.start();
312              }
313            });
314
315          pagination
316            .find('.btAutoplays')
317            .children()
318            .each(function() {
319              const $this = $(this);
320              $this.off('click').on('click', function() {
321                const $this = $(this);
322                const data = container.data('swiper');
323                $this.hide().siblings('button').show();
324                if ($this.hasClass('btStop')) {
325                  data.autoplay.stop();
326                } else {
327                  data.autoplay.start();
328                }
329              });
330            });
331        }
332
333        // 버튼
334        if (mySwiper.el.prevBtn.length > 0) {
335          options.navigation = {
336            nextEl: container.next('.swiper-button-next')[0],
337            prevEl: container.prev('.swiper-button-prev')[0]
338          };
339        }
340
341        // 페이지네이션
342        if (optionData.pagination === 'all') {
343          // 두 타입 모두
344          options.pagination = {
345            el: pagination,
346            type: 'custom',
347            renderCustom: function(swiper, current, total) {
348              // 기호
349              if (this.el.find('.tyBl').length === 0) {
350                this.el.prepend('<span class="tyBl"></span>');
351              }
352              let bl = '';
353              for (let i = 1; i <= total; i++) {
354                if (current === i) {
355                  bl +=
356										'<span class="swiper-pagination-bullet swiper-pagination-bullet-active"></span>';
357                } else {
358                  bl += '<span class="swiper-pagination-bullet"></span>';
359                }
360              }
361              this.el.find('.tyBl').html(bl);
362
363              // 숫자
364              if (this.el.find('.tyNum').length === 0) {
365                this.el.append('<div class="tyNum"></div>');
366              }
367              let num =
368								'<div class="swiper-paging"><div class="paging"><span class="swiper-pagination-current">' +
369								current +
370								'</span>/<span class="swiper-pagination-total">
370' +
371								total;
372
373              if (defaultPaging !== '') {
374                num += '</span></div>' + defaultPaging + '</div>';
375              }
376              num += '</span></div>';
377              this.el.find('.tyNum').html(num);
378
379							
380            }
381          };
382        } else if (optionData.pagination === 'fraction') {
383          // 숫자
384          options.pagination = {
385            el: pagination,
386            type: 'custom',
387            renderCustom: function(swiper, current, total) {
388              if (this.el.find('.tyNum').length === 0) {
389                this.el.append('<div class="tyNum"></div>');
390              }
391
392              let num =
393								'<div class="swiper-paging"><div class="paging"><span class="swiper-pagination-current">' +
394								current +
395								'</span>/<span class="swiper-pagination-total">' +
396								total;
397
398              if (defaultPaging !== '') {
399                num += '</span></div>' + defaultPaging + '</div>';
400              }
401              num += '</span></div>';
402              this.el.find('.tyNum').html(num);
403							
404            }
405          };
406        } else if (pagination.length > 0) {
407          // 기호
408          options.pagination = {
409            el: pagination,
410            type: 'custom',
411            renderCustom: function(swiper, current, total) {
412              // 기호
413              if (this.el.find('.tyBl').length === 0) {
414                this.el.prepend('<span class="tyBl"></span>');
415              }
416              let bl = '';
417              for (let i = 1; i <= total; i++) {
418                if (current === i) {
419                  bl +=
420										'<span class="swiper-pagination-bullet swiper-pagination-bullet-active"></span>';
421                } else {
422                  bl += '<span class="swiper-pagination-bullet"></span>';
423                }
424              }
425              this.el.find('.tyBl').html(bl);
426							
427            }
428          };
429        }
430
431        // 몇개씩 보일지
432        if (optionData.view !== undefined) {
433          options.slidesPerView = optionData.view;
434        }
435        // 몇개씩 움직일지
436        if (optionData.group > 0) {
437          options.slidesPerGroup = optionData.group;
438          const slidesLength = mySwiper.el.container[0].children[0].children.length;
439
440          if (optionData.group > slidesLength) {
441            options.loop = false;
442          }
443        }
444        // 가로,세로 방향
445        if (optionData.vertical) {
446          options.direction = 'vertical';
447        }
448
449        // 모드(이펙트)
450        if (optionData.mode) {
451          options.effect = optionData.mode;
452        }
453
454        // 유사 스크롤 모드
455        if (optionData.free) {
456          options.freeMode = {
457            enabled: optionData.free,
458            momentumRatio: 0.2,
459            sticky: true
460          };
461          // 스냅 활성화
462          if (optionData.freeSticky) {
463            options.freeMode.sticky = optionData.freeSticky;
464          }
465        }
466
467        if (optionData.centeredSlides) {
468          options.centeredSlides = true;
469        }
470
471        // 섬네일
472        if (mySwiper.el.swiperWrap.hasClass('swiperThumb')) {
473          options.watchSlidesProgress = true;
474          options.freeMode = true;
475        }
476
477        if (container.data('swiper') !== undefined) {
478          container.data('swiper').destroy();
479        }
480        const swiper = new common.Swiper(container, options);
481        container.data('swiper', swiper);
482
483        if (optionData.destroy) {
484          container.data('swiper').destroy();
485          container.next('.swiper-button-next')[0].style.display = "none";
486          container.prev('.swiper-button-prev')[0].style.display = "none";
487        }
488
489        // 섬네일 연동 스와이프
490        if (mySwiper.el.swiperWrap.hasClass('swiperThumb')) {
491          const wrap = mySwiper.el.swiperWrap;
492          const nextCon = wrap
493            .prev()
494            .children('.swiper-container')
495            .data('swiper');
496          nextCon.thumbs.swiper = swiper;
497          nextCon.thumbs.init();
498          nextCon.thumbs.update(0);
499        }
500
501        // if (container.closest('.themeViewArea').length) {
502        //   swiper.allowTouchMove = false;
503        // }
504      },
505      swiperUpdate: function(target) {
506        target.find('.swiper-container').each(function() {
507          const $this = $(this);
508          const sData = $this.data('swiper');
509          if (sData != undefined) {
510            sData.update();
511          }
512        });
513      },
514      tabScrollSwiper: function(target) {
515        if (target.data('swiper') !== undefined) {
516          target.data('swiper').update();
517        }
518        target.closest('.tabScript').each(function() {
519          if (!$('.viewContArea').hasClass('jprentcarViewContArea') && !$(this).closest('.tabAllCont.tabFixedCont').length) { // jprentcar 상세 제외
520            const $this = $(this);
521            $this.find('>ul>li').addClass('swiper-slide');
522            const mySwiper = new Swiper($this, {
523              wrapperClass: $this.children('ul')[0].classList[0],
524              slidesPerView: 'auto',
525              freeMode: {
526                enabled: true
527              },
528              allowTouchMove: true,
529              CenteredSlidesBounds: true,
530              SlideToClickedSlide: true,
531              // spaceBetween        : 8,
532              observer: true,
533              observeParents: true,
534              on: {
535                setTranslate: tab.handler.scroll,
536                // init: function() {
537                // 	var swiper = this;
538                //     swiper.update();
539                // }
540              }
541            });
542            target.data('swiper', mySwiper);
543          }
544        });
545      }
546    },
547    handler: {},
548    setProperty: function(el) {
549      this.el.swiperWrap = el;
550      this.el.container = el.children('.swiper-container');
551      this.el.wrapper = this.el.container.children('.swiper-wrapper');
552      this.el.cont = this.el.wrapper.children('.swiper-slide');
553      this.el.prevBtn = this.el.container.siblings('.swiper-button-prev');
554      this.el.nextBtn = this.el.container.siblings('.swiper-button-next');
555      this.el.pagination = this.el.container.siblings('.swiper-pagination');
556      this.el.paging = this.el.container.siblings('.swiper-paging');
557
558      this.methodes.init();
559    },
560    bind: function() {},
561    init: function(el) {
562      this.setProperty($(el));
563    }
564  };
565
566  // 디자인 스크롤
567  var myScroll = {
568    el: {
569      target: null
570    },
571    selector: {},
572    methodes: {
573      init: function(target) {
574        const el = target || myScroll.el.target;
575        const classList = el.attr('class').split(' ');
576        el.scrollbar({
577          onInit: function(con) {
578            classList.forEach(function(val) {
579              con.removeClass(val);
580            });
581
582            if (con.closest('#filterWrap').length > 0) {
583              con.closest('.scriptScroll').css('height', '100%');
584            }
585          }
586        });
587        el.css('overflow', 'hidden');
588      },
589      destroy: function(target) {
590        const child = target.children();
591        target.children().scrollbar('destroy');
592        child.closest('div').addClass('scriptScroll').css('height', '100%');
593      }
594    },
595    handler: {},
596    setProperty: function(el) {
597      this.el.target = el;
598    },
599    bind: function() {},
600    init: function(el) {
601      this.setProperty($(el));
602      this.methodes.init();
603      this.bind();
604    }
605  };
606
607  // 팝업
608  var popup = {
609    el: {
610      popup: null,
611      popBtn: null,
612      layContainer: null
613    },
614    selector: {
615      closeBtn: '.closeL'
616    },
617    methodes: {
618      // 팝업 show
619      show: function(target) {
620        // 팝업 다중 노출 시 z-index 처리
621        if (common.el.doc.find('.layPop:visible').length > 0) {
622          let maxIndex = 0;
623          common.el.doc.find('.layPop:visible').each(function() {
624            const $this = $(this);
625            const zIndex = parseInt($this.css('z-index'));
626            maxIndex = maxIndex < zIndex ? zIndex : maxIndex;
627          });
628          target.css('z-index', maxIndex + 1);
629        }
630
631        target.show();
632        // 지도 left 팝업
633        if (target.hasClass('layerMapList')) {
634          target.stop().animate({
635            left: 0
636          });
637          target
638            .find('.closeL')
639            .off('click')
640            .on('click', function() {
641              popup.methodes.hide(target);
642            });
643        }
644
645        // 스와이프 초기화
646        mySwiper.methodes.swiperUpdate(target);
647
648        // 딤 예외 처리
649        if (!target.hasClass('layerMap') && !target.hasClass('layerMapList')) {
650          mvJs.utils.dimmedShow();
651        }
652
653        utils.scrollDisabled();
654
655        target
656          .find('.scroll-content')
657          .off('scroll.popup')
658          .on('scroll.popup', popup.handler.scroll);
659      },
660      // 팝업 hide
661      hide: function(target) {
662        if (target.hasClass('layerMap')) {
663          // 지도 팝업
664          const mapLeft = common.el.doc.find('.layerMapList');
665          if (mapLeft.is(':visible')) {
666            mapLeft.css('left', -mapLeft.width());
667            mapLeft.hide();
668          }
669          target.hide();
670        } else if (target.hasClass('layerMapList')) {
671          // 지도 left 팝업
672          target.stop().animate({
673            left: -target.width()
674          }, function() {
675            target.hide();
676            target.find('.closeL').off('click');
677          });
678        } else if (target.hasClass('layCent')) {
679          // 가운데 정렬 팝업
680          target.hide();
681        } else {
682          // 외 경우 (풀팝업)
683          target.hide();
684        }
685        mvJs.utils.dimmedHide();
686        utils.scrollEnabled();
687      }
688    },
689    handler: {
690      show: function() {
691        const $this = $(this);
692        const popLayer = $('#' + $this.data('id'));
693
694        popup.methodes.show(popLayer);
695      },
696      hide: function() {
697        const $this = $(this);
698        const popLayer = $this.closest('.layPop');
699
700        popup.methodes.hide(popLayer);
701      },
702      resize: function() {},
703      scroll: function() {
704        const $this = $(this);
705        const laypop = $this.closest('.layPop');
706        const scrollTop = $this.scrollTop();
707        // 팝업 내부 스크롤 시 class on/off
708        // if (scrollTop === 0 && laypop.hasClass('layScroll')) {
709        //   laypop.removeClass('layScroll');
710        // }
711        // if (scrollTop > 0 && !laypop.hasClass('layScroll')) {
712        //   laypop.addClass('layScroll');
713        // }
714
715        // 앵커 탭 대응
716        const anchor = $this.find('.anchorTabFixed');
717        if (anchor.length > 0) {
718          const anchorScroll = scrollTop + anchor.height();
719
720          anchor.find('ul>li>a').each(function(idx) {
721            const $this = $(this);
722            const target = $('#' + $this.data('controls'));
723            const top = target.position().top + scrollTop;
724            const nextArea = target.nextAll('div[class*=anchorTab]').eq(0);
725            let nextTop;
726            if (nextArea.length) {
727              nextTop = nextArea.position().top + scrollTop;
728            }
729
730            if (nextArea.length === 0) {
731              if (
732                top <=
733								anchorScroll + laypop.find('.scriptScroll').height() / 3
734              ) {
735                anchor.find('>ul>li>a').attr('aria-selected', 'false');
736                $this.attr('aria-selected', 'true');
737              } else {
738                $this.attr('aria-selected', 'false');
739              }
740            } else if (idx === 0 && top > anchorScroll) {
741              $this.attr('aria-selected', 'true');
742            } else if (top <= anchorScroll && anchorScroll < nextTop) {
743              $this.attr('aria-selected', 'true');
744            } else {
745              $this.attr('aria-selected', 'false');
746            }
747          });
748        }
749      }
750    },
751    setProperty: function(el) {
752      this.el.popBtn = el;
753      this.el.popup = $('#' + el.data('id'));
754      this.el.layCont = this.el.popup.find('.layContainer');
755    },
756    bind: function() {
757      this.el.popBtn.off('click.popup').on('click.popup', popup.handler.show);
758      this.el.popup
759        .find(this.selector.closeBtn)
760        .off('click.popup')
761        .on('click.popup', popup.handler.hide);
762
763      this.el.layCont
764        .find('.scroll-content')
765        .off('scroll.popup')
766        .on('scroll.popup', popup.handler.scroll);
767
768      // 퍼블 확인 용
769      // $('.viewListWrap .btView')
770      //   .off('click')
771      //   .on('click', function() {
772      //     popup.methodes.show($('.layerMapList'));
773      //   });
774    },
775    init: function(el) {
776      this.setProperty($(el));
777      this.bind();
778    }
779  };
780
781  // 헤더 영역 기능
782  var header = {
783    el: {
784      header: null,
785      search: null,
786      laySearch: null,
787      searchDim: null,
788      searchBtns: null
789    },
790    selector: {
791      mainTopbanner: '.mainTopbanner'
792    },
793    methodes: {
794      // navContral: function(idx, speed) {
795      //   var navList = header.el.navList;
796      //   var navListW = navList.outerWidth();
797      //   var navCon = header.el.navCon;
798      //   var target = header.el.navCon.eq(idx);
799      //   var targetLeft = target.position().left;
800      //   var navW = parseInt(navList.css('padding-left')) * 2;
801      //   var scrollLeft = navList.scrollLeft();
802      //   var aniSpeed = speed || 250;
803      //   var moveVal =
804      //     targetLeft + scrollLeft - parseInt(navList.css('padding-left'));
805      //   navCon.each(function() {
806      //     var $this = $(this);
807      //     navW += $this.width();
808      //   });
809      //   if (moveVal + navListW > navW) {
810      //     moveVal = navW - navListW;
811      //   }
812      //   header.el.navCon.removeClass('navON').eq(idx).addClass('navON');
813      //   navList.stop().animate(
814      //     {
815      //       scrollLeft: moveVal
816      //     },
817      //     aniSpeed
818      //   );
819      // }
820      searchMenuOpen: function(target) {
821        const targetId = target.attr('aria-controls');
822        const cont = common.el.doc.find('#' + targetId);
823        target.attr('aria-selected', true);
824        target
825          .closest('li')
826          .siblings('li')
827          .children('a')
828          .attr('aria-selected', false);
829        cont
830          .addClass('sectionON')
831          .siblings('.k1_section_multi')
832          .removeClass('sectionON');
833        mySwiper.methodes.swiperUpdate(cont);
834      }
835    },
836    handler: {
837      searchMenuToggle: function(e) {
838        e.preventDefault();
839        const $this = $(this);
840        header.methodes.searchMenuOpen($this);
841      },
842      searchToggle: function() {
843        const lay = header.el.laySearch;
844        const dim = header.el.searchDim;
845        const section = $(common.selector.wrapper);
846        if (lay.is(':animated')) {
847          return false;
848        }
849        if (lay.is(':visible')) {
850          lay.slideUp(function() {
851            section.removeClass('quickWrapper');
852          });
853          dim.css('opacity', 0);
854          mvJs.utils.scrollEnabled();
855        } else {
856          section.addClass('quickWrapper');
857          lay.slideDown();
858          dim.css('opacity', 1);
859          mySwiper.methodes.swiperUpdate(lay);
860          mvJs.utils.scrollDisabled();
861        }
862      },
863      searchClose: function() {
864        header.handler.searchToggle();
865      },
866      topBannerClose: function() {
867        const $this = $(this);
868        const topBanner = $this.closest('.mainTopbanner');
869        // topBanner.slideUp(function() {
870        //   topBanner.remove();
871        // });
872        topBanner.animate({
873          marginTop: -topBanner.height()
874        }, 200, function() {
875          topBanner.remove();
876        });
877      },
878      scroll: function() {
879        const head = header.el.header;
880        const scrollTop = common.el.win.scrollTop();
881        let headerH = head.height();
882        const fixedWrap = head.children('.fixedWrap');
883        const wrap = head.closest('#wrapper');
884        const mainTopbanner = $(header.selector.mainTopbanner);
885
886        if (mainTopbanner.length > 0) {
887          headerH += mainTopbanner.height();
888        }
889
890        if ($(common.selector.body).css('overflow') !== 'hidden') {
891          if (scrollTop === 0 && wrap.hasClass('headFixed')) {
892            wrap.removeClass('headFixed');
893          }
894          if (scrollTop > headerH && !wrap.hasClass('headFixed')) {
895            wrap.addClass('headFixed');
896          }
897        }
898      }
899    },
900    setProperty: function(el) {
901      this.el.header = el;
902      this.el.search = el.find('.btSearch');
903      this.el.searchNoDataBtn = el.siblings('#container').find('.sch_result .noData .btSearch');
904      this.el.laySearch = el.find('.laySearch');
905      this.el.searchDim = this.el.laySearch.find('.dimmed');
906      this.el.searchClose = this.el.laySearch.find('.closeL');
907      this.el.searchBtns = common.el.doc.find('.searchBtns');
908    },
909    bind: function() {
910      const mainTopbanner = $(header.selector.mainTopbanner);
911      common.el.win
912        .off('scroll.header')
913        .on('scroll.header', header.handler.scroll);
914
915      this.el.search
916        .off('click.header')
917        .on('click.header', header.handler.searchToggle);
918      this.el.searchNoDataBtn
919        .off('click.header')
920        .on('click.header', header.handler.searchToggle);
921      this.el.searchClose
922        .off('click.header')
923        .on('click.header', header.handler.searchClose);
924      this.el.searchBtns.find('>li>a').each(function() {
925        $(this)
926          .off('click.header')
927          .on('click.header', header.handler.searchMenuToggle);
928      });
929
930      if (mainTopbanner.length > 0) {
931        mainTopbanner
932          .children('.btn_close')
933          .off('click.header')
934          .on('click.header', header.handler.topBannerClose);
935      }
936    },
937    init: function(el) {
938      this.setProperty($(el));
939      this.bind();
940    }
941  };
942
943  // 탭기능
944  var tab = {
945    el: {
946      tabWrap: null,
947      tab: null,
948      tabCon: null
949    },
950    selector: {},
951    methodes: {
952      tabOn: function(target, speed) {
953        const tabScript = target.closest('.tabScript');
954        const wrap = target.closest('ul');
955        const targetA = target.children('a');
956        const tabConData = targetA.data('controls');
957        if (targetA.attr('aria-selected') === 'true') {
958          return true;
959        }
960
961        // 앵커 타입일 때 미동작
962        if (!tabScript.hasClass('anchorTabFixed')) {
963          targetA.attr('aria-selected', 'true');
964          if (!tabScript.hasClass('listTap')) {
965            target.siblings('li').children('a').attr('aria-selected', 'false');
966          }
967        }
968
969        if (tabConData !== undefined) {
970          const con = common.el.doc.find('#' + tabConData);
971          // 앵커 타입
972          if (tabScript.hasClass('anchorTabFixed')) {
973            let fixedH = wrap.height();
974            $('#wrapper header').each(function() {
975              fixedH += $(this).height();
976            });
977            if (con.closest('.scriptScroll').length > 0) {
978              // 팝업 내부
979              con
980                .closest('.scroll-content')
981                .stop()
982                .animate({
983                  scrollTop: con.position().top -
984											tabScript.height() +
985											con.closest('.scroll-content').scrollTop() +
986											20
987                },
988                500
989                );
990            } else {
991              if (!$('#wrapper').hasClass('headFixed')) {
992                fixedH -= 32;
993              }
994
995              $(common.selector.bh)
996                .stop()
997                .animate({
998                  scrollTop: con.offset().top - fixedH
999                },
1000                500
1001                );
1002            }
1003          } else {
1004            con
1005              .addClass('tabON')
1006              .siblings('.tabContentWrap')
1007              .removeClass('tabON');
1008
1009            common.el.win.trigger('scroll');
1010
1011            // 스와이프 업데이트
1012            mySwiper.methodes.swiperUpdate(con);
1013
1014            // 리뷰 리스트 업데이트
1015            con.find('.reviewList').each(function() {
1016              const $this = $(this);
1017              // $this.find('>li>.txt').css({
1018              //   textOverflow        : '',
1019              //   '-webkit-box-orient': ''
1020              // });
1021              etc.methodes.reviewMoreBtn($this);
1022            });
1023          }
1024        }
1025
1026        tabScript.each(function() {
1027          const $this = $(this);
1028          const sData = wrap.data('swiper');
1029
1030          if (sData !== {}) {
1031            const aniSpeed = speed === undefined ? 200 : speed;
1032            tab.methodes.tabScrollMove(wrap, target, aniSpeed);
1033          }
1034        });
1035        wrap.find('[class^="tabType"]').trigger('scroll');
1036      },
1037      tabScrollMove: function(wrap, target, speed) {
1038        if (!wrap.closest('.tabAllCont.tabFixedCont').length) {
1039          const sData = wrap.data('swiper');
1040          const wrapW = wrap.outerWidth(true);
1041          const wrapInnerW = tab.methodes.tabInnerWidth(wrap) - wrapW;
1042          const targetLeft = target.position().left;
1043          if (!$('.viewContArea').hasClass('jprentcarViewContArea')) { // jprentcar 상세 제외
1044            const scrollLeft = -sData.translate;
1045          }
1046          let moveVal =
1047                        targetLeft /* + scrollLeft */ - wrapW / 2 + target.width() / 2;
1048          if (moveVal < 0) {
1049            moveVal = 0;
1050          }
1051
1052          if (moveVal > wrapInnerW) {
1053            moveVal = wrapInnerW;
1054          }
1055
1056          if (!$('.viewContArea').hasClass('jprentcarViewContArea')) { // jprentcar 상세 제외
1057            sData.translateTo(-moveVal, speed);
1058          }
1059        }
1060      },
1061      tabInnerWidth: function(wrap) {
1062        let innerW = 0;
1063        wrap.children('li').each(function() {
1064          const $this = $(this);
1065          innerW += $this.outerWidth(true);
1066        });
1067        return innerW;
1068      }
1069    },
1070    handler: {
1071      click: function(e) {
1072        // 탭 클릭 시
1073        const $this = $(this);
1074        if ($this.children('a').attr('href') === '#') {
1075          e.preventDefault();
1076        }
1077        tab.methodes.tabOn($this);
1078      },
1079      scroll: function() {
1080        // 탭 가로 스크롤 시
1081        const $this = $(this.el);
1082        const wrap = $this.children('ul');
1083        const wrapW = $this.children('ul').outerWidth(true) + 10;
1084        const scrollLeft = -this.translate;
1085        const nextBtn = $this.children('.next');
1086        const prevBtn = $this.children('.prev');
1087        const idx = wrap.find('a[aria-selected=true]').closest('li').index();
1088
1089        if (nextBtn.length > 0) {
1090          if (scrollLeft < tab.methodes.tabInnerWidth(wrap) - wrapW) {
1091            nextBtn.show();
1092          } else {
1093            nextBtn.hide();
1094          }
1095
1096          if (scrollLeft > 0) {
1097            prevBtn.show();
1098          } else {
1099            prevBtn.hide();
1100          }
1101        }
1102      },
1103      resize: function() {
1104        $(common.selector.tab).each(function() {
1105          const $this = $(this);
1106          $this.trigger('scroll.tab');
1107        });
1108      },
1109      moveBtn: function() {
1110        // prev next 버튼
1111        const $this = $(this);
1112        const wrap = $this.siblings('ul');
1113        const sData = wrap.data('swiper');
1114        wrap.children('li').each(function() {
1115          const cont = $(this);
1116          const viewSize = wrap.width() + -sData.getTranslate();
1117          const targetSize = cont.position().left + cont.outerWidth(true);
1118
1119          if ($this.hasClass('next')) {
1120            if (viewSize < targetSize) {
1121              sData.translateTo(wrap.width() - targetSize - $this.width(), 200);
1122              return false;
1123            }
1124          } else {
1125            if (-sData.getTranslate() < targetSize) {
1126              sData.translateTo(-cont.position().left + $this.width(), 200);
1127              return false;
1128            }
1129          }
1130        });
1131      },
1132      winScroll: function() {
1133        // 윈도우 스크롤 시
1134        const doc = common.el.doc;
1135        const scrollTop = common.el.win.scrollTop();
1136        const viewTab = doc.find(
1137          '.viewTab > .tabWrap.tabScript, .viewTab > .tabBasics '
1138        );
1139        const header = doc.find('#wrapper>header');
1140        const headScrollTop = 0;
1141        // if (header.length > 0) {
1142        //   headScrollTop = scrollTop + header.height();
1143        // }
1144
1145        // if (common.el.doc.find('.tripSelect>.inner').length > 0) {
1146        //   headScrollTop += common.el.doc
1147        //     .find('.tripSelect>.inner')
1148        //     .outerHeight();
1149        // }
1150
1151        // if (viewTab.length > 0) {
1152        //   if (
1153        //     viewTab.offset().top <= headScrollTop &&
1154        //     !viewTab.hasClass('fixed')
1155        //   ) {
1156        //     viewTab.addClass('fixed');
1157        //   } else if (
1158        //     viewTab.offset().top > headScrollTop &&
1159        //     viewTab.hasClass('fixed')
1160        //   ) {
1161        //     viewTab.removeClass(['fixed', 'tabScroll']);
1162        //   }
1163        // }
1164
1165        // var fixedTab = doc.find('.tabScript.fixed');
1166        // fixedTab.each(function() {
1167        //   var $this = $(this);
1168        //   if (scrollTop === 0 && $this.hasClass('tabScroll')) {
1169        //     $this.removeClass('tabScroll');
1170        //   }
1171        //   if (scrollTop > 0 && !$this.hasClass('tabScroll')) {
1172        //     $this.addClass('tabScroll');
1173        //   }
1174        // });
1175
1176        // jprentcar 앵커 탭 기능 대응 (상세페이지 앵커 탭 기능 대응)
1177        if ($('.viewContArea').hasClass('jprentcarViewContArea') || $('.tabAllCont').hasClass('tabFixedCont')) {
1178          const anchor = doc.find('.anchorTabFixed');
1179          if (anchor.length > 0) {
1180            let anchorScroll = scrollTop + 57;
1181            $('#wrapper header').each(function() {
1182              anchorScroll += $(this).height();
1183            });
1184            anchor.find('.tabType01 li>a').each(function(idx) {
1185              const $this = $(this);
1186              const target = $('#' + $this.data('controls'));
1187              const top = target.offset().top;
1188              const nextArea = target.nextAll('div[class*=anchorTab]').eq(0);
1189              let nextTop;
1190              if (nextArea.length) {
1191                nextTop = nextArea.offset().top;
1192              } else {
1193                if ($this.closest('#container').length) {
1194                  nextTop =
1195                                        $this.closest('#container').offset().top +
1196                                        $this.closest('#container').outerHeight();
1197                }
1198              }
1199
1200              if (idx === 0 && top > anchorScroll) {
1201                $this.attr('aria-selected', 'true');
1202              } else if (top <= anchorScroll && anchorScroll < nextTop) {
1203                $this.parent().siblings().children().attr('aria-selected', 'false');
1204                $this.attr('aria-selected', 'true');
1205              } else {
1206                $this.attr('aria-selected', 'false');
1207              }
1208            });
1209          }
1210        }
1211      }
1212    },
1213    setProperty: function(el) {
1214      this.el.tabWrap = el;
1215      this.el.tab = el.children('li');
1216      this.el.btn = this.el.tabWrap.siblings('button');
1217    },
1218    bind: function() {
1219      this.el.tab.off('click.tab').on('click.tab', tab.handler.click);
1220      // this.el.tabWrap.off('scroll.tab').on('scroll.tab', tab.handler.scroll);
1221
1222      this.el.btn.each(function() {
1223        const $this = $(this);
1224        $this.off('click.tab').on('click.tab', tab.handler.moveBtn);
1225      });
1226
1227      mySwiper.methodes.tabScrollSwiper(this.el.tabWrap);
1228      common.el.win.off('resize.tab').on('resize.tab', tab.handler.resize);
1229      common.el.win.off('scroll.tab').on('scroll.tab', tab.handler.winScroll);
1230    },
1231    init: function(el) {
1232      this.setProperty($(el));
1233      this.bind();
1234    }
1235  };
1236
1237  // 아코디언
1238  var accordion = {
1239    el: {
1240      wrap: null
1241    },
1242    selector: {},
1243    methodes: {
1244      show: function(target, speed) {
1245        if (target.is(':animated')) {
1246          return false;
1247        }
1248        // if (target.hasClass('toggleCont')) {
1249        // 마이페이지 좌즉에 붙는 타입
1250        const aniSpeed = speed || 300;
1251        let btn = target.prev('.toggleBtn');
1252        if (target.hasClass('snbListDep2')) {
1253          btn = target.prev('.snbDep1');
1254          btn.attr('aria-selected', 'true');
1255        }
1256        btn.attr('aria-expanded', 'true');
1257
1258        // 필터 예외
1259        const filterWrap = target.closest('#filterWrap');
1260        if (filterWrap.length > 0) {
1261          filterWrap.find('.filterSelectWrap').each(function() {
1262            const $this = $(this);
1263            $this.find('.scroll-content').data('scrollbar').init();
1264          });
1265          return false;
1266        }
1267
1268        target.hide().slideDown(aniSpeed);
1269        // 마이페이지 좌즉에 붙는 타입은 하나만 열리게 처리
1270        if (target.hasClass('snbListDep2')) {
1271          target
1272            .closest('li')
1273            .siblings('li')
1274            .children('.snbDep1[aria-expanded=true]')
1275            .each(function() {
1276              const $this = $(this);
1277              const con = $this.next('.snbListDep2');
1278              con.slideUp(aniSpeed, function() {
1279                $this.attr({
1280                  'aria-expanded': 'false',
1281                  'aria-selected': 'false'
1282                });
1283              });
1284            });
1285        }
1286
1287        // 가는편 오는편 컨텐츠 테두리 작업
1288        if (target.closest('.k1_sch_result').length > 0) {
1289          target.closest('li').addClass('toggleON');
1290        }
1291
1292        mySwiper.methodes.swiperUpdate(target);
1293        // }
1294      },
1295      hide: function(target, speed) {
1296        if (target.is(':animated')) {
1297          return false;
1298        }
1299        // if (target.hasClass('toggleCont')) {
1300        // 마이페이지 좌즉에 붙는 타입
1301        const aniSpeed = speed || 300;
1302        let btn = target.prev('.toggleBtn');
1303        if (target.hasClass('snbListDep2')) {
1304          btn = target.prev('.snbDep1');
1305          btn.attr('aria-selected', 'true');
1306        }
1307        // 필터 예외
1308        const filterWrap = target.closest('#filterWrap');
1309        if (filterWrap.length > 0) {
1310          btn.attr('aria-expanded', 'false');
1311          filterWrap.find('.filterSelectWrap').each(function() {
1312            const $this = $(this);
1313            $this.find('.scroll-content').data('scrollbar').init();
1314          });
1315          return false;
1316        }
1317
1318        target.slideUp(aniSpeed, function() {
1319          btn.attr('aria-expanded', 'false');
1320          // 마이페이지 좌즉에 붙는 타입
1321          if (target.hasClass('snbListDep2')) {
1322            btn.attr('aria-selected', 'false');
1323          }
1324          // 가는편 오는편 컨텐츠 테두리 작업
1325          if (target.closest('.k1_sch_result').length > 0) {
1326            target.closest('li').removeClass('toggleON');
1327          }
1328        });
1329        // }
1330      }
1331    },
1332    handler: {
1333      toggle: function() {
1334        const $this = $(this);
1335        const check = $this.attr('aria-expanded');
1336        let con = $this.next('.toggleCont');
1337        if ($this.hasClass('snbDep1')) {
1338          con = $this.next('.snbListDep2');
1339        }
1340
1341        if (check === 'true') {
1342          accordion.methodes.hide(con);
1343        } else if (check === 'false') {
1344          accordion.methodes.show(con);
1345        }
1346      }
1347    },
1348    setProperty: function(el) {
1349      this.el.wrap = el;
1350      this.el.btn = el.find('.toggleBtn');
1351      if (!el.hasClass('toggleList')) {
1352        this.el.btn = el.find('.snbDep1');
1353      }
1354    },
1355    bind: function() {
1356      this.el.btn.each(function() {
1357        const $this = $(this);
1358        $this
1359          .off('click.accordion')
1360          .on('click.accordion', accordion.handler.toggle);
1361      });
1362    },
1363    init: function(el) {
1364      this.setProperty($(el));
1365      this.bind();
1366    }
1367  };
1368
1369  // 플로팅 컨텐츠
1370  var floating = {
1371    el: {
1372      area: null,
1373      sorting: null,
1374      filter: null,
1375      search: null
1376    },
1377    selector: {},
1378    methodes: {},
1379    handler: {
1380      scroll: function(e) {
1381        const win = common.el.win;
1382        const scrollTop = win.scrollTop();
1383        const header = $(common.selector.header);
1384        const headerH = 104;
1385        let headerH2 = 72;
1386        const fMarginTop = 32;
1387        const footer = $(common.selector.footer);
1388        const elData = e.data;
1389        const area = elData.area;
1390        const sorting = elData.sorting;
1391        const filter = elData.filter;
1392        // var search = elData.search;
1393        const btn = filter.find('.filterBtns');
1394        const accoArea = filter.find('.filterSelectWrap');
1395        const filterSorting = filter.find('.filterSorting');
1396
1397        if (filter.hasClass('kf_paymentBox')) {
1398
1399          if (!filter.hasClass('floatingTrip') || !filter.hasClass('floatingJprentcar')) {
1400            if (filter.css('position') === 'fixed') {
1401              $('.kf_paymentBox').find('._boxWrap').each(function() {
1402                const $this = $(this);
1403                const maxH =
1404									win.height() -
1405									$('.floatingBtns').outerHeight(true) -
1406									filter.position().top -
1407									$('._boxWrap').position().top -
1408									// parseInt(accoArea.css('margin-top')) -
1409									// accoArea.children('.tit').height() -
1410									fMarginTop;
1411                $this.css('max-height', maxH);
1412                $this.children('.inner').css('max-height', maxH);
1413              });
1414            }
1415
1416            if (filter.prevAll().last().offset().top < scrollTop + headerH2 + 32) {
1417              filter.addClass('fixedPayment');
1418              if (footer.offset().top - scrollTop <= win.height()) {
1419                filter.css('position', '');
1420                filter.addClass('filterFoot');
1421              } else {
1422                filter.removeClass('filterFoot');
1423              }
1424            } else {
1425              filter.removeClass('fixedPayment filterFoot');
1426            }
1427
1428          } else {
1429            if (scrollTop > 104) {
1430              filter.addClass('fixedPayment');
1431
1432              const filterOffsetB = filter.height() + filter.offset().top;
1433              const viewContents = filter.prev();
1434              const viewContentsOffsetB = viewContents.height() + viewContents.offset().top + 64;
1435
1436              if (filterOffsetB >= viewContentsOffsetB) {
1437                filter.addClass('filterFoot');
1438              }
1439
1440              if (scrollTop < filter.offset().top - 72) {
1441                filter.removeClass('filterFoot');
1442              }
1443
1444            } else {
1445              filter.removeClass('fixedPayment');
1446            }
1447          }
1448
1449        } else {
1450          // 출발 도착 정보 픽스
1451          // if (common.el.doc.find('.headFixed').length > 0) {
1452          //   search.addClass('fixed');
1453          // } else {
1454          //   search.removeClass('fixed');
1455          // }
1456
1457
1458          // 숙박 예외처리
1459          if (filter.parents('.k1_schedule_search').hasClass('stay')) {
1460            headerH2 = 0;
1461          }
1462          // 렌터카 예외처리
1463          if (filter.parents('.k1_schedule_search').hasClass('rentcar')) {
1464            headerH2 = 100;
1465          }
1466
1467          // 빠른정렬 픽스
1468          if (scrollTop >= sorting.offset().top - headerH2 - parseInt(sorting.css('margin-top'))) {
1469            sorting.each(function() {
1470              const $this = $(this);
1471              $this.addClass('fixed');
1472            });
1473          } else {
1474            sorting.each(function() {
1475              const $this = $(this);
1476              $this.removeClass('fixed');
1477            });
1478          }
1479
1480          if (!filter.hasClass('filterFoot')) {
1481            if (sorting.hasClass('fixed') && filter.height() < $('#contents').height()) {
1482              filter.css({
1483                position: 'fixed',
1484                top: ''
1485              });
1486            } else {
1487              filter.css({
1488                position: 'absolute',
1489                top: '0'
1490              });
1491            }
1492          }
1493
1494          // footer 도달 시 픽스
1495          if (filter.offset().top > scrollTop + headerH2 + fMarginTop + sorting.height() && filter.hasClass('filterFoot')) {
1496            filter.removeClass('filterFoot');
1497          } else if (footer.offset().top < btn.offset().top + btn.outerHeight(true) + 20 && !filter.hasClass('filterFoot')) {
1498            if (filter.height() < $('#contents').height()) {
1499              filter.css('position', '');
1500              filter.addClass('filterFoot');
1501            } else {
1502              filter.addClass('filterFootClear');
1503            }
1504          }
1505
1506          if (filter.css('position') === 'fixed') {
1507            accoArea.find('.scriptScroll').each(function() {
1508              const $this = $(this);
1509              const maxH =
1510								win.height() -
1511								btn.outerHeight(true) -
1512								filter.position().top -
1513								accoArea.position().top -
1514								parseInt(accoArea.css('margin-top')) -
1515								accoArea.children('.tit').height() -
1516								fMarginTop;
1517              $this.css('max-height', maxH);
1518              $this.children('.scroll-content').css('max-height', maxH);
1519            });
1520          }
1521        }
1522      },
1523      resize: function(e) {
1524        const elData = e.data;
1525        floating.handler.scroll({
1526          data: elData
1527        });
1528      }
1529    },
1530    setProperty: function(el) {
1531      this.el.filter = el;
1532      this.el.area = el.closest('.k1_schedule_search');
1533      this.el.sorting = this.el.area.prevAll('.kf_quickFixed');
1534      // this.el.search = this.el.area.prevAll('.kf_searchFixed');
1535    },
1536    bind: function() {
1537      common.el.win
1538        .off('scroll.floating')
1539        .on('scroll.floating', this.el, this.handler.scroll);
1540      common.el.win
1541        .off('resize.floating')
1542        .on('resize.floating', this.el, this.handler.resize);
1543    },
1544    init: function(el) {
1545      this.setProperty($(el));
1546      this.bind();
1547    }
1548  };
1549
1550  // 툴팁
1551  var tooltip = {
1552    el: {
1553      btn: null,
1554      cont: null
1555    },
1556    selector: {
1557      header: '#wrapper > header'
1558    },
1559    handler: {
1560      show: function() {
1561        const $this = $(this);
1562        const cont = $this.next();
1563        $('.tooltipCont').hide();
1564        if (!cont.is(':visible')) {
1565          cont.show();
1566        }
1567      },
1568      close: function() {
1569        const $this = $(this);
1570        if ($this.hasClass('btClose')) {
1571          $this.closest('.notiView').hide();
1572        } else {
1573          $this.closest('.tooltipCont').hide();
1574        }
1575      }
1576    },
1577    setProperty: function(el) {
1578      this.el.showBtn = el;
1579      this.el.cont = el.next();
1580
1581      if (el.hasClass('btNoti')) {
1582        this.el.closeBtn = this.el.cont.find('.btClose');
1583      } else {
1584        this.el.closeBtn = this.el.cont.find('.btnClose');
1585      }
1586    },
1587    bind: function() {
1588      this.el.showBtn.off('.tooltip').on('click.tooltip', this.handler.show);
1589      this.el.closeBtn.off('.tooltip').on('click.tooltip', this.handler.close);
1590    },
1591    init: function(el) {
1592      this.setProperty($(el));
1593      this.bind();
1594      if ($(el).closest('.layPop')) {
1595        $('.closeL').click(function() {
1596          $('.tooltipCont').hide();
1597        });
1598      }
1599    }
1600  };
1601
1602  // 빠른 정렬 선택
1603  var tabAhcnor = {
1604    el: {
1605      tripArea: null,
1606      con: null,
1607      morning: null,
1608      afternoon: null,
1609      evening: null
1610    },
1611    selector: {
1612      wrapper: '#wrapper'
1613    },
1614    handler: {
1615      click: function(e) {
1616        const bh = $(common.selector.bh);
1617        const $this = $(this);
1618        const idx = $this.closest('li').index();
1619        const tab = tabAhcnor.el.tripArea;
1620        let tabT =
1621					parseInt(tab.parent().css('top')) +
1622					tab.closest('.tabSorting').outerHeight();
1623        let moveTop;
1624
1625        moveTop = $('#' + $this.attr('aria-controls')).offset().top;
1626        if (!$(tabAhcnor.selector.wrapper).hasClass('headFixed')) {
1627          moveTop -= 32;
1628
1629          $this.closest('.kf_quickFixed').addClass('fixed');
1630          tabT =
1631						parseInt(tab.parent().css('top')) +
1632						tab.closest('.tabSorting').outerHeight();
1633          $this.closest('.kf_quickFixed').removeClass('fixed');
1634        }
1635
1636        bh.stop().animate({
1637          scrollTop: moveTop - tabT
1638        });
1639      },
1640      scroll: function() {
1641        const win = common.el.win;
1642        const con = tabAhcnor.el.con;
1643        const tab = tabAhcnor.el.tripArea;
1644        const scrollTop = tab.offset().top + tab.outerHeight() + 20;
1645
1646        con.children('button').each(function(idx) {
1647          const $this = $(this);
1648          const target = $('#' + $this.attr('aria-controls'));
1649          const top = target.offset().top;
1650          const nextArea = target.nextAll('li[id*=anchor]').eq(0);
1651          let nextTop;
1652          if (nextArea.length) {
1653            nextTop = nextArea.offset().top;
1654          } else {
1655            nextTop =
1656							$this.closest('#container').offset().top +
1657							$this.closest('#container').height();
1658          }
1659          if (idx === 0 && top > scrollTop) {
1660            $this.attr('aria-selected', 'true');
1661          } else if (top <= scrollTop && scrollTop < nextTop) {
1662            $this.attr('aria-selected', 'true');
1663          } else {
1664            $this.attr('aria-selected', 'false');
1665          }
1666        });
1667      }
1668    },
1669    setProperty: function(el) {
1670      const doc = common.el.doc;
1671      this.el.tripArea = el;
1672      this.el.con = this.el.tripArea.children('li').not('.sorting');
1673      this.el.morning = doc.find('#anchorMorning');
1674    },
1675    bind: function() {
1676      if (this.el.morning.length > 0) {
1677        this.el.con.children('button').each(function() {
1678          const $this = $(this);
1679          $this.off('click.trip').on('click.trip', tabAhcnor.handler.click);
1680        });
1681        common.el.win
1682          .off('scroll.trip')
1683          .on('scroll.trip', tabAhcnor.handler.scroll);
1684      }
1685    },
1686    init: function(el) {
1687      this.setProperty($(el));
1688      this.bind();
1689    }
1690  };
1691
1692  // 달력
1693  var datepicker = {
1694    el: {
1695      area: null
1696    },
1697    selector: {},
1698    methodes: {
1699      init: function(area) {
1700        let template = '';
1701        const wrap = area.find('.swiper-wrapper');
1702        const today = new Date();
1703        const toYear = today.getFullYear();
1704        const toMonth = today.getMonth() + 1;
1705        const toDay = today.getDate();
1706        const options = {
1707          monthLength: 1,
1708          week: ['일', '월', '화', '수', '목', '금', '토'],
1709          startTxt: '체크인',
1710          endTxt: '체크아웃',
1711          availableTodaySelect: true,
1712          sameAlert: ''
1713        };
1714        const optionData = area.data('options') || {};
1715
1716        // 현재 월 기준으로 나올 계월 수
1717        if (optionData.monthLength) {
1718          options.monthLength = optionData.monthLength;
1719        }
1720
1721        // 시작일 텍스트
1722        if (optionData.startTxt) {
1723          options.startTxt = optionData.startTxt;
1724        }
1725
1726        // 종료일 텍스트
1727        if (optionData.endTxt) {
1728          options.endTxt = optionData.endTxt;
1729        }
1730
1731        // 오늘 선택 가능 여부
1732        if (typeof(optionData.availableTodaySelect) !== 'undefined') {
1733          options.availableTodaySelect = optionData.availableTodaySelect;
1734        }
1735
1736        // 당일선택 얼럿 텍스트
1737        if (optionData.sameAlert) {
1738          options.sameAlert = optionData.sameAlert;
1739        }
1740
1741        // 템플릿 생성
1742        for (let i = 0; i < options.monthLength; i++) {
1743          const year = today.getFullYear();
1744          const month = today.getMonth() + 1;
1745          const startDay = new Date(year, month - 1, 1).getDay();
1746          const dayLength = new Date(year, month, 0).getDate();
1747          const prevDayLength = new Date(year, month - 1, 0).getDate();
1748          const col = Math.ceil((startDay + dayLength) / 7);
1749
1750          template += '<li class="swiper-slide"><div class="k1_calendar_wrap">';
1751          template +=
1752						'<div class="k1_sel_month">' + year + '년 ' + month + '월</div>';
1753          template += '<table class="k1_board_mcal">';
1754          template += '<thead><tr>';
1755          options.week.forEach(function(val) {
1756            template += '<th>' + val + '</th>';
1757          });
1758          template += '</tr></thead>';
1759          template += '<tbody>';
1760
1761          for (let j = 0; j < col; j++) {
1762            template += '<tr>';
1763            for (let s = 1; s < 8; s++) {
1764              const num = s + j * 7 - startDay;
1765
1766              if (num <= 0) {
1767                // 이전 월 표시
1768                template +=
1769									'<td class="off prevMonth"><span>' +
1770									(prevDayLength + num) +
1771									'</span></td>';
1772              } else if (num > dayLength) {
1773                // 다음 월 표시
1774                template +=
1775									'<td class="off nextMonth"><span>' + (num - dayLength) + '</span></td>';
1776              } else if (
1777                new Date(year, month - 1, num) < new Date(toYear, toMonth - 1, toDay + (options.availableTodaySelect ? 0 : 1))
1778              ) {
1779                // 오늘 이전 날
1780                template += '<td class="off"><span>' + num + '</span></td>';
1781              } else {
1782                const td = new Date(year, month - 1, num);
1783                const tdString = moment(td).format("YYYY-MM-DD");
1784                template +=
1785									'<td><a href="#" role="button" data-date="' + tdString + '">' + num + '</a></td>';
1786              }
1787            }
1788            template += '</tr>';
1789          }
1790          template += '</tbody>';
1791          template += '</table>';
1792          template += '</div></li>';
1793          today.setDate(1);
1794          today.setMonth(today.getMonth() + 1);
1795        }
1796
1797        // 기존 폼 제거 후 템플릿 적용
1798        wrap.children().remove();
1799        wrap.append(template);
1800        mySwiper.methodes.swiperUpdate(area);
1801        // 기본 세팅
1802        wrap.find('.k1_calendar_wrap').each(function() {
1803          const $this = $(this);
1804          const ymTxt = $this.find('.k1_sel_month').text();
1805          const onDay = $this.find('tbody td').not('.off');
1806          const evtData = {
1807            year: toYear,
1808            month: toMonth,
1809            day: toDay,
1810            option: options
1811          };
1812
1813          // 토, 일 체크
1814          $this
1815            .find('tbody')
1816            .children('tr')
1817            .each(function() {
1818              const $this = $(this);
1819              const td = $this.children('td');
1820              td.first().not('.off').addClass('sun');
1821              td.last().not('.off').addClass('sat');
1822            });
1823
1824          // 오늘 날짜 체크
1825          const ymTxtSplit = ymTxt.split(" ");
1826          const ymTxtYear = ymTxtSplit[0].replace("년", "");
1827          const ymTxtMonth = ymTxtSplit[1].replace("월", "");
1828
1829          if (ymTxtYear == toYear && ymTxtMonth == toMonth) {
1830            $this.find('tbody td')
1831              .children('a:contains(' + toDay + ')')
1832              .filter(function(idx, target) {
1833                return target.innerText === String(toDay);
1834              })
1835              .closest('td')
1836              .addClass('today');
1837          }
1838
1839          onDay.children('a').each(function() {
1840            const $this = $(this);
1841            $this.data("evtdata", evtData);
1842            $this
1843              .off('click.datepicker')
1844              .on('click.datepicker', evtData, datepicker.handler.dayPick);
1845          });
1846        });
1847      }
1848    },
1849    handler: {
1850      dayPick: function(e) {
1851        e.preventDefault();
1852        datepicker.handler.customDayPick($(this));
1853      },
1854      customDayPick: function(obj, e) {
1855        const $this = obj;
1856        const regex = /[^0-9]/g;
1857        const pick = $this.closest('td');
1858        const area = $this.closest('.multiCalendar');
1859        const wrap = $this.closest('.k1_calendar_wrap');
1860        const dateArea = wrap.find('.k1_sel_month');
1861        const tbody = area.find('tbody');
1862        const tr = tbody.children('tr');
1863        const td = tr.children('td');
1864        let start = tr.children('td.start');
1865        let end = tr.children('td.end');
1866        const yy = dateArea.text().split(' ')[0].replace(regex, ''); // 년도
1867        let mm = dateArea.text().split(' ')[1].replace(regex, ''); // 월
1868        if (mm.length < 2) {
1869          mm = '0' + mm;
1870        }
1871        let dd = $this.text(); // 일
1872        if (dd.length < 2) {
1873          dd = '0' + dd;
1874        }
1875        const data = e ? e.data : $this.data("evtdata");
1876        const options = data.option;
1877
1878        if (start.length > 0 && end.length > 0) {
1879          start.removeClass('start').children('.txt').remove();
1880          start = area.find('tbody td.start');
1881          end.removeClass('end').children('.txt').remove();
1882          end = area.find('tbody td.end');
1883          area.find('.range').removeClass('range');
1884        } else if (td.index(start) > td.index(pick)) {
1885          // pick -> start, start-> end가 되야함
1886          // start.removeClass('start').children('.txt').remove();
1887          pick.addClass('start').append('<span class="txt">' + options.startTxt + '</span>');
1888          start.removeClass('start').addClass('end').append('<span class="txt">' + options.endTxt + '</span>');
1889          start = area.find('tbody td.start');
1890          end = area.find('tbody td.end');
1891
1892          pick.nextAll('td').not('.end').addClass('range');
1893          end.prevAll('td').not('.end').addClass('range');
1894          pick.prevAll('td').not('.off').removeClass('range');
1895          end.nextAll('td').not('.off').removeClass('range');
1896          pick.prevAll('td.off').removeClass('range');
1897          pick.removeClass('range');
1898          end.removeClass('range');
1899
1900          var startCol = tr.index(pick.closest('tr'));
1901          var endCol = tr.index(end.closest('tr'));
1902
1903
1904          if (endCol - startCol > 1) {
1905            for (var i = 1; i < endCol - startCol; i++) {
1906              tr.eq(startCol + i)
1907                .find('td')
1908              // .not('.off')
1909                .addClass('range');
1910            }
1911          }
1912        }
1913
1914        if (start.length === 0) {
1915          $this.after('<span class="txt">
1915' + options.startTxt + '</span>');
1916          pick.addClass('start');
1917          // 선택 날짜 val 로 전달
1918          area
1919            .val(yy + '-' + mm + '-' + dd)
1920            .attr('value', yy + '-' + mm + '-' + dd);
1921        } else if (end.length === 0) {
1922          var startDate = area.val();
1923          if ($this.siblings('.txt').length > 0) {
1924            if (options.sameAlert) {
1925              if (jppJs) {
1926                jppJs.alert("알림", options.sameAlert);
1927              } else {
1928                alert(options.sameAlert);
1929              }
1930            }
1931            return false;
1932          } else {
1933            $this.after('<span class="txt">' + options.endTxt + '</span>');
1934            area
1935              .val(startDate + ' ~ ' + yy + '-' + mm + '-' + dd)
1936              .attr('value', startDate + ' ~ ' + yy + '-' + mm + '-' + dd);
1937          }
1938          pick.addClass('end');
1939
1940          // 범위 표시
1941          start.nextAll('td').not('.off, .end').addClass('range');
1942          pick.prevAll('td').not('.off, .range, .start').addClass('range');
1943          start.prevAll('td').not('.off').removeClass('range');
1944          pick.nextAll('td').not('.off').removeClass('range');
1945          start.closest('tr').find('.off').addClass('range');
1946          pick.closest('tr').find('.off').addClass('range');
1947          start.prevAll('td.off').removeClass('range');
1948          pick.nextAll('td.off').removeClass('range');
1949          var startCol = tr.index(start.closest('tr'));
1950          var endCol = tr.index(pick.closest('tr'));
1951
1952          if (endCol - startCol > 1) {
1953            for (var i = 1; i < endCol - startCol; i++) {
1954              tr.eq(startCol + i)
1955                .find('td')
1956              // .not('.off')
1957                .addClass('range');
1958            }
1959          }
1960        } else {
1961          console.log("역방향 ");
1962          var startDate = area.val();
1963          console.log(startDate);
1964          console.log(yy + '-' + mm + '-' + dd);
1965          console.log("역방향 end ");
1966          area
1967            .val(yy + '-' + mm + '-' + dd + ' ~ ' + startDate)
1968            .attr('value', yy + '-' + mm + '-' + dd + ' ~ ' + startDate);
1969        }
1970      }
1971    },
1972    setProperty: function(el) {
1973      this.el.area = el;
1974    },
1975    init: function(el) {
1976      const _this = this;
1977      _this.setProperty($(el));
1978      _this.el.area.data("datepicker", {
1979        setStartDate: (function(area) {
1980          return function(startDate) {
1981            const $this = area.find('[data-date=' + startDate + ']');
1982            _this.handler.customDayPick($this);
1983          };
1984        })(_this.el.area),
1985        setEndDate: (function(area) {
1986          return function(endDate) {
1987            const $this = area.find('[data-date=' + endDate + ']');
1988            _this.handler.customDayPick($this);
1989          }
1990        })(_this.el.area),
1991        init: (function(area) {
1992          return function() {
1993            datepicker.methodes.init(area);
1994          }
1995        })(_this.el.area)
1996      });
1997      datepicker.methodes.init(_this.el.area);
1998    }
1999  };
2000
2001  // 슬라이더
2002  var slider = {
2003    el: {
2004      target: null,
2005      viewArea: null
2006    },
2007    selector: {},
2008    methodes: {
2009      init: function() {
2010        // 기본 옵션
2011        const optionData = slider.el.target.data('options') || {};
2012        const options = {
2013          range: optionData.range || false,
2014          min: optionData.min || null,
2015          max: optionData.max || null,
2016          step: optionData.step || null,
2017          value: optionData.value || 0,
2018          values: optionData.values || null,
2019          text: optionData.text || null,
2020          slide: function() {}
2021        };
2022
2023        const mySlider = slider.el.target.slider(options);
2024
2025        if (slider.el.viewArea.length > 0) {
2026          slider.el.viewArea.children('.amount').each(function(idx) {
2027            const $this = $(this);
2028            $this.val(
2029              slider.methodes.comma(optionData.values[idx]) + optionData.text
2030            );
2031          });
2032        }
2033        mySlider.on('slide', options, slider.handler.slide);
2034      },
2035      comma: function(number) {
2036        return number.toLocaleString('en');
2037      }
2038    },
2039    handler: {
2040      slide: function(e, ui) {
2041        const options = e.data;
2042        const target = $(e.target);
2043        const amount = target.next('.fp_slideInp').children('.amount');
2044
2045        if (options.range === true) {
2046          if (ui.values[0] + options.step > ui.values[1]) {
2047            return false;
2048          }
2049        }
2050        if (
2051          options.range === 'min' &&
2052					target.closest('.slideReview').length > 0
2053        ) {
2054          target.next('.amount').val(ui.value);
2055        }
2056
2057        amount.each(function(idx) {
2058          const $this = $(this);
2059          let val = ui.values[idx];
2060          if (val === null) {
2061            val = 0;
2062          }
2063          $this.val(slider.methodes.comma(val) + options.text);
2064        });
2065      }
2066    },
2067    setProperty: function(el) {
2068      this.el.target = el;
2069      this.el.viewArea = el.next('.fp_slideInp');
2070
2071      this.methodes.init();
2072    },
2073    bind: function() {},
2074    init: function(el) {
2075      this.setProperty($(el));
2076      this.bind();
2077    }
2078  };
2079
2080  // 정렬
2081  var sortable = {
2082    el: {
2083      target: null
2084    },
2085    selector: {},
2086    methodes: {
2087      init: function() {
2088        sortable.el.target.sortable({
2089          handle: '.btIco',
2090          cancel: '',
2091          containment: sortable.el.target,
2092          animation: 150,
2093          axis: 'y',
2094          scroll: false,
2095          revert: 150,
2096          start: function() {
2097            const sort = $(this).sortable('instance');
2098            sort.containment[3] += 25;
2099            sort.containment[1] -= 25;
2100          }
2101        });
2102        sortable.el.target.disableSelection();
2103      }
2104    },
2105    handler: {},
2106    setProperty: function(el) {
2107      this.el.target = el;
2108
2109      this.methodes.init();
2110    },
2111    bind: function() {},
2112    init: function(el) {
2113      this.setProperty($(el));
2114      this.bind();
2115    }
2116  };
2117
2118  // 기타
2119  var etc = {
2120    el: {},
2121    selector: {
2122      inpDeleteAni: '.inpDeleteAni',
2123      allCheck: '.agree> .large, .chkTotalSel > .total, .chkGroup > .frmInp',
2124      toggleAgree: '.agreeList.toggleList',
2125      frmAcctList: '.frmAcctList .inpAcct, .frmColGroup .frmInp, .rentcarStoreList .rentcarStore ',
2126      selTotal: '.selTotal',
2127      searchIcon: '.searchIcon',
2128      rentercarList: '.rentercarList > div > .rentcarItemGroup',
2129      eagVisual: '.eagVisual',
2130      setting: '.kf_areaNum .setting',
2131      btTop: '.btTop',
2132      viewInfoWrap: '.viewInfoWrap',
2133      fileInput: '.file',
2134      reviewList: '.reviewList',
2135      bottomFrmWrap: '.bottomFrmWrap',
2136      mapArea: '.quick_mapArea',
2137      mapDropdown: '.quick_tools',
2138      detailsTxt: 'details.txt',
2139      rentcarDetail: '.rentcarDetail'
2140    },
2141    methodes: {
2142      // 리뷰 영역 더보기/닫기 버튼 노출 유무 및 이벤트 바인딩
2143      reviewMoreBtn: function(target) {
2144        target.children('li').each(function() {
2145          const $this = $(this);
2146          const txtArea = $this.children('.txt');
2147          const txtAreaH = txtArea.height();
2148          const clone = txtArea.clone().prependTo($this).css({
2149            visibility: 'hidden',
2150            position: 'absolute',
2151            textOverflow: 'inherit',
2152            display: 'block',
2153            '-webkit-box-orient': 'inherit',
2154            'max-height': 'inherit'
2155          });
2156          const cloneH = clone.height();
2157          clone.remove();
2158
2159          if (txtAreaH < cloneH || txtArea.hasClass('txtFull')) {
2160            if ($this.find('.btLink').length === 0) {
2161              txtArea.after(
2162                '<button type="button" class="btLink btLine light"><span class="more">더보기</span><span class="close">닫기</span></button>'
2163              );
2164            }
2165          }
2166
2167          $this.off('click.etc').on('click.etc', '.btLink', function() {
2168            const $this = $(this);
2169            $this.prev('.txt').toggleClass('txtFull');
2170          });
2171        });
2172      }
2173    },
2174    handler: {
2175      scroll: function() {
2176        const win = $(this);
2177        const scrollTop = win.scrollTop();
2178        const topBtn = $(etc.selector.btTop);
2179        const aside = topBtn.closest('aside');
2180        const esgFoot = $(etc.selector.bottomFrmWrap);
2181        const footer = $(common.selector.footer);
2182        let footerTop = 0;
2183        if (footer.length > 0) {
2184          footerTop = footer.offset().top;
2185        }
2186
2187        // 렌터카 페이지 고정 컨텐츠 제어
2188        $(etc.selector.rentercarList).each(function() {
2189          const $this = $(this);
2190          const $thisH = $this.outerHeight();
2191          const $thisTop = $this.offset().top;
2192          const summaryInfo = $this.children('.summaryInfo');
2193          const headerH = $('#wrapper').children('header').height();
2194          const tripSelect = common.el.doc.find('.tripSelect');
2195          let tripSelectH = 0;
2196          if (tripSelect.length > 0) {
2197            tripSelectH = tripSelect.children('.inner').outerHeight();
2198          }
2199          if (
2200            scrollTop + headerH + tripSelectH > $thisH + $thisTop - 100 ||
2201						scrollTop === 0
2202          ) {
2203            summaryInfo.hide();
2204          } else if (scrollTop + headerH + tripSelectH >= $thisTop + 100) {
2205            summaryInfo.show();
2206          } else {
2207            summaryInfo.hide();
2208          }
2209        });
2210
2211        // 탑버튼 제어
2212        if (topBtn.length > 0) {
2213          if (scrollTop > 0) {
2214            if (!topBtn.is(':visible')) {
2215              topBtn.show();
2216              $(etc.selector.rentcarDetail).each(function() {
2217                const $this = $(this);
2218                $this.find('aside .notiView').css('right', '72px');
2219              });
2220            }
2221          } else {
2222            topBtn.hide();
2223            $(etc.selector.rentcarDetail).each(function() {
2224              const $this = $(this);
2225              $this.find('aside .notiView').css('right', '24px');
2226            });
2227          }
2228          // 탑버튼 고정
2229          if (
2230            footerTop - scrollTop < win.height() &&
2231						!aside.hasClass('footON')
2232          ) {
2233            aside.addClass('footON');
2234            esgFoot.addClass('footON');
2235          } else if (
2236            footerTop - scrollTop >= win.height() &&
2237						aside.hasClass('footON')
2238          ) {
2239            aside.removeClass('footON');
2240            esgFoot.removeClass('footON');
2241          }
2242        }
2243      },
2244      resize: function() {},
2245      // 인풋박스 내용이 있을 때 내용 삭제 버튼 노출
2246      inputValCheck: function() {
2247        const $this = $(this);
2248        const removeBtn = $this.next(etc.selector.icDel);
2249        setTimeout(function() {
2250          const val = $this.val();
2251          if (val !== '') {
2252            removeBtn.show();
2253          } else {
2254            removeBtn.hide();
2255          }
2256        }, 10);
2257      },
2258      // 인풋박스 내용 삭제
2259      inputRemoveBtn: function() {
2260        const $this = $(this);
2261        const input = $this.prev('input');
2262        input.val('');
2263        input.trigger('keydown');
2264      },
2265      // 전체 선택 체크 박스 기능
2266      allCheck: function(e) {
2267        const $this = $(this);
2268        const checked = $this.prop('checked');
2269        const conts = $(e.data.conts);
2270        const toggleAgree = $(e.data.toggleAgree);
2271        let count = 0;
2272        if (checked) {
2273          if ($this.closest('.agreeList.toggleList').length > 0) {
2274            conts.each(function() {
2275              if ($(this).is(':checked')) {
2276                count++;
2277              }
2278            });
2279            if (count > 0) {
2280              return true;
2281            }
2282          }
2283          conts.prop('checked', true);
2284          toggleAgree.prop('checked', true).trigger('change');
2285        } else {
2286          conts.prop('checked', false);
2287          toggleAgree.prop('checked', false).trigger('change');
2288        }
2289      },
2290      // 전체 선택 체크 박스의 목록 체크박스 기능
2291      allCheckCon: function(e) {
2292        const conts = $(e.data.conts);
2293        const all = $(e.data.all);
2294        const type = e.data.type;
2295        let count = 0;
2296
2297        conts.each(function() {
2298          const $this = $(this);
2299          if ($this.prop('checked') === true) {
2300            count++;
2301          }
2302        });
2303
2304        let checkOn = count === conts.length;
2305        if (type === 'once') {
2306          checkOn = count > 0;
2307        }
2308
2309        if (checkOn) {
2310          all.prop('checked', true);
2311          accoCheck();
2312        } else {
2313          all.prop('checked', false);
2314          accoCheck();
2315        }
2316
2317        // 아코디언 체크박스 체크
2318        function accoCheck() {
2319          if (
2320            all.closest('.toggleList').length > 0 &&
2321						all.closest('.chkTotalSel').length === 0
2322          ) {
2323            all.trigger('change');
2324          }
2325        }
2326      },
2327      // radio, checkbox 선택 시 컨텐츠 show/hide
2328      frmChange: function() {
2329        const $this = $(this);
2330        const span = $this.closest('span');
2331        const wrap = $this.closest('.frmAcctList');
2332        const frmColGroup = $this.closest('.frmColGroup');
2333        const rentcarStoreList = $this.closest('.rentcarStoreList');
2334
2335        if (rentcarStoreList.length > 0) {
2336          rentcarStoreList.find('.chkON').removeClass('chkON');
2337          $this.closest('.rentcarStore').addClass('chkON');
2338        } else if (frmColGroup.length > 0) {
2339          frmColGroup.find('.chkON').removeClass('chkON');
2340          $this.closest('.frmInp').addClass('chkON');
2341        } else {
2342          if ($this.attr('type') === 'radio') {
2343            wrap.find('.inpAcct>input[type=radio]').each(function() {
2344              const $this = $(this);
2345              const span = $this.closest('span');
2346              span.attr('aria-expanded', $this.prop('checked'));
2347            });
2348          } else {
2349            span.attr('aria-expanded', $this.prop('checked'));
2350          }
2351        }
2352        mySwiper.methodes.swiperUpdate(wrap);
2353      },
2354      // 검색input 포커스 in 시 클래스 on
2355      searchFocusIn: function(e) {
2356        const $this = $(this);
2357        if ($(e.target).hasClass('icDel')) {
2358          return false;
2359        }
2360        $this.addClass('inpFocus');
2361      },
2362      // 검색input 포커스 out 시 클래스 off
2363      searchFocusOut: function() {
2364        const $this = $(this);
2365        $this.removeClass('inpFocus');
2366      },
2367    },
2368    bind: function() {
2369      common.el.win.off('scroll.etc').on('scroll.etc', etc.handler.scroll);
2370      common.el.win.off('resize.etc').on('resize.etc', etc.handler.resize);
2371
2372      // 인풋박스 내용 삭제 버튼 기능
2373      $(etc.selector.inpDeleteAni).each(function() {
2374        const $this = $(this);
2375        const btn = $this.find('.icDel');
2376        const input = $this.find('input');
2377        btn
2378          .off('click.removeBtn')
2379          .on('click.removeBtn', etc.handler.inputRemoveBtn);
2380        input
2381          .off('keydown.removeBtn')
2382          .on('keydown.removeBtn', etc.handler.inputValCheck);
2383        input.trigger('keydown.removeBtn');
2384      });
2385
2386      // 체크 박스 전체 선택 제어
2387      $(etc.selector.allCheck).each(function() {
2388        const $this = $(this);
2389        const allCheck = $this.find('input[type=checkbox]');
2390        let checkCon = $this.next('.agreeList').find('input[type=checkbox]');
2391        const checkCon2 = $this
2392          .nextAll('.agreeList.toggleList')
2393          .find('.acctItem > .frmInp input[type=checkbox]');
2394
2395        const checkCon3 = $this
2396          .closest('.chkGroup')
2397          .find(
2398            '.frmBox li input[type=checkbox]'
2399          );
2400
2401        if (checkCon2.length > 0) {
2402          checkCon = checkCon.add(checkCon2);
2403        }
2404                
2405        if (checkCon3.length > 0) {
2406          checkCon = checkCon.add(checkCon3);
2407        }
2408
2409        // 필터 영역 전체 체크
2410        if ($this.hasClass('total')) {
2411          checkCon = $this.nextAll('.frmInp').find('input[type=checkbox]');
2412        }
2413
2414        const data = {
2415          all: allCheck,
2416          conts: checkCon,
2417          toggleAgree: $this
2418            .nextAll('.agreeList.toggleList')
2419            .find('.acctItem > .frmInp input[type=checkbox]') || {}
2420        };
2421        allCheck
2422          .off('change.allCheck')
2423          .on('change.allCheck', data, etc.handler.allCheck);
2424        checkCon
2425          .off('change.allCheck')
2426          .on('change.allCheck', data, etc.handler.allCheckCon);
2427      });
2428      // 전체 선택 체크 박스의 목록 체크박스 제어
2429      $(etc.selector.toggleAgree).each(function() {
2430        const $this = $(this);
2431        const tit = $this.find('.acctItem > .frmInp input[type=checkbox]');
2432        const cont = $this.find('.toggleCont input[type=checkbox]');
2433        tit
2434          .off('change.allCheck2')
2435          .on('change.allCheck2', {
2436            conts: cont
2437          }, etc.handler.allCheck);
2438        cont
2439          .off('change.allCheck2')
2440          .on(
2441            'change.allCheck2', {
2442              all: tit,
2443              conts: cont,
2444              type: 'once'
2445            },
2446            etc.handler.allCheckCon
2447          );
2448      });
2449
2450      // radio, checkbox 선택 시 컨텐츠 show/hide
2451      $(etc.selector.frmAcctList).each(function() {
2452        const $this = $(this);
2453        const box = $this.children('input');
2454        box.off('change.etc').on('change.etc', etc.handler.frmChange);
2455      });
2456
2457      // 전체 박스가 있는 목록 체크 시 목록 초기화
2458      $(etc.selector.selTotal).each(function() {
2459        const $this = $(this);
2460        const total = $this.children('.total').children('input');
2461        const conts = $this.children('li').not('.total').children('input');
2462        conts.off('change.etc').on('change.etc', function() {
2463          let count = 0;
2464          conts.each(function() {
2465            const $this = $(this);
2466            if ($this.prop('checked') === false) {
2467              count += 1;
2468            }
2469          });
2470          if (!count) {
2471            conts.prop('checked', false);
2472            conts.attr('checked', 'false');
2473            total.prop('checked', true);
2474            total.attr('checked', 'true');
2475            return false;
2476          }
2477          total.prop('checked', false);
2478          total.attr('checked', 'false');
2479        });
2480        total.off('change.etc').on('change.etc', function() {
2481          conts.prop('checked', false);
2482          conts.attr('checked', 'false');
2483        });
2484      });
2485
2486      // 검색input 포커스 시 클래스 on/off
2487      $(etc.selector.searchIcon).each(function() {
2488        const $this = $(this);
2489        $this.off('focusin.etc').on('focusin.etc', etc.handler.searchFocusIn);
2490        $this
2491          .off('focusout.etc')
2492          .on('focusout.etc', etc.handler.searchFocusOut);
2493      });
2494
2495      // 플러스, 마이너스 버튼 클릭 시 카운트 기능 : vue 처리(영향 없을 경우 삭제)
2496      /* $(etc.selector.setting).each(function() {
2497        const $this = $(this);
2498        const areaNum = $this.closest('.kf_areaNum');
2499        const plusBtn = $this.children('.plus');
2500        const minusBtn = $this.children('.minus');
2501        const num = $this.children('.num');
2502        let thisNum = Number(num.val());
2503        const max = Number(num.attr('maxlength'));
2504        const min = Number(num.attr('minlength')) || 0;
2505        plusBtn.off('click.etc').on('click.etc', function(e) {
2506          e.stopPropagation();
2507          num.val(++thisNum);
2508          minusBtn.attr('disabled', false);
2509          areaNum.addClass('notMin');
2510          if (thisNum == max) {
2511            plusBtn.attr('disabled', true);
2512          }
2513        });
2514        minusBtn.off('click.etc').on('click.etc', function(e) {
2515          e.stopPropagation();
2516          num.val(--thisNum);
2517          plusBtn.attr('disabled', false);
2518          if (thisNum - 1 < min) {
2519            areaNum.removeClass('notMin');
2520            minusBtn.attr('disabled', true);
2521          }
2522        });
2523      }); */
2524
2525      // $(document).off('click', '.ticketItem.kf_areaNum').on('click', '.ticketItem.kf_areaNum', function(e){
2526      //   e.stopPropagation();
2527      //   $(this).closest('.kf_areaNum').toggleClass('notMin');
2528      // });
2529
2530      // a 태그 클릭 시 탭 변경 기능
2531      $(etc.selector.viewInfoWrap).each(function() {
2532        const $this = $(this);
2533        $this
2534          .find('a[href*=tabContents]')
2535          .off('click.etc')
2536          .on('click.etc', function(e) {
2537            e.preventDefault();
2538            const $this = $(this);
2539            const href = $this.attr('href').split('#')[1];
2540            const target = common.el.doc.find('a[data-controls*=' + href + ']');
2541            target.trigger('click');
2542            // $(common.selector.bh).animate({scrollTop: target.closest('.tabAllCont').offset().top}, 300);
2543          });
2544      });
2545
2546      // 첨부파일 선택 시 파일 이름 삽입
2547      $(etc.selector.fileInput).each(function() {
2548        const txtArea = $(this);
2549        const input = txtArea.prev('input[type=file]');
2550        input.off('change.etc').on('change.etc', function(e) {
2551          const $this = $(this);
2552          txtArea.val($this[0].files[0].name);
2553          txtArea.attr('value', $this[0].files[0].name);
2554        });
2555      });
2556
2557      // 리뷰 영역 더보기 버튼 기능
2558      $(etc.selector.reviewList).each(function() {
2559        const $this = $(this);
2560        etc.methodes.reviewMoreBtn($this);
2561      });
2562
2563      // 퀵서치 지도 선택
2564      // $(etc.selector.mapArea).each(function() {
2565      //   var $this = $(this);
2566      //   var $allStates = $this.find('svg > *');
2567
2568      //   $allStates.addClass('active');
2569      //   $allStates.off('click').on('click', function() {
2570      //       if ( $(this).hasClass('active') ) {
2571      //         $(this).removeClass('active');
2572      //       } else {
2573      //         $(this).addClass('active');
2574      //       }
2575      //   });
2576      // });
2577
2578      // 퀵서치 키워드 이벤트
2579      $(etc.selector.mapDropdown).each(function() {
2580        const $this = $(this);
2581
2582        $this.siblings('input').focus(function() {
2583          $this.show();
2584        });
2585        $this.siblings('input').blur(function() {
2586          setTimeout(function() {
2587            $this.hide();
2588          }, 200);
2589        });
2590      });
2591
2592      // 탑버튼
2593      // $(etc.selector.btTop).each(function() {
2594      //   var $this = $(this);
2595      //   $this.off('click.etc').on('click.etc', function(e) {
2596      //     e.preventDefault();
2597      //     $(common.selector.bh).stop().animate({scrollTop: 0});
2598      //   });
2599      // });
2600
2601      // 상품상세 설명 더보기
2602      if ($(etc.selector.detailsTxt).length) {
2603        const txtOpenH = $(etc.selector.detailsTxt).prop('open', true).height();
2604        const txtMaxH = 72;
2605
2606        $(etc.selector.detailsTxt).prop('open', false);
2607
2608        if (txtOpenH > txtMaxH) {
2609          $(etc.selector.detailsTxt).addClass('ellipsisTrue');
2610        }
2611      }
2612
2613      // 렌터카 상세페이지 안내 툴팁 출력
2614      $(etc.selector.rentcarDetail).each(function() {
2615        const $this = $(this);
2616        setTimeout(function() {
2617          $this.find('aside .notiView').toggleClass('bottom', true).show();
2618        }, 15000);
2619      });
2620
2621    },
2622    init: function() {
2623      this.bind();
2624    }
2625  };
2626
2627  // mvJs interface
2628  var mvJs = {
2629    // js 초기화
2630    init: common.handler.ready,
2631    utils: {
2632      // window 스크롤 비활성화
2633      scrollDisabled: utils.scrollDisabled,
2634      // window 스크롤 활성화
2635      scrollEnabled: utils.scrollEnabled,
2636      // dim 활성화
2637      dimmedShow: utils.dimmedShow,
2638      // dim 비활성화
2639      dimmedHide: utils.dimmedHide
2640    },
2641    swiper: {
2642      /**
2643			 * 스와이프 업데이트
2644			 * mvJs.swiper.update(target: jQuerySeletor)
2645			 * target: 스와이프를 감싸고 있는 태그의 셀렉터
2646			 * 스와이프 swiper-wrapper 안쪽 컨텐츠만 바뀌었을 때 실행
2647			 * target의 자식으로 있는 스와이프를 update
2648			 * mvJs.swiper.update($('.swiperWrap'))
2649			 */
2650      update: mySwiper.methodes.swiperUpdate
2651    },
2652    popup: {
2653      /**
2654			 * 팝업 show
2655			 * mvJs.popup.show(target: jQuerySeletor)
2656			 * target: 팝업 셀렉터
2657			 * mvJs.popup.show($('.layer_popup'));
2658			 */
2659      show: popup.methodes.show,
2660      /**
2661			 * 팝업 hide
2662			 * mvJs.popup.show(target: jQuerySeletor)
2663			 * target: 팝업 셀렉터
2664			 * mvJs.popup.hide($('.layer_popup'));
2665			 */
2666      hide: popup.methodes.hide
2667    },
2668    ect: {
2669      /**
2670			 * 리뷰 말줄임 시 더보기 버튼 및 이벤트 바인딩
2671			 * mvJs.ect.reviewMoreBtn(target: jQuerySeletor)
2672			 * target: 리뷰 리스트 셀렉터
2673			 * mvJs.ect.reviewMoreBtn($('.reviewList'))
2674			 */
2675      reviewMoreBtn: etc.methodes.reviewMoreBtn
2676    }
2677  };
2678  window.mvJs = mvJs;
2679})(window.jQuery, window);

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.