Creative Div
Creative Div

Reputation: 443

Jquery Slider Loop

Hope you are doing well! I have a jquery card slider that is not working properly. When it goes to the last slide, the blank screen appear. Looks so much buggy. While when i try to go back to previous slider, it doesn't work either.

Is it possible to make a slider go from the last card to 1st card? A loop that transfers it from the last slide to the first slide. If the last card viewed, I don't want it to end, I want to go from the start again.

Any Help will be appreciated.

$num = $('.my-card').length;
$even = $num / 2;
$odd = ($num + 1) / 2;

if ($num % 2 == 0) {
  $('.my-card:nth-child(' + $even + ')').addClass('active');
  $('.my-card:nth-child(' + $even + ')').prev().addClass('prev');
  $('.my-card:nth-child(' + $even + ')').next().addClass('next');
} else {
  $('.my-card:nth-child(' + $odd + ')').addClass('active');
  $('.my-card:nth-child(' + $odd + ')').prev().addClass('prev');
  $('.my-card:nth-child(' + $odd + ')').next().addClass('next');
}

$('.my-card').click(function() {
  $slide = $('.active').width();
  console.log($('.active').position().left);
  
  if ($(this).hasClass('next')) {
    $('.card-carousel').stop(false, true).animate({left: '-=' + $slide});
  } else if ($(this).hasClass('prev')) {
    $('.card-carousel').stop(false, true).animate({left: '+=' + $slide});
  }
  
  $(this).removeClass('prev next');
  $(this).siblings().removeClass('prev active next');
  
  $(this).addClass('active');
  $(this).prev().addClass('prev');
  $(this).next().addClass('next');
});


// Keyboard nav
$('html body').keydown(function(e) {
  if (e.keyCode == 37) { // left
    $('.active').prev().trigger('click');
  }
  else if (e.keyCode == 39) { // right
    $('.active').next().trigger('click');
  }
});



  

$('a.slide-control').on('click', function(e){
  e.preventDefault();
  var slides = $('.my-card');
  var nextSlide;
  $slide = $('.active').width();

  if($(this).attr('id') === "prev-slide"){
    nextSlide = $('.active').prev();
      $('.card-carousel').stop(false, true).animate({left: '+=' + $slide});
  } else {
    nextSlide = $('.active').next();
      $('.card-carousel').stop(false, true).animate({left: '-=' + $slide});
  }
  
  
  $(slides).each(function(){
      $(this).removeClass('prev active next');
  })
  
  $(nextSlide).addClass('active');
  $(nextSlide).prev().addClass('prev');
  $(nextSlide).next().addClass('next');
})
html body {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  overflow-x: hidden;
}

