Wednesday, 17 June 2020

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

Now that we have the HTML layout up, JavaScript is what makes this thing run. We'll run this entire thing from one object, carousel.

slides is an array of content for the slides, which we will populate later. currentSlideIndex is an integer that starts at 0 and is used to point to the current element of slides.
<script>
    var carousel =
    {
        slides:
        [

        ],
        currentSlideIndex: 0
    }
</script>


currentContainer, c0 and c1 are variables used to hold the DOM objects that will be frequently referred to.
<script>
    var carousel =
    {
        slides:
        [

        ],
        currentSlideIndex: 0,
        contentContainer: undefined,
        c0: undefined,
        c1: undefined
    }
</script>


Finally, the methods. begin() is the method that's run when the entire page is loaded. slide() accepts a parameter, dir, which defines whether the display should slide left or right. sliderButtonClick() simply calls slide(), passing in whatever value it received, as the argument.
<script>
    var carousel =
    {
        slides:
        [

        ],
        currentSlideIndex: 0,
        contentContainer: undefined,
        c0: undefined,
        c1: undefined,
        begin: function()
        {
       
        },               
        slide: function(dir)
        {

        },
        sliderButtonClick: function(dir)
        {
            this.slide(dir);
        }
    }
</script>


In the onload attribute of the bdy tag, make sure the begin() method is called. In the buttons, ensure that when clicked, they call the sliderButtonClick() method, passing in "left" and "right" as arguments. This won't do anything for now because begin() is empty. sliderButtonClick() is not empty, but the method it calls, slide(), certainly is.
<body onload = "carousel.begin();">
    <div id="carouselContainer">
        <div class="margin">
            <input type="button" onclick="carousel.sliderButtonClick('left')" value="&#9668;"/>
        </div>

        <div id="viewport">
            <div id="contentContainer">
                <div id="content0" class="content"></div>
                <div id="content1" class="content"></div>
            </div>
        </div>

        <div class="margin">
            <input type="button" onclick="carousel.sliderButtonClick('right')" value="&#9658;"/>
        </div>   
    </div>
</body>


Next, let's update the slides array. Each element is an object with the properties bg and content. content will be set to an empty string for now, but bg will hold the filenames of the images.
var carousel =
{
    slides:
    [
        {
            bg: "00.jpg",
            content: ""
        },
        {
            bg: "01.jpg",
            content: ""
        },
        {
            bg: "02.jpg",
            content: ""
        },
        {
            bg: "03.jpg",
            content: ""
        },
        {
            bg: "04.jpg",
            content: ""
        }
    ],
    currentSlideIndex: 0,
    contentContainer: undefined,
    c0: undefined,
    c1: undefined,
    begin: function()
    {
   
    },               
    slide: function(dir)
    {

    },
    sliderButtonClick: function(dir)
    {
        this.slide(dir);
    }
}


We'll set up the begin() method next, because it's the first thing to be run when the page loads. In here, we set the contentContainer, c0 and c1 properties to the objects in the DOM.
begin: function()
{
    this.contentContainer = document.getElementById("contentContainer");
    this.c0 = document.getElementById("content0");
    this.c1 = document.getElementById("content1");
},


Then we run the setContent() method. We will pass in the currentslideIndex property plus 1, and the string "left" as arguments.
begin: function()
{
    this.contentContainer = document.getElementById("contentContainer");
    this.c0 = document.getElementById("content0");
    this.c1 = document.getElementById("content1");

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


Now create the method.
slide: function(dir)
{

},
setContent: function(next, dir)
{

},
sliderButtonClick: function(dir)
{
    this.slide(dir);
}


setContent() is a method that accepts two parameters - next and dir. next is the slide after the current slide. Remember we passed in the currentslideIndex property plus 1? That's why. And dir is the direction the slider will slide in. For now, we'll only handle the case for "left", but feel free to add an If block for "right" too.
setContent: function(next, dir)
{
    if (dir == "left")
    {

    }

    if (dir == "right")
    {

    }
},


First, we set c0's innerHTML property to the content property of the current element of slides pointed to by currentSlideIndex. Since all of the content properties are empty strings at the moment, this doesn't do much.
setContent: function(next, dir)
{
    if (dir == "left")
    {
        this.c0.innerHTML = this.slides[this.currentSlideIndex].content;
    }

    if (dir == "right")
    {

    }
},


Then  we set c0's background image to the bg property.
setContent: function(next, dir)
{
    if (dir == "left")
    {
        this.c0.innerHTML = this.slides[this.currentSlideIndex].content;
        this.c0.style.backgroundImage = "url(img/" + this.slides[this.currentSlideIndex].bg + ")";
    }

    if (dir == "right")
    {

    }
},


Do the same for c1, but the element pointed to in slides will be decided by next.
setContent: function(next, dir)
{
    if (dir == "left")
    {
        this.c0.innerHTML = this.slides[this.currentSlideIndex].content;
        this.c0.style.backgroundImage = "url(img/" + this.slides[this.currentSlideIndex].bg + ")";

        this.c1.innerHTML = this.slides[next].content;
        this.c1.style.backgroundImage = "url(img/" + this.slides[next].bg + ")";
    }

    if (dir == "right")
    {

    }
},


Ack, that's hideous. Let's clean this up a bit.


Style content to ensure that background covers the whole of the div and doesn't repeat.
.content
{
    width: 50%;
    height: 100%;
    float: left;
    background-color: #000044;
    background-size: cover;
    background-position: 50% 50%;
    background-repeat: no-repeat;   
}


Much, much better. Now you can clearly see that content0 has 00.jpg as its background, and content01 has 01.jpg.


Great! Now it's time we did the slide() method. Remember when you click the button, it calls the sliderButtonClick() method with "left" as an argument, which in turn calls slide() with "left" as an argument? We'll be handling that.

Declare variables nextSlide and nextMarginLeft. And add two If blocks - one for "left" and one for "right". Again, we will only handle the first case for now.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

    if (dir == "left")
    {

    }

    if (dir == "right")
    {

    }
},


