What is autoplay?

Have you ever come across a slider on a website which navigates automatically? A slider where you don't have to press any button whatsoever to go from one slide to another - it all happens on itself.

Don't you think it is amazing to have this feature on a slider? Perhaps it would've been even more amazing if we could somehow incorporate this idea into our very own slider and this is what this chapter is all about.

How it works?

The whole idea behind slides navigating automatically is to call a function that navigates them, repeatedly, after a certain time interval.

In our case the function is navigateSlider() and so what we are left with is only to figure out a way to repeatedly invoke this function.

Can you think of a way?

If you've read the chapter on JavaScript Timers, you would definitely have an answer right away.

The easiest way to execute a function repeatedly is to use the global method setInterval().

setInterval() takes two arguments - the first one is the function to be called repeatedly and the second one is the time interval between the calls (given in milliseconds).

For example, if we wanted to call a function someFunc() after every 5s we would write:

setInterval(someFunc, 5000);

First we provide the function to be called again and again, and then the time interval as a number, in milliseconds.

Note that 1s = 1000ms, therefore 5s = 5000ms.

Now that you know what is meant by the term automatic navigation and even how to get a simple function be called continually, it's time to work on taking the idea into our slider!

Implementation

Before we jump into writing the automation code, recall what needs to be done in order to perform a forward navigation of the slider.

First increment index, and consequently call navigateSlider().

The same would also need to be done in conjunction with setInterval(), but at least not by passing the function navigateSlider directly as shown below:

setInterval(navigateSlider, 5000);
// index++ is missing!

Here we've skipped the incrementing expression of index, that actually enables the slider's navigation. Writing this code will mean navigating to the current index everytime after 5 seconds - clearly not what we want!

What we ought to do instead, is to create another function, add both these statements within it, and finally pass it to setInterval(). This simple technique will be sufficient to solve our simple problem!

Now whether the function shall be named or anonymous is your choice - we'll go with the latter.

Following is the correct code:

setInterval(function() {
    index++; // incrementing index
    navigateSlider(); // then navigate
}, 5000);

Executing this would result in an anonymous function being called after every 5s, which increments index and then invokes navigateSlider().

Now despite the fact that this code works well, it doesn't provide us much of a control over the entire automation logic.

For instance, to change the interval's time we have to come up at the location of this code in our script and then make the alteration likewise. Furthermore, to disable this functionality, we only have the option to comment this code out, and nothing else!

When developing applications, libraries, components like these; or simple anything in JavaScript we have to think in an efficient and extensible way - one which makes it easy for us to go over the code and make given changes quickly.

For the case above, we can make two basic additions to it to give it a lot more flexibility:

  1. Create a global variable timeInterval to hold setInterval()'s second argument.
  2. Create a global Boolean variable automate to indicate whether automation shall be done or not. If it's true only then do we proceed with the code above.

Summarising both these idea we get the following:

var time = 5000;
var automate = true;

if (automate) {
    setInterval(function() {
        index++;
        navigateSlider();
    }, time);
}
Currently, we've preset automate to true to get things working. However, in a real scenario we'll leave this is upto the developer to explicitly specify, somewhere in his code, whether automation is needed. We'll see what this means later in this tutorial.

And this automates our simple slider ensuring that in the process we can, at any time, navigate from the current slide to the next or previous one without getting into any sort of errors.

Basic Automatic Slider

Simple, wasn't it?

A slight problem..

Although this code works perfectly, there is a slight problem with it.

If the user is interacting with the slider, for example clicking the navigation buttons, we ideally want to clear the current interval and start a new one. In other words, we want to reset the timer.

This is to prevent any unexpected navigations from happening, let's say when the user is reading something within the current slide. However just figuring out the fact of clearing the interval isn't enough - we have to also figure out the exact place where we would accomplish this.

We leave this as a quick, short exercise for you to do on your own and try to come up with a location in our previously developed script where the logic for clearing the interval can be set up.

Perhaps the best place to clear the ongoing interval is inside navigateSlider().

A couple of reasons contribute to this:

  1. Each time we make a navigation, be it using the navigation buttons, key strokes (as we shall see later in this tutorial), touch gestures etc, we want to reset the timer to start all over again. Since all these events call navigateSlider(), therefore it makes sense to add the interval logic directly within it.
  2. There's no point of adding this logic separately inside the handlers for all the events discussed in 1). It will lead to less maintainable code and even lead to a lot of repetition - one of the worst things that can be present in code.

