Search code examples
javascripthtmlcsscarousel

Add Progress Bar in Every Slide of the Carousel (JavaScript)


Have a Nice Saturday. I'm gonna ask something about adding progress bar in carousel which the progress bar code reference is in https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_progressbar_3. But after I apply it to my code, it doesn't work at all. It only showed that cannot set properties of undefined (setting 'width'). I'm very new in JavaScript, so please Help me to solve this everyone. Here's my snippet :

window.onload = function() {
  var slides = document.getElementsByClassName('carousel-item'),
      addActive = function(slide) {slide.classList.add('active-carousel')},
      removeActive = function(slide) {slide.classList.remove('active-carousel')},
      time = 3000,
      a = 0,
      timeLine = function() {if(a == 0) {a = 1; var elem = document.getElementsByClassName('progress-line'), width = 1, id = setInterval(frame,time/100); function frame() {if(width >= 100) {clearInterval(id); a = 0;} else {width++; elem.style.width = width + "%";}}}}; //this one I'm not sure the code is right
      
  addActive(slides[0]);
  
  setInterval(function () {
    for (var i = 0; i < slides.length; i++){
      if (i + 1 == slides.length) {
        addActive(slides[0]);
        timeLine(slides[0]);
        slides[0].style.zIndex = 3;
        slides[i].classList.add('show-carousel');
        setTimeout(function() {
          slides[i].classList.remove('show-carousel');
        },1000);
        setTimeout(removeActive, 500, slides[i]);
        break;
      }
      
      if (slides[i].classList.contains('active-carousel')) { 
        slides[i].classList.add('show-carousel');
        timeLine(slides[i + 1]);
        setTimeout(function() {
          slides[i].classList.remove('show-carousel');
        },1000);
        slides[i].removeAttribute('style');
        setTimeout(removeActive, 500, slides[i]);
        addActive(slides[i + 1]);
        break;
      }
    } 
  }, time);
}
*{box-sizing: border-box;}
.carousel {
  position: relative;
  width: 400px;
  height: 270px;
  overflow: hidden;
}
.carousel-item {
  display: none;
  flex-direction: column;
  position: absolute;
  width: 100%;
  height: 100%;
  border: none;
}

.progress-line {
  position: absolute;
  width: 0%;
  height: 2px;
  background-color: black;
  z-index: 9;
}

.active-carousel {
  display: flex;
  animation-name: slide-in;
  animation-duration: 1s;
}

@keyframes slide-in {
  0% {display: none; bottom: 100%;}
  1% {display: flex; bottom: 100%;}
  100% {display: flex; bottom: 0%;}
}
.show-carousel {
  display: flex;
  animation-name: slide-out;
  animation-duration: 1.1s;
}

@keyframes slide-out {
  0% {display: flex; bottom: 0%;}
  99% {display: flex; bottom: -100%;}
  100% {display: none; bottom: -100%;}
}

div {height: 100%;}
  .red {background-color: red;}
  .green {background-color: green;}
  .yellow {background-color: yellow;}
  .violet {background-color: violet;}
<div class="carousel">
  <div class="progress-line">
  </div>
  
  <div class="carousel-item">
    <div class="red"></div>
  </div>
  <div class="carousel-item">
    <div class="green"></div>
  </div>
  <div class="carousel-item">
    <div class="yellow"></div>
  </div>
  <div class="carousel-item">
    <div class="violet"></div>
  </div>
</div>


Solution

  • window.onload = function() {
      var slides = document.getElementsByClassName('carousel-item'),
          addActive = function(slide) {slide.classList.add('active-carousel')},
          removeActive = function(slide) {slide.classList.remove('active-carousel')},
          time = 3000,
          a = 0,
          timeLine = function() {if(a == 0) {a = 1; 
          let elem = document.querySelector('.progress-line');
          let width = 1;
    
          var id = setInterval(frame,time/100); 
          function frame() { if(width >= 100) { clearInterval(id); a = 0;} else {width++; elem.style.width = width + "%";}}}}; 
          
      addActive(slides[0]);
      
      setInterval(function () {
        for (var i = 0; i < slides.length; i++){
          if (i + 1 == slides.length) {
            addActive(slides[0]);
            timeLine(slides[0]);
            slides[0].style.zIndex = 3;
            slides[i].classList.add('show-carousel');
            setTimeout(function() {
              slides[i].classList.remove('show-carousel');
            },1000);
            setTimeout(removeActive, 500, slides[i]);
            break;
          }
          
          if (slides[i].classList.contains('active-carousel')) { 
            slides[i].classList.add('show-carousel');
            timeLine(slides[i + 1]);
            setTimeout(function() {
              slides[i].classList.remove('show-carousel');
            },1000);
            slides[i].removeAttribute('style');
            setTimeout(removeActive, 500, slides[i]);
            addActive(slides[i + 1]);
            break;
          }
        } 
      }, time);
    }
    *{box-sizing: border-box;}
    .carousel {
      position: relative;
      width: 400px;
      height: 270px;
      overflow: hidden;
    }
    .carousel-item {
      display: none;
      flex-direction: column;
      position: absolute;
      width: 100%;
      height: 100%;
      border: none;
    }
    
    .progress-line {
      position: absolute;
      width: 0%;
      height: 2px;
      background-color: black;
      z-index: 9;
    }
    
    .active-carousel {
      display: flex;
      animation-name: slide-in;
      animation-duration: 1s;
    }
    
    @keyframes slide-in {
      0% {display: none; bottom: 100%;}
      1% {display: flex; bottom: 100%;}
      100% {display: flex; bottom: 0%;}
    }
    .show-carousel {
      display: flex;
      animation-name: slide-out;
      animation-duration: 1.1s;
    }
    
    @keyframes slide-out {
      0% {display: flex; bottom: 0%;}
      99% {display: flex; bottom: -100%;}
      100% {display: none; bottom: -100%;}
    }
    
    div {height: 100%;}
      .red {background-color: red;}
      .green {background-color: green;}
      .yellow {background-color: yellow;}
      .violet {background-color: violet;}
    <div class="carousel">
      <div class="progress-line">
      </div>
      
      <div class="carousel-item">
        <div class="red"></div>
      </div>
      <div class="carousel-item">
        <div class="green"></div>
      </div>
      <div class="carousel-item">
        <div class="yellow"></div>
      </div>
      <div class="carousel-item">
        <div class="violet"></div>
      </div>
    </div>

    • var not work inside of function use let