1class ProductRoller { 2 constructor(selector, options = {}) { 3 this.$wrap = $(selector); 4 this.options = { 5 animationSpeed: 500, 6 autoplaySpeed: 3000, 7 ...options, 8 }; 9 this.$container = this.$wrap.find('.SliderContainer'); 10 this.$slide = this.$wrap.find('.SliderSlide'); 11 this.$items = this.$wrap.find('.SlideItem'); 12 this.isAnimating = false; 13 this.autoRoll = null; 14 15 if (!this.$wrap.length || !this.$container.length || !this.$slide.length || !this.$items.length) { 16 console.error('ProductRoller: íìí ìì를 ì°¾ì ì ììµëë¤.'); 17 return; 18 } 19 20 this.init(); 21 } 22 23 init() { 24 this.$slide.append(this.$items.clone()); 25 this.bindEvents(); 26 this.startAutoRoll(); 27 } 28 29 calculateSlideWidth() { 30 let totalWidth = 0; 31 this.$items.each(function () { 32 totalWidth += $(this).outerWidth(true); 33 }); 34 return totalWidth / 2; 35 } 36 37 nextSlide() { 38 if (this.isAnimating) return; 39 this.isAnimating = true; 40 41 // $items 를 ë¤ì ê³ì°í©ëë¤. 42 this.$items = this.$wrap.find('.SlideItem'); 43 const $firstItem = this.$items.first(); 44 const itemWidth = $firstItem.outerWidth(true); 45 46 this.$slide.animate({ marginLeft: -itemWidth }, this.options.animationSpeed, () => { 47 $firstItem.appendTo(this.$slide); 48 this.$slide.css('marginLeft', 0); 49 this.isAnimating = false; 50 }); 51 } 52 53 prevSlide() { 54 if (this.isAnimating) return; 55 this.isAnimating = true; 56 57 // $items 를 ë¤ì ê³ì°í©ëë¤. 58 this.$items = this.$wrap.find('.SlideItem'); 59 const $lastItem = this.$items.last(); 60 const itemWidth = $lastItem.outerWidth(true); 61 62 $lastItem.prependTo(this.$slide); 63 this.$slide.css('marginLeft', -itemWidth);
64 65 this.$slide.animate({ marginLeft: 0 }, this.options.animationSpeed, () => { 66 this.isAnimating = false; 67 }); 68 } 69 70 startAutoRoll() { 71 this.stopAutoRoll(); 72 this.autoRoll = setInterval(() => this.nextSlide(), this.options.autoplaySpeed); 73 } 74 75 stopAutoRoll() { 76 clearInterval(this.autoRoll); 77 this.autoRoll = null; 78 } 79 80 bindEvents() { 81 this.$wrap.find('.SlideNext').on('click', () => this.nextSlide()); 82 this.$wrap.find('.SlidePrev').on('click', () => this.prevSlide()); 83 84 this.$wrap.on('mouseenter', () => this.stopAutoRoll()); 85 this.$wrap.on('mouseleave', () => this.startAutoRoll()); 86 87 let touchStartX, startMarginLeft; 88 89 this.$container.on('touchstart', (e) => { 90 if (this.isAnimating) return; 91 touchStartX = e.originalEvent.touches[0].clientX; 92 startMarginLeft = parseInt(this.$slide.css('marginLeft')) || 0; 93 this.stopAutoRoll(); 94 }); 95 96 this.$container.on('touchmove', (e) => { 97 if (!touchStartX || this.isAnimating) return; 98 const touchMoveX = e.originalEvent.touches[0].clientX; 99 const diff = touchStartX - touchMoveX; 100 101 if (Math.abs(diff) > 5) { 102 e.preventDefault(); 103 this.$slide.css('marginLeft', startMarginLeft - diff); 104 } 105 }); 106 107 this.$container.on('touchend touchcancel', (e) => { 108 if (!touchStartX || this.isAnimating) return; 109 const touchEndX = e.originalEvent.changedTouches[0].clientX; 110 const diff = touchStartX - touchEndX; 111 112 if (Math.abs(diff) > 50) { 113 if (diff > 0) this.nextSlide(); 114 else this.prevSlide(); 115 } else { 116 this.$slide.animate({ marginLeft: startMarginLeft }, 200); 117 } 118 119 touchStartX = null; 120 this.startAutoRoll(); 121 }); 122 } 123}
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.