.card-carousel {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.card-carousel .my-card {
  height: 400px;
  width: 500px;
  position: relative;
  z-index: 1;
  -webkit-transform: scale(0.6) translateY(-2rem);
  transform: scale(0.6) translateY(-2rem);
  opacity: 0;
  cursor: pointer;
  pointer-events: none;
  background: #2e5266;
  background: linear-gradient(to top, #2e5266, #6e8898);
  transition: 1s;
}

.card-carousel .my-card.active {
  z-index: 3;
  -webkit-transform: scale(1) translateY(0) translateX(0);
  transform: scale(1) translateY(0) translateX(0);
  opacity: 1;
  pointer-events: auto;
  transition: 1s;
}

.card-carousel .my-card.prev, .card-carousel .my-card.next {
  z-index: 2;
  -webkit-transform: scale(0.8) translateY(-1rem) translateX(0);
  transform: scale(0.8) translateY(-1rem) translateX(0);
  opacity: 0.6;
  pointer-events: auto;
  transition: 1s;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<body>
<div class="heading">
</div>
<div class="card-carousel">
  <div class="my-card"></div>
  <div class="my-card"></div>
  <div class="my-card"></div>
  <div class="my-card"></div>
  <div class="my-card"></div>
  <div class="my-card"></div>
  <div class="my-card"></div>
  <div class="my-card"></div>
  <div class="my-card"></div>
</div>

  <div style="font-size:70px">
    <a class="slide-control" id="prev-slide" href=""><i class="fas fa-chevron-circle-left"></i></a>
    <a class="slide-control"  id="next-slide" href=""><i class="fas fa-chevron-circle-right"></i></a>
  </div>
</body>
</html>

Upvotes: 1

Views: 1141

Answers (1)

Roko C. Buljan
Roko C. Buljan

Reputation: 205987

  • Welcome to responsive design (it's 2018 after all). Use responsive units like %.
    If you need a fixed width, than simply create a neutral wrapper that will encapsulate your reusable flexible carousel!
  • Be consistent in naming classes. Use a CSS naming convention like i.e: SUIT.
  • Don't use IDs, or you might find yourself copy-pasteing JS code all over the place in case of multiple galleries.
  • Don't style unnecessarily html, body. Wrap your elements into a .Carousel wrapper component.
  • If you don't use actual links, use <button> element (and style it accordingly).
  • Use CSS transform instead of jQuery's .animate() whenever possible.
  • A jQuery variable naming convention says to prefix with $ only Elements collections references. Do so.
  • If you have multiple animation triggers, don't make animations all over your code, instead create a reusable anim() function that does this. The triggers should only increment or decrement a currently active index counter i.
  • Get to know JS basics, the Ternary Operator ?:
  • Use Math.floor when trying to get a middle index
  • Use Module operator % to reset index to 0 when it exceeds tot (number of cards)
  • The resulting code should look pretty and easily readable/debuggable:

$(".Carousel").each(function() {

  var $this = $(this),
      $btns = $this.find(".Carousel-prev, .Carousel-next"),
      $slider = $this.find(".Carousel-slider"),
      $cards = $slider.find(">*"),
      tot = $cards.length,
      i = Math.floor(tot / 2); // Somewhere in the middle

  function anim() {
    i = i < 0 ? tot - 1 : i % tot; // Fix index
    var $active = $cards.eq(i);
    $cards.removeClass('active prev next');
    $active.addClass('active');
    $active.prev().addClass('prev');
    $active.next().addClass('next');
    $slider.css({transform: `translateX(-${100*i}%)`}); // CSS! yey
  }

  $cards.on("click", function() {
    i = $cards.index(this);
    anim();
  });

  $btns.on("click", function() {
    i = $(this).is(".Carousel-next") ? ++i : --i;
    anim();
  });

  anim();

  // Keyboard nav
  $(document).on("keydown", function(e) {
    var k = e.which;
    if (k === 37 || k === 39) {
      i = k === 39 ? ++i : --i;
      anim();
    }
  });

});
/*QuickReset*/*{margin:0;box-sizing: border-box;}html,body{height:100%;font:14px/1.4 sans-serif;}

/* Carousel component */

.Carousel {
  position: relative;
  overflow: hidden;
  width: 100%;
}

.Carousel-slider {
  display: flex;
  height: 150px; /* for demo */
  transition: 1s;
  -webkit-backface-visibility: hidden;
}

.Carousel-slider>* {
  /* CARDS */
  position: relative;
  flex: 0 0 90%; /* 90 flex-basis */
  margin: 0 5%; /* 90 + 5 + 5 = 100 */
  height: 100%;
  cursor: pointer;
  pointer-events: none;
  background: #6e8898;
  object-fit: cover; /*In case the card is an <img>!*/
  transform: scale(0.8);
  transition: 1s;
  -webkit-backface-visibility: hidden;
}

.Carousel-slider>.active {
  opacity: 1;
  cursor: auto;
  flex: 0 0 80%;
  margin: 0 10%;
  transform: scale(1);
  pointer-events: auto;
}

.Carousel-slider>.prev {
  transform: translateX(24%) scale(0.8);
}

.Carousel-slider>.next {
  transform: translateX(-24%) scale(0.8);
}

.Carousel-slider>.prev,
.Carousel-slider>.next {
  opacity: 0.5;
  pointer-events: auto;
}

.Carousel-controls {
  text-align: center;
}

.Carousel-prev,
.Carousel-next {
  border: 0;
  height: 3rem;
  font-size: 2em;
  line-height: 1em;
  background: #000;
  border-radius: 50%;
  color: #fff;
  cursor: pointer;
}
<div class="Carousel">
  <div class="Carousel-slider">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <img src="//placehold.it/800x400/0bf/fff?text=IMAGINE!" alt="Carousel image!">
    <div>6</div>
    <img src="//placehold.it/800x400/f0b/fff?text=No+limits" alt="Carousel image!">
    <div>8</div>
    <div>9</div>
  </div>
  <div class="Carousel-controls">
    <button type="button" class="Carousel-prev">&#x23f4;</button>
    <button type="button" class="Carousel-next">&#x23f5;</button>
  </div>
</div>

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

See above how the anim() function is reused, after manipulating the Current index i variable.

Upvotes: 1

Related Questions