Sifting navigateSlider() for the implementation details of this feature, we see that first we need to check for automate and proceed only if it evaluates to true. Once this happens we need to clear the interval using clearInterval() and then set it using setInterval().

Had we done this the other way round i.e by first setting the timer and then clearing it, we would've actually broken the automation feature!

By first calling clearInterval() we ensure that the ongoing timer is put to a halt and then, by setInterval(), we ensure that a new one is begun for the same time interval.

You'll see this clear-then-set combination quite often in applications out there for similar use cases - all boiling down to resetting a timer.

So let's finally incorporate this idea into our slider navigateSlider() function:

function navigateSlider() {

    if (automate) {
        // clear the ongoing interval
        clearInterval(id);

        // then start a new one
        id = setInterval(function() {
            index++;
            navigateSlider();
       }, time);
    }
    
    // rest of the code
}

First we'll perform a check for automation and proceed if it's desired (that is, automate is true), by obviously first clearing the interval (in line 5) and then starting a new one (in line 8).

The last // rest of the code comment here is a placeholder for the segment inside navigateSlider() that we developed in the previous Pagination chapter. We've omitted it only to favour readability - you obviously will need it!
If you need to know how the function setInterval() works in JavaScript you can go to JavaScript Timers.

Thinking efficiently

If you are a believer of the DRY (Don't Repeat Yourself) principle in programming, then you would've surely picked up one problem in the code above.

It involves repetition!

Notice that the code to set an interval appears twice - first within the outer scope of our script, inside the if block and then inside the definition for navigateSlider().

The code present in both these locations is exactly the same and therefore must be grouped into one single unit.

Whenever we encounter repetitive pieces of code in a program, we must try our best to come up with a way to group them together in a function, and use that instead.

For our case, not only will we group the call to setInterval() inside a separate function but also create a global object Automation that will encapsulate all the functionalities for our automation feature.

These functionalities are:

  1. The time interval, in milliseconds
  2. Setting an interval using setInterval()
  3. Clearing the interval using clearInterval()
  4. Saving the interval's ID to be passed to clearInterval()

So in simple terms, rather than creating mutiple functions like startTimer() or resetTimer() in the outer scope, we'll create them under the object Automation to keep things well-structured and separate within their respective namespaces.

Following is the definition of Automation. Observe the names we've used for the methods and how do they speak out their underlying purpose in a quick and precise manner.

var Automation = {
    // the id used to clear the interval
    id: null,

    // the time interval, in milliseconds
    // for now, we use a dummy value 5000
    time: 5000,

    // start a new interval
    start: function() {
        this.id = setInterval(function() {
            index++;
            navigateSlider();
       }, this.time);
    },

    // reset the interval
    reset: function() {
        clearInterval(this.id);
        this.start();
    }
}

The property id is given to temporarily hold the ID returned by setInterval() to be passed to clearInterval() for clearing the respective interval.

The property time is created in place of the global time variable we created before. Since time is something more related to the automation functionality, the Automation object serves to hold it rather than the global object.

Make sure to remove the global time variable from your code!

The method start() solves the repetition problem we were discussing previously and serves to simply start a new interval.

Finally the method reset(), does the job we desired within navigateSlider() earlier i.e first it clears the ongoing interval and then starts a new one. In other words, it resets the interval.

You can also create a method stop() here, to clear the interval instead of calling clearInterval() directly - it's all your choice! We've skipped it because it would've otherwise introduced more identifiers into our program, for no special reason!

With this object in place, we can now rewrite our old code snippets using its methods:

var automate = true;

if (automate) {
    Automation.start();
}
function navigateSlider() {
    if (automate) {
        // reset the interval
        Automation.reset();
    }
    // rest of the code
}
If you know there is nothing as such in the slider that will take the user a long time to read, you can consider ignoring this preventing automation feature.

Rectified Automatic Slider

In conclusion

And this concludes our slider's automatic navigation, self transition, interval-based invocation chapter, whatever you like to call it.

Some of you might think that we could've also used setTimeout() for the automation task above and that is absolutely alright, but surely with less simplicity. You'll have to recursively call setTimeout() inside a named function (instead of the anonymous function above in setInterval()) which would've only been a comparative mess to the simple and easy approach discussed above.

Remember the principle KISS - Keep It Simple Stupid and you'll arguably be all good in programming!