Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Carousel slides incorrectly when swiping or when clicking the slider controls (next/prev)

I've just finished building a carousel I've been working on that uses swipe/touch and also uses controls such as prev/next to control the carousel. Right now I'm having an issue regarding about the carousel behavior. Basically I'm trying to make it slide one by one. Here is a sample of the code I've been working on. Right now it seems to be sliding by 2 or 3 depending on how many carousel I've placed.

I'm also having an issue with regards to making it responsive also

function fCarousel() {
  // var activeSlide = 0;
  // $('.faculty-carousel').attr('data-slide', '0');

  var viewPortSize        = $(window).width(),
      facultyPanel = $('.faculty-carousel .faculty-items li'),
      profileCount = facultyPanel.length,
      activeSlide         = 0,
      carousel            = $('.faculty-carousel .faculty-items');

  $('.faculty-carousel').attr('data-slide', '0');

  //Set Panel Size based on viewport

  if (viewPortSize <= 1920 ) {
      var profilePanelSize = viewPortSize / 5
  }

  if (viewPortSize < 1024 ) {
      var profilePanelSize = viewPortSize / 4
  }

  if (viewPortSize < 768 ) {
      var profilePanelSize = viewPortSize / 3
  } 

  if (viewPortSize < 480 ) {
      var profilePanelSize = viewPortSize
  }

  carousel.outerWidth( profilePanelSize * profileCount );
  facultyPanel.outerWidth(profilePanelSize);
  carousel.css('transform', 'translateX(' + 0 + '% )');

  $('.prev').on('click', function(e) {
      event.stopPropagation();

    var carouselWrapper     = $(this).closest('.faculty-carousel'),
        facultyProfilePanel = carouselWrapper.find('.faculty-items li'),
        facultyProfileCount = facultyProfilePanel.length,
        viewPortSize        = $(window).width(),
        carousel = carouselWrapper.find('.faculty-items'),
        position            = 0,
        currentSlide        = parseInt(carouselWrapper.attr('data-slide'));

      // Check if data-slide attribute is greater than 0
      if (currentSlide > 0) {
          // Decremement current slide
          currentSlide--;
          // Assign CSS position to clicked slider
          var transformPercentage = -1 * currentSlide / facultyProfileCount * 100;
          carousel.css('transform', 'translateX(' + transformPercentage + '% )');
          // Update data-slide attribute
          carouselWrapper.attr('data-slide', currentSlide);
          activeSlide = currentSlide;
      }
  });

  $('.next').on('click', function(e) {
      event.stopPropagation();
      // store variable relevent to clicked slider

    var carouselWrapper     = $(this).closest('.faculty-carousel'),
        facultyProfilePanel = carouselWrapper.find('.faculty-items li'),
        facultyProfileCount = facultyProfilePanel.length,
        viewPortSize   = $(window).width(),
        carousel = carouselWrapper.find('.faculty-items'),
        position = 0,
        currentSlide = parseInt(carouselWrapper.attr('data-slide'));

      // Check if dataslide is less than the total slides
      if (currentSlide < facultyProfileCount - 1) {
          // Increment current slide
          currentSlide++;
          // Assign CSS position to clicked slider
          var transformPercentage = -1 * currentSlide / facultyProfileCount * 100;
          carousel.css('transform', 'translateX(' + transformPercentage + '% )');
          // Update data-slide attribute
          carouselWrapper.attr('data-slide', currentSlide);
          activeSlide = currentSlide;
      }
  })

    $('.faculty-carousel .faculty-items').each(function() {

        // create a simple instance
        // by default, it only adds horizontal recognizers

        var direction;
        var touchSlider = this;
        var mc = new Hammer.Manager(this),
            itemLength = $(this).find('li').length,
            count = 0,
            slide = $(this),
            timer;

        var sliderWrapper = slide,
            slideItems = sliderWrapper.find('li'),
            //slider = sliderWrapper.find('li'),
            totalPanels = slideItems.length,
            currentSlide = parseInt(sliderWrapper.attr('data-slide'));

        // mc.on("panleft panright", function(ev) {
        //   direction = ev.type;
        // });

        mc.add(new Hammer.Pan({
            threshold: 0,
            pointers: 0
        }))
        mc.on('pan', function(e) {
            var percentage = 100 / totalPanels * e.deltaX / window.innerWidth;
            var transformPercentage = percentage - 100 / totalPanels * activeSlide;
            touchSlider.style.transform = 'translateX( ' + transformPercentage + '% )';
            var sliderWrapper = $(e.target).closest('.faculty-carousel')


            if (e.isFinal) { // NEW: this only runs on event end

                var newSlide = activeSlide;
                if (percentage < 0)
                    newSlide = activeSlide + 1;
                else if (percentage > 0)
                    newSlide = activeSlide - 1;
                goToSlide(newSlide, sliderWrapper);
            }
        });


        var goToSlide = function(number, sliderWrapper) {
            if (number < 0)
                activeSlide = 0;
            else if (number > totalPanels - 1)
                activeSlide = totalPanels - 1
            else
                activeSlide = number;

            sliderWrapper.attr('data-slide', activeSlide);

            touchSlider.classList.add('slide-animation');
            var percentage = -(100 / totalPanels) * activeSlide;
            touchSlider.style.transform = 'translateX( ' + percentage + '% )';
            timer = setTimeout(function() {
                touchSlider.classList.remove('slide-animation');
            }, 400);

        };
    });

}