If we're sliding left, obviously nextSlide is the value of currentSlideIndex plus 1.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

    if (dir == "left")
    {
        nextSlide = this.currentSlideIndex + 1;
    }

    if (dir == "right")
    {

    }
},


Now remember we have a finite amount of elements in slides. So if currentSlideIndex is already pointing to the last element of slides, nextSlide is 0.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

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

    if (dir == "right")
    {

    }
},


nextMarginLeft is -100. This is in percentages. So after this, we will set the left margin to -100%.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

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

        nextMarginLeft = -100;
    }

    if (dir == "right")
    {

    }
},


This is done by running the setMarginLeft() method and passing in currentMarginLeft as an argument. But before that, run the setContent() method, passing in nextSlide and dir as arguments.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

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

        nextMarginLeft = -100;
    }

    if (dir == "right")
    {

    }

    this.setContent(nextSlide, dir);

    this.setMargin(nextMarginLeft);
},


And after that,  set the currentSlideIndex property to nextSlide.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

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

        nextMarginLeft = -100;
    }

    if (dir == "right")
    {

    }

    this.setContent(nextSlide, dir);

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


Time to create the setMargin() method. It has a parameter, margin. Basically, what it does is set contentContainer's left margin to margin %.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

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

        nextMarginLeft = -100;
    }

    if (dir == "right")
    {

    }

    this.setContent(nextSlide, dir);

    this.setMargin(nextMarginLeft);
    this.currentSlideIndex = nextSlide;
},
setMargin: function(margin)
{
    this.contentContainer.style.marginLeft = margin + "%";
},
setContent: function(next, dir)
{
    if (dir == "left")
    {
        this.c0.innerHTML = this.slides[this.currentSlideIndex].content;
        this.c0.style.backgroundImage = "url(img/" + this.slides[this.currentSlideIndex].bg + ")";

        this.c1.innerHTML = this.slides[next].content;
        this.c1.style.backgroundImage = "url(img/" + this.slides[next].bg + ")";
    }

    if (dir == "right")
    {

    }
},


Click on the left button. You should see contentContainer shifts to the left!


Let's style viewport. Set the overflow property to hidden. While we're at it, give it round corners.
#viewport
{
    width: 80%;
    height: 100%;
    float: left;
    overflow: hidden;
    border-radius: 15px;
}


Now with only room for one content div at a time, you can click on the left button to your heart's content, and see all the pictures scroll!


Let's settle the "right" case now. Since it's sliding right, the next slide to come into view should be the previous slide.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

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

        nextMarginLeft = -100;
    }

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

    this.setContent(nextSlide, dir);

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


Unless, of course currentSlideIndex is already 0. In which case you set it to the index of the last element in slides.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

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

        nextMarginLeft = -100;
    }

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

    this.setContent(nextSlide, dir);

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


And then nextMarginLeft is set to 0.
slide: function(dir)
{
    var nextSlide;
    var nextMarginLeft;

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

        nextMarginLeft = -100;
    }

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

        nextMarginLeft = 0;
    }

    this.setContent(nextSlide, dir);

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


In the setContent() method, let's cater for "right". It's the same as for "left", but next and currentSlideIndex reverse positions.
setContent: function(next, dir)
{
    if (dir == "left")
    {
        this.c0.innerHTML = this.slides[this.currentSlideIndex].content;
        this.c0.style.backgroundImage = "url(img/" + this.slides[this.currentSlideIndex].bg + ")";

        this.c1.innerHTML = this.slides[next].content;
        this.c1.style.backgroundImage = "url(img/" + this.slides[next].bg + ")";
    }

    if (dir == "right")
    {
        this.c0.innerHTML = this.slides[next].content;
        this.c0.style.backgroundImage = "url(img/" + this.slides[next].bg + ")";

        this.c1.innerHTML = this.slides[this.currentSlideIndex].content;
        this.c1.style.backgroundImage = "url(img/" + this.slides[this.currentSlideIndex].bg + ")";
    }
},


Now if you click on the right button, you will see the sequence of images go from the slides with the highest to the lowest!

Next

You're probably wondering what the deal with having two content divs is, if we're only going to show one at a time anyway. Fret not, your questions will be answered right after this intermission.

No comments:

Post a Comment