Product grid carousel

by kthornbloom

HTML

<div class="wrapper">


<div class="product-stage">
  <div class="product-stage__img">
    <img src="https://picsum.photos/id/1/140/140" alt="">
  </div>
  <div class="product-stage__img">
    <img src="https://picsum.photos/id/2/140/140" alt="">
  </div>
  <div class="product-stage__img">
    <img src="https://picsum.photos/id/3/140/140" alt="">
  </div>
  <div class="product-stage__img">
    <img src="https://picsum.photos/id/4/140/140" alt="">
  </div>
</div>

</div>

<div class="wrapper">


<div class="product-stage">
  <div class="product-stage__img">
    <img src="https://picsum.photos/id/5/140/140" alt="">
  </div>
  <div class="product-stage__img">
    <img src="https://picsum.photos/id/6/140/140" alt="">
  </div>
  <div class="product-stage__img">
    <img src="https://picsum.photos/id/7/140/140" alt="">
  </div>
  <div class="product-stage__img">
    <img src="https://picsum.photos/id/8/140/140" alt="">
  </div>
</div>

</div>

SCSS

.wrapper {
  position: relative;
  width: 140px;
  display: inline-block;
}

.product-stage-wrap {
  display: flex;
  position: relative;
  left: 0%;
  white-space: nowrap;
  width: 100%;
  transition: .1s;
}

.product-stage {
  overflow: hidden;
  width: 100%;
  &__img {
    display: inline-block;
  }
  &__img:not(:first-of-type) {
  }
  
  &__controls {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    pointer-events: none;
    button {
      position: absolute;
      left: 0;
      top: 50%;
      transform: translateY(-50%);
    }
    button:last-of-type {
      left: auto;
      right: 0;
    }
  }
}

.show-controls .product-stage__controls {
  opacity: 1;
  pointer-events: initial;
}

JavaScript

const gridSlideshows = document.querySelectorAll(".product-stage");

var i;
for (i = 0; i < gridSlideshows.length; i++) {
	const imgQty = gridSlideshows[i].querySelectorAll('.product-stage__img').length;
  const group = gridSlideshows[i];
	// Add Markup
	var currentHtml = gridSlideshows[i].innerHTML;
  gridSlideshows[i].innerHTML = '<div class="product-stage-wrap" style="left: 0%">'+currentHtml + '</div><div class="product-stage__controls"><button class="product-stage__prev">Prev</button><button class="product-stage__next">Next</button</div>';
  
  // Add MOUSE Event Listeners
   group.onmouseover = function(){
    this.classList.add('show-controls');
  }
  group.onmouseout = function(){
    this.classList.remove('show-controls');
  }
  group.onclick = function(e){
    var currentLeft = parseInt(group.querySelector('.product-stage-wrap').style.left);
    if(event.target.classList.contains('product-stage__prev')){
      e.preventDefault();
      if (currentLeft + 100 != 100){
        group.querySelector('.product-stage-wrap').style.left = (currentLeft + 100) + '%';
      }
    }
    else if(event.target.classList.contains('product-stage__next')){
      e.preventDefault();
      if (currentLeft - 100 > -1 * (imgQty * 100)){
        group.querySelector('.product-stage-wrap').style.left = (currentLeft - 100) + '%';
      }
    }
  } 
  
  group.addEventListener("touchmove", function(){
  	console.log('test');
  });
  
}