$(document).ready(function() {
  fCarousel();
})

$(window).on('resize', function(){
  fCarousel();
})
/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
  display: block;
}
body {
  line-height: 1;
}
ol, ul {
  list-style: none;
}
blockquote, q {
  quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}
.faculty-items li {
    height : 100px;
}
.faculty-items li:nth-child(odd) {
    background-color : grey;
}
.faculty-items li:nth-child(even) {
    background-color : aqua
}
.faculty-items {
    overflow   : hidden;
    position   : relative;
    right      : 0;
    display : flex;
    -webkit-transition: transform 0.3s linear;
}
.faculty-carousel .controls {
    display : block;
}
<!doctype html>
<html>
<head>
<title>Carousel</title>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
</head>
<body>
  <div class="faculty-carousel">
    <ul class="faculty-items">
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
        <li>Item 4</li>
        <li>Item 5</li>
        <li>Item 6</li>
    </ul>

    <div class="controls">
      <div class="prev">
        prev
      </div>

      <div class="next">
        next
      </div>
    </div>
  </div>


  <div class="faculty-carousel">
    <ul class="faculty-items">
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
        <li>Item 4</li>
        <li>Item 5</li>
        <li>Item 6</li>
    </ul>

    <div class="controls">
      <div class="prev">
        prev
      </div>

      <div class="next">
        next
      </div>
    </div>
  </div>

  <div class="faculty-carousel">
    <ul class="faculty-items">
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
        <li>Item 4</li>
        <li>Item 5</li>
        <li>Item 6</li>
    </ul>

    <div class="controls">
      <div class="prev">
        prev
      </div>

      <div class="next">
        next
      </div>
    </div>
  </div>
</body>
</html>
like image 764
clestcruz Avatar asked Aug 31 '17 13:08

clestcruz


People also ask

Why is my carousel not sliding?

In browsers where the Page Visibility API is supported, the carousel will avoid sliding when the webpage is not visible to the user (such as when the browser tab is inactive, the browser window is minimized, etc.).

How do I stop carousel from moving automatically?

To turn off the autoplay set data-interval="false" to the carousel element.

How do I get my carousel slider to stop clicking?

click(function(){ alert("Clicked."); $('#myCarousel'). carousel({ pause: true, interval: false }); });

What is slider carousel?

A carousel slider is a slideshow of photos in WordPress. Adding visuals such as photos and videos to a website gets visitors' attention. It also enhances the user experience. For a design or photographer website, placing images in sliders or photo carousels makes them more interactive.


1 Answers

