Saturday 20 June 2020

Web Tutorial: The Slide Carousel (Part 3/3)

Right! We're at the final part and probably the most important. The slide carousel, as it stands, works. But we want it to slide slowly, not instantly. And we want it to slide on its own without clicking on the buttons. We'll be taking care of it today.

Go to the slide() method. Declare the variable currentMarginLeft.
slide: function(dir)
{
    var nextSlide;
    var currentMarginLeft;
    var nextMarginLeft;


In the If blocks, set the value of currentMarginLeft as well. For sliding left, currentMarginLeft is 0 and nextMarginLeft is -100. It's reversed for sliding right.
var nextSlide;
var currentMarginLeft;
var nextMarginLeft;

if (dir == "left")
{
    if (this.currentSlideIndex == this.slides.length - 1)
    {
        nextSlide = 0;
    }
    else
    {
        nextSlide = this.currentSlideIndex + 1;
    }

    currentMarginLeft = 0;
    nextMarginLeft = -100;
}

if (dir == "right")
{
    if (this.currentSlideIndex == 0)
    {
        nextSlide = this.slides.length - 1;
    }
    else
    {
        nextSlide = this.currentSlideIndex - 1;
    }   

    currentMarginLeft = -100;
    nextMarginLeft = 0;
}


Call the setTransitionSpeed() method with an argument of 0 before the If blocks.
var nextSlide;
var currentMarginLeft;
var nextMarginLeft;

this.setTransitionSpeed(0);

if (dir == "left")
{
    if (this.currentSlideIndex == this.slides.length - 1)
    {
        nextSlide = 0;
    }
    else
    {
        nextSlide = this.currentSlideIndex + 1;
    }

    currentMarginLeft = 0;
    nextMarginLeft = -100;
}

if (dir == "right")
{
    if (this.currentSlideIndex == 0)
    {
        nextSlide = this.slides.length - 1;
    }
    else
    {
        nextSlide = this.currentSlideIndex - 1;
    }   

    currentMarginLeft = -100;
    nextMarginLeft = 0;
}


This method basically sets contentContainer's transition speed, in seconds, to the value specified by interval. We passed in 0 just now, so it's still instantaneous. But that's by design...
slide: function(dir)
{
    var nextSlide;
    var currentMarginLeft;
    var nextMarginLeft;

    this.setTransitionSpeed(0);

    if (dir == "left")
    {
        if (this.currentSlideIndex == this.slides.length - 1)
        {
            nextSlide = 0;
        }
        else
        {
            nextSlide = this.currentSlideIndex + 1;
        }

        currentMarginLeft = 0;
        nextMarginLeft = -100;
    }

    if (dir == "right")
    {
        if (this.currentSlideIndex == 0)
        {
            nextSlide = this.slides.length - 1;
        }
        else
        {
            nextSlide = this.currentSlideIndex - 1;
        }   

        currentMarginLeft = -100;
        nextMarginLeft = 0;
    }

    this.setContent(nextSlide, dir);

    this.setMargin(nextMarginLeft);
    this.currentSlideIndex = nextSlide;
},
setTransitionSpeed: function(interval)
{
    this.contentContainer.style.webKitTransition = interval + "s all";
    this.contentContainer.style.transition = interval + "s all";
},
setMargin: function(margin)
{
    this.contentContainer.style.marginLeft = margin + "%";
},


...because we want this part to be instant. We call the setMarginLeft() method and pass in the value of currentMarginLeft.
slide: function(dir)
{
    var nextSlide;
    var currentMarginLeft;
    var nextMarginLeft;

    this.setTransitionSpeed(0);

    if (dir == "left")
    {
        if (this.currentSlideIndex == this.slides.length - 1)
        {
            nextSlide = 0;
        }
        else
        {
            nextSlide = this.currentSlideIndex + 1;
        }

        currentMarginLeft = 0;
        nextMarginLeft = -100;
    }

    if (dir == "right")
    {
        if (this.currentSlideIndex == 0)
        {
            nextSlide = this.slides.length - 1;
        }
        else
        {
            nextSlide = this.currentSlideIndex - 1;
        }   

        currentMarginLeft = -100;
        nextMarginLeft = 0;
    }

    this.setMargin(currentMarginLeft);
    this.setContent(nextSlide, dir);

    this.setMargin(nextMarginLeft);
    this.currentSlideIndex = nextSlide;


Then we introduce the setTimeout() function to run the setTransitonSpeed() method with an interval of 1 second, after a delay of 250 milliseconds. Look up some information on setTimeout() here.
    this.setMargin(currentMarginLeft);
    this.setContent(nextSlide, dir);

    setTimeout
    (
        function()
        {
            carousel.setTransitionSpeed(1);
        },
        250
    );

    this.setMargin(currentMarginLeft);
    this.setContent(nextSlide, dir);


Then we enclose the next code block in another setTimeout() function call. This one will execute after 500 milliseconds.
setTimeout
(
    function()
    {
        carousel.setTransitionSpeed(1);
    },
    250
);

setTimeout
(
    function()
    {
        this.setMargin(currentMarginLeft);
        this.setContent(nextSlide, dir);
    },
    500
);


Use the object name instead of this. Because this can't be relied on to refer to what you think it refers to when called from inside a callback.
setTimeout
(
    function()
    {
        carousel.setMargin(currentMarginLeft);
        carousel.setContent(nextSlide, dir);
    },
    500
);


Now you see it sliding slowly from right to left, or left to right.

Automating this slider

This one's easy enough. We've already established that sliding left and right works, so all that's left to do is automate this.

In the carousel object, add a property, canMove, and set it to true by default.
currentSlideIndex: 0,
contentContainer: undefined,
c0: undefined,
c1: undefined,
canMove: true,
begin: function()
{
    this.contentContainer = document.getElementById("contentContainer");
    this.c0 = document.getElementById("content0");
    this.c1 = document.getElementById("content1");

    this.setContent(this.currentSlideIndex + 1, "left");               
},


In the begin() method, use the setInterval() function to run the animateSlider() method every 5 seconds. Here's some info on the setInterval() function.
currentSlideIndex: 0,
contentContainer: undefined,
c0: undefined,
c1: undefined,
canMove: true,
begin: function()
{
    this.contentContainer = document.getElementById("contentContainer");
    this.c0 = document.getElementById("content0");
    this.c1 = document.getElementById("content1");

    this.setContent(this.currentSlideIndex + 1, "left");

    setInterval
    (
        function()
        {
            carousel.animateSlider();
        },
        5000
    );                   
},   


Create the animateSlider() method.
begin: function()
{
    this.contentContainer = document.getElementById("contentContainer");
    this.c0 = document.getElementById("content0");
    this.c1 = document.getElementById("content1");

    this.setContent(this.currentSlideIndex + 1, "left");

    setInterval
    (
        function()
        {
            carousel.animateSlider();
        },
        5000
    );                   
},       
animateSlider: function()
{

},


Check to see if canMove is true, and call the slide() method with an argument of "left" if so.
animateSlider: function()
{
    if (this.canMove)
    {
        this.slide("left");   
    }
},


Set canMove to false whenever a button is clicked. This means that the slider will no longer move automatically. Because it would be annoying if you were scrolling to see something and the slider moved by itself, possibly sooner than you'd like or in the opposite direction.
sliderButtonClick: function(dir)
{
    this.canMove = false;
    this.slide(dir);
}


And then every time after the slide() method is run, set canMove to true after 5 seconds. This way, after roughly 5 seconds, if you stop clicking on the buttons, the carousel will resume moving!
slide: function(dir)
{
    var nextSlide;
    var currentMarginLeft;
    var nextMarginLeft;

    this.setTransitionSpeed(0);

    if (dir == "left")
    {
        if (this.currentSlideIndex == this.slides.length - 1)
        {
            nextSlide = 0;
        }
        else
        {
            nextSlide = this.currentSlideIndex + 1;
        }

        currentMarginLeft = 0;
        nextMarginLeft = -100;
    }

    if (dir == "right")
    {
        if (this.currentSlideIndex == 0)
        {
            nextSlide = this.slides.length - 1;
        }
        else
        {
            nextSlide = this.currentSlideIndex - 1;
        }   

        currentMarginLeft = -100;
        nextMarginLeft = 0;
    }

    this.setMargin(currentMarginLeft);
    this.setContent(nextSlide, dir);

    setTimeout
    (
        function()
        {
            carousel.setTransitionSpeed(1);
        },
        250
    );

    setTimeout
    (
        function()
        {
            carousel.setMargin(nextMarginLeft);
            carousel.currentSlideIndex = nextSlide;
        },
        500
    );

    setTimeout
    (
        function()
        {
            carousel.canMove = true;
        },
        5000
    );
},


Turn off the red outlines.
div {outline: 0px solid #FF0000;}


Now this is what it looks like. It should move every 5 seconds.

Some little niceties

Remember we left the content properties of the elements in the slides array were all empty strings? Let's set them to some random text and HTML.
slides:
[
    {
        bg: "00.jpg",
        content: "<div><h2>Phasellus ullamcorper</h2><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent fringilla molestie pellentesque. Aliquam auctor scelerisque mattis. Donec maximus ipsum non eros gravida suscipit. Sed vulputate massa orci, non placerat lectus suscipit mollis. Fusce faucibus lorem eu lectus mattis, et dictum urna semper. Maecenas massa magna, commodo at pulvinar ac, lacinia nec augue. Nullam pretium consectetur ultricies. In a mattis justo. Suspendisse potenti. Vivamus scelerisque, urna imperdiet faucibus facilisis, orci elit dictum ex, blandit rutrum metus diam eget mi. Phasellus ullamcorper eu purus eu venenatis. Nullam vestibulum dolor vel felis facilisis, ac rutrum tellus rutrum. Sed vehicula elementum erat, eget mattis tortor rhoncus a. Phasellus ut nisl volutpat, dictum lectus ut, dictum lectus.</p><h2>Quisque pharetra</h2><p>Lorem ipsum vel felis facilisis, ac rutrum tellus rutrum. Sed vehicula elementum erat, eget mattis tortor rhoncus a.</p><p>Vestibulum porta mattis quam a gravida. Aliquam quis quam nulla.</p></div>"
    },
    {
        bg: "01.jpg",
        content: "<div><h2>Phasellus mattis</h2><p>Lorem ipsum vel felis facilisis, ac rutrum tellus rutrum. Sed vehicula elementum erat, eget mattis tortor rhoncus a.</p></div>"
    },
    {
        bg: "02.jpg",
        content: "<div><h2>In diam nisi erat</h2><p>Vestibulum porta mattis quam a gravida. Aliquam quis quam nulla. Pellentesque nisi erat, elementum ut maximus sed, euismod vel dui. Curabitur vitae dui nec justo rhoncus imperdiet. In diam risus, egestas dictum viverra vel, pretium sed nisl.</p></div>"
    },
    {
        bg: "03.jpg",
        content: "<div><h2>Nullam ullamcorper</h2><p>Lorem ipsum scelerisque, urna imperdiet faucibus facilisis, orci elit dictum ex, blandit rutrum metus diam eget mi. Phasellus ullamcorper eu purus eu venenatis. Nullam vestibulum dolor vel felis facilisis, ac rutrum tellus rutrum. Sed vehicula elementum erat, eget mattis tortor rhoncus a. Phasellus ut nisl volutpat, dictum lectus ut, dictum lectus.</p><h2>Quisque pharetra</h2><p><img src='img/03.jpg' height='150' align='right' />Vestibulum porta mattis quam a gravida. Aliquam quis quam nulla. Pellentesque nisi erat, elementum ut maximus sed, euismod vel dui. Curabitur vitae dui nec justo rhoncus imperdiet. In diam risus, egestas dictum viverra vel, pretium sed nisl. Nam mi risus, imperdiet sed purus id, posuere feugiat nibh. Curabitur dignissim ipsum eget est pretium, ut luctus leo dapibus. Praesent in vehicula felis. Nullam quis faucibus justo. Praesent ac turpis tempor elit lobortis sodales laoreet pulvinar velit. Nam vel leo arcu. Cras magna nulla, lacinia in turpis vel, efficitur sagittis sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. In congue consectetur lacus, ac venenatis elit gravida at.</p></div>"
    },
    {
        bg: "04.jpg",
        content: "<div><h2>Quisque pharetra</h2><p>Quisque eget aliquam urna. Integer tortor justo, fringilla ut diam in, ornare maximus sem. Nam dictum mauris nisl, id posuere sem sodales sit amet. Sed ac nulla ut nunc molestie vestibulum id a ipsum. Duis nec elementum libero. Etiam porttitor turpis eu venenatis porta. Quisque pharetra diam vel dui porta luctus. Duis sed odio viverra, molestie orci et, hendrerit erat. Duis ut tortor nec orci suscipit finibus nec non massa. </p></div>"
    }
],


Hmm, we'll need some styling here.


We'll style all divs inside content with padding, a translucent white background, round corners and all that jazz.
.content
{
    width: 50%;
    height: 100%;
    float: left;
    background-color: #000044;
    background-size: cover;
    background-position: 50% 50%;
    background-repeat: no-repeat;
    padding-top: 1em;               
}

.content div
{
    padding: 1em;
    background-color: rgba(255, 255, 255, 0.5);
    color: rgba(0, 0, 0, 1);
    font-weight: bold;
    width: 80%;
    border-radius: 5px;
    margin: 0 auto 0 auto;
}


See, HTML works here too!


Nice, we have a carousel!

This was done in vanilla JavaScript. Could probably have done it much easier in the numerous JavaScript frameworks in the tech stratosphere, but I believe in the importance of starting from the basics. And this is how you implement a simple slide carousel with basic tools.

Happy carousing,
T___T

No comments:

Post a Comment