Search code examples
jquerysliderreset

Reset Timer for flex slider on click


I am trying to create a flex slider following the example by w3schools.

Automatic sliding and new slide on click works like a charme, but I can't get my head wrapped around how to reset the timer each time I click on the buttons.

Yes, I have almost no experience with jquery/javascript and I have tested out resetTimer(), t.reset() and more stuff like that at almost every place I could somehow make sense of. Would be super glad if someone could help me out here.

Thanks to Sam0, I already edited the code - somewhere is still something wrong:

<script type="text/javascript">

var slideIndex = 0;
carousel();

var repeater;

function carousel() {
var i;
var x = document.getElementsByClassName("mySlides");
for (i = 0; i < x.length; i++) {
  x[i].style.display = "none";
}
slideIndex++;
if (slideIndex > x.length) {slideIndex = 1}
x[slideIndex-1].style.display = "block";
}

function cycle(){
setInterval(function(){
  carousel();
}, 5000);
}

cycle();

function cycle(r){

if (r){   // if r is true then clear and restart the timer
  clearInterval(repeater); // clear the timer
  repeater = setInterval(function(){ // start the timer
     carousel();
  }, 5000);
} else {
  clearInterval(repeater); // clear and stop the timer if r isn't true
}
}

cycle(true);


var slideIndex = 1;
showDivs(slideIndex);

function plusDivs(n) {
showDivs(slideIndex += n);
}

function currentDiv(n) {
cycle(true);
showDivs(slideIndex = n);
}

</script>

Solution

  • If you remove the setTimeout( call from the carousel() function and replace it with setInterval(), this will allow you to call the carousel function on a repeating timer.

    function cycle(){
       setInterval(function(){ 
          carousel(); 
       }, 5000);
    }
    
    cycle();
    

    We can then assign the setInterval() call to a private variable (which we define earlier outside of the function) we can then use as a handle to reset and restart the timer:

    var repeater;
    
    function cycle(r){
    
       if (r){   // if r is true then clear and restart the timer
          clearInterval(repeater); // clear the timer
          repeater = setInterval(function(){ // start the timer
             carousel(); 
          }, 5000);
       } else {
          clearInterval(repeater); // clear and stop the timer if r isn't true
       }
    }
    
    cycle(true);
    

    now you can call cycle(false) at any point to stoop the timer, and calling cycle(true) should reset and restart the timer as the variable repeater can only hold one value at a time. If you want to reset the timer each time one of your buttons is clicked then add the cycle(true) anywhere inside your currentDiv() function like so:

    function currentDiv(n) {
        cycle(true);
        showDivs(slideIndex = n);
    }
    

    UPDATE:

    Large snippet below with adapted version of the OP's edited code and the w3schools code for tinkering.

      var i;
      var slides = document.getElementsByClassName("mySlides");
      var dots = document.getElementsByClassName("dot");
      var slideIndex = -1;
      var repeater;
    
      function carousel() {
    
        for (i = 0; i < slides.length; i++) {
          slides[i].style.display = "none";
        } // cycle through and hide all the images
    
        slideIndex++;
    
        if (slideIndex > slides.length) {
          slideIndex = 1;
        } else if (slideIndex <= 0) {
          slideIndex = slides.length;
        } // what to do if slideIndex is too high or too low
    
        slides[slideIndex - 1].style.display = "block";
        // show the relevant slide
      }
    
      function cycle(r) {
    
        if (r) { // if r is true then clear and restart the timer
          clearInterval(repeater); // clear the timer
          repeater = setInterval(function() { // start the timer
            carousel();
          }, 5000);
        } else {
          clearInterval(repeater); // clear and stop the timer if r isn't true
        }
      }
    
      window.onload = function() {
        carousel();
      }; // show the start image on load
    
      carousel();
      cycle(true);
    
    
      function plusDivs(n) {
        cycle(true);
        slideIndex += n - 1;
        carousel();
      }
    
      function currentDiv(n) {
        cycle(true);
        slideIndex = n - 1;
        carousel();
      }
    * {
      box-sizing: border-box
    }
    body {
      font-family: Verdana, sans-serif;
      margin: 0
    }
    .mySlides {
      display: none
    }
    /* Slideshow container */
    
    .slideshow-container {
      max-width: 1000px;
      position: relative;
      margin: auto;
    }
    /* Next & previous buttons */
    
    .prev,
    .next {
      cursor: pointer;
      position: absolute;
      top: 50%;
      width: auto;
      padding: 16px;
      margin-top: -22px;
      color: white;
      font-weight: bold;
      font-size: 18px;
      transition: 0.6s ease;
      border-radius: 0 3px 3px 0;
    }
    /* Position the "next button" to the right */
    
    .next {
      right: 0;
      border-radius: 3px 0 0 3px;
    }
    /* On hover, add a black background color with a little bit see-through */
    
    .prev:hover,
    .next:hover {
      background-color: rgba(0, 0, 0, 0.8);
    }
    /* Caption text */
    
    .text {
      color: #f2f2f2;
      font-size: 15px;
      padding: 8px 12px;
      position: absolute;
      bottom: 8px;
      width: 100%;
      text-align: center;
    }
    /* Number text (1/3 etc) */
    
    .numbertext {
      color: #f2f2f2;
      font-size: 12px;
      padding: 8px 12px;
      position: absolute;
      top: 0;
    }
    /* The dots/bullets/indicators */
    
    .dot {
      cursor: pointer;
      height: 13px;
      width: 13px;
      margin: 0 2px;
      background-color: #bbb;
      border-radius: 50%;
      display: inline-block;
      transition: background-color 0.6s ease;
    }
    .active,
    .dot:hover {
      background-color: #717171;
    }
    /* Fading animation */
    
    .fade {
      -webkit-animation-name: fade;
      -webkit-animation-duration: 1.5s;
      animation-name: fade;
      animation-duration: 1.5s;
    }
    @-webkit-keyframes fade {
      from {
        opacity: .4
      }
      to {
        opacity: 1
      }
    }
    @keyframes fade {
      from {
        opacity: .4
      }
      to {
        opacity: 1
      }
    }
    /* On smaller screens, decrease text size */
    
    @media only screen and (max-width: 300px) {
      .prev,
      .next,
      .text {
        font-size: 11px
      }
    }
    <h2>Automatic Slideshow</h2>
    <p>Change image every 5 seconds:</p>
    
    <div class="slideshow-container">
    
      <div class="mySlides fade">
        <div class="numbertext">1 / 3</div>
        <img src="http://www.w3schools.com/howto/img_nature_wide.jpg" style="width:100%">
        <div class="text">Caption Text</div>
      </div>
    
      <div class="mySlides fade">
        <div class="numbertext">2 / 3</div>
        <img src="http://www.w3schools.com/howto/img_fjords_wide.jpg" style="width:100%">
        <div class="text">Caption Two</div>
      </div>
    
      <div class="mySlides fade">
        <div class="numbertext">3 / 3</div>
        <img src="http://www.w3schools.com/howto/img_mountains_wide.jpg" style="width:100%">
        <div class="text">Caption Three</div>
      </div>
      <a class="prev" onclick="plusDivs(-1)">❮</a>
      <a class="next" onclick="plusDivs(1)">❯</a>
    </div>
    <br>
    
    <div style="text-align:center">
      <span class="dot" onclick="currentDiv(1)"></span> 
      <span class="dot" onclick="currentDiv(2)"></span> 
      <span class="dot" onclick="currentDiv(3)"></span> 
    </div>