Okay, my first answer here was done in a hurry but I believe I have a clear JavaScript representation of what most modern Carousels would function like, although the rest is up to you if you choose to use it.

Here is the JavaScript side of things well explained

// Index all Carousel
for (var i = 0; i < document.getElementsByClassName("carousel").length; i++) {
    // Create a container for all the slides
    document.getElementsByClassName("carousel")[i].innerHTML = (
        '<div class="slides-container">' +
            document.getElementsByClassName("carousel")[i].innerHTML +
        '</div>'
    );

    // If the Carousel is automated
    if (document.getElementsByClassName("carousel")[i].getAttribute("data-auto")) {
        // Remove all white-space in the Carousel's "data-auto" attribute.
        document.getElementsByClassName("carousel")[i].setAttribute("data-auto", document.getElementsByClassName("carousel")[i].getAttribute("data-auto").replace(/ /g, ""));

        // Set the Carousel direction
        document.getElementsByClassName("carousel")[i]._direction = String(document.getElementsByClassName("carousel")[i].getAttribute("data-auto").slice(0, document.getElementsByClassName("carousel")[i].getAttribute("data-auto").indexOf("_")));

        // Set the Carousel interval
        document.getElementsByClassName("carousel")[i]._interval = (parseFloat(document.getElementsByClassName("carousel")[i].getAttribute("data-auto").slice(document.getElementsByClassName("carousel")[i].getAttribute("data-auto").indexOf("_")).replace("_", "")) * 1000)
    };

    // Index all Carousel slides
    for (var j = 0; j < document.getElementsByClassName("carousel")[i].querySelector(".slides-container").children.length; j++)
        // Hide them
        document.getElementsByClassName("carousel")[i].querySelector(".slides-container").children[j].hidden = true;

        // Show the first one or the specified slide
        document.getElementsByClassName("carousel")[i].querySelector(".slides-container").children[(parseInt(document.getElementsByClassName("carousel")[i].getAttribute("data-active")) || 0)].hidden = false;

    // Carousel Next
    document.getElementsByClassName("carousel")[i]._next = function() {
        // Index all Carousel Slides
        for (var j = 0; j < this.querySelector(".slides-container").children.length; j++)
            // Show the next slide in the set
            if (this.querySelector(".slides-container").children[j].hidden == false) {
                this.querySelector(".slides-container").children[j].hidden = true;
                (this.querySelector(".slides-container").children[j].nextElementSibling || this.querySelector(".slides-container").children[0]).hidden = false;

                break
            }
    };

    // Carousel Previous
    document.getElementsByClassName("carousel")[i]._prev = function() {
        // Index all Carousel Slides
        for (var j = 0; j < this.querySelector(".slides-container").children.length; j++)
            // Show the previous slide in the set
            if (this.querySelector(".slides-container").children[j].hidden == false) {
                this.querySelector(".slides-container").children[j].hidden = true;
                (this.querySelector(".slides-container").children[j].previousElementSibling || this.querySelector(".slides-container").children[this.querySelector(".slides-container").children.length - 1]).hidden = false;

                break
            }
    };

    // Carousel Toggle
    document.getElementsByClassName("carousel")[i]._toggle = function(slideIndex) {
        // Index all Carousel Slides
        for (var j = 0; j < this.querySelector(".slides-container").children.length; j++)
            // Hide them
            this.querySelector(".slides-container").children[j].hidden = true;

        // Show the specified slide
        (this.querySelector(".slides-container").children[slideIndex] || document.createElement("div")).hidden = false
    };

    // If the Carousel Interval is a Number
    if (typeof document.getElementsByClassName("carousel")[i]._interval == "number") {
        // Index
        var index = i;

        // Set an interval to automate the Carousel
        setInterval(function() {
            // If the Carousel direction is right
            if (document.getElementsByClassName("carousel")[index]._direction == "right")
                document.getElementsByClassName("carousel")[index]._next();

            // If the Carousel direction is left
            else if (document.getElementsByClassName("carousel")[index]._direction == "left")
                document.getElementsByClassName("carousel")[index]._prev()
        }, document.getElementsByClassName("carousel")[i]._interval)
    }

    // If the Carousel has buttons
    if (document.getElementsByClassName("carousel")[i].hasAttribute("data-buttons"))
        // Make the Buttons Container
        document.getElementsByClassName("carousel")[i].innerHTML += (
            '<div class="buttons-container">' +
                '<button onclick="this.parentNode.parentNode._prev()"> Previous </button>' +
                '<button onclick="this.parentNode.parentNode._next()"> Next </button>' +
            '</div>'
        )

    // If the Carousel has indicators
    if (document.getElementsByClassName("carousel")[i].hasAttribute("data-indicators"))
        // Make the Indicators Container
        document.getElementsByClassName("carousel")[i].innerHTML += (
            '<div class="indicators-container">' +
                // Place as many checkboxes for as many slides there are
                (function() {
                    var indicators = "";

                    for (var k = 0; k < document.getElementsByClassName("carousel")[i].querySelector(".slides-container").children.length; k++)
                        indicators += (
                            '<input class="indicator-' + k + '" onclick="this.parentNode.parentNode._toggle(this.getAttribute(\'class\')[this.getAttribute(\'class\').length - 1])" type="checkbox">'
                        );

                    return indicators
                })() +
            '</div>'
        );

    // Add a click event to the Carousel
    document.getElementsByClassName("carousel")[i].addEventListener("click", function() {
        // Index all Carousel
        for (var j = 0; j < document.getElementsByClassName("carousel").length; j++)
            // If the Carousel indexed is not the target Carousel
            if (document.getElementsByClassName("carousel")[j] != this)
                // Blur it
                document.getElementsByClassName("carousel")[j].removeAttribute("data-focus");

            else
                // 'Focus' it
                document.getElementsByClassName("carousel")[j].setAttribute("data-focus", "")

        // If the mouse click is to the left of the carousel
        if (event.clientX < (this.getBoundingClientRect().left + (this.getBoundingClientRect().width / 2)))
            this._prev();

        // If the mouse click is to the right of the carousel
        else if ((event.clientX > (this.getBoundingClientRect().left + (this.getBoundingClientRect().width / 2))))
            this._next()
    })
};

// Attach an event to the <body>.
document.body.addEventListener("keydown", function() {
    switch (event.code) {
        // If the left arrow key is pressed
        case "ArrowLeft":
            document.querySelector(".carousel[data-focus")._prev();
            break;

        // If the right arrow key is pressed
        case "ArrowRight":
            document.querySelector(".carousel[data-focus")._next();
            break;
    }
})

in this section of the code for the Carousel, the .hidden property can be replaced with anything else but it gives a basic idea of how the slides pass on through the active and inactive states. as for the HTML part

<html>
    <body>
        <div class="carousel" data-active="1" data-auto="right_1" data-buttons data-indicators style="height: 300px">
            <div style="background: #F00; color: #FFF; font-size: 50px; height: 100%; line-height: 300px; text-align: center"> R </div>
            <div style="background: #0F0; color: #FFF; font-size: 50px; height: 100%; line-height: 300px; text-align: center"> G </div>
            <div style="background: #00F; color: #FFF; font-size: 50px; height: 100%; line-height: 300px; text-align: center"> B </div>
        </div>

        <!-- The JS script for the Carousel -->
        <script src="carousel.js"> </script>
    </body>
</html>

Everything has been simplified: the class of carousel to make a new Carousel, data-active attribute to state which slide is active (starts from 0), the data-auto attribute which specifies if the Carousel is automated or not (the right_ stands for the direction the automation and the _1 for how long the interval is), the data-buttons attribute if buttons are required, data-indicators if Carousel indicators are required and the slides as the children of the Carousel.

So yes, this is pretty much the HTML/JS code required for building a simple Carousel.

In case you're looking for anything exciting going on in the world of JavaScript, there is a library I'm working on that I think you might be interested in: https://github.com/LapysDev/LapysJS.

like image 50
Lapys Avatar answered Nov 11 '22 07:11

Lapys