londonfed
londonfed

Reputation: 1230

jQuery carousel with active dots

I am building a simple carousel where the active dots will change active state once the user scrolls horizontally. However, the jQuery left position return value is not changing when I scroll:

li_left = li.position().left; // this is not changing value in console.log()

Any ideas why this is happening? Full code below. If you run you can see that li_left is not changing in console.

var $div = $('.carousel__list');
var divleft = $div.position().left;

$('.carousel').scroll(function() {
  console.log('Scroll started')
  $('.carousel li').each(function() {
    li = $(this);
    li_left = li.position().left;
    console.log('li_left', li_left)
    if (li_left >= divleft && li_left + li.width() <= divleft + $div.width()) {
      $(this).css({
        opacity: '1'
      })
      $(this).siblings('li').css({
        opacity: '0.2'
      });
      return false;
    }
  });
})
.carousel {
  width: 400px;
  overflow-x: auto;
}

.carousel__list,
carousel__dots {
  list-style: none;
  padding: 0;
  margin: 0;
}

.carousel__list {
  width: 3000px;
  position: relative;
}

.carousel li {
  display: inline-block;
  background-color: grey;
  width: 140px;
  height: 140px;
  margin: 20px;
}

.dots {
  margin: 30px auto 50px auto;
  display: flex;
  padding: 0;
  justify-content: center;
}

.dots li {
  background-color: blue;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  list-style: none;
  margin: 0 5px 0 0;
  display: inline-block;
  opacity: 0.2
}

.dots li.active {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="carousel">
  <ul class="carousel__list">
    <li>Slide 1</li>
    <li>Slide 2</li>
    <li>Slide 3</li>
    <li>Slide 4</li>
    <li>Slide 5</li>
  </ul>
</div>

<ol class="dots">
  <li class="active"></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ol>

For reference the following is a jsfiddle link I was trying to adapt into my solution. In this example the position().left is changing:

http://jsfiddle.net/Vy33z/4/

Upvotes: 0

Views: 1325

Answers (3)

londonfed
londonfed

Reputation: 1230

Apologies, I was targeting the wrong selector. I must be tired. Below is the correct solution with the active dots changing:

var $div = $('.carousel__list');
var divleft = $div.position().left;

$('.carousel').scroll(function() {
    console.log('Scroll started')
    $('.carousel__list li').each(function() {
        li = $(this);
        li_left = li.offset().left;
        console.log('li', li)
        console.log('li_left', li_left)
        if (li_left >= divleft && li_left + li.width() <= divleft + $div.width()) {
            var index = $(this).index();
            $(this).css({opacity: '1'});
            $('.dots li:eq('+index+')').css({opacity: '1'});

            $(this).siblings('li').css({opacity: '0.2'});
            $('.dots li:eq('+index+')').siblings('li').css({opacity: '0.2'});

            return false;
        }
    });
})
.carousel {
  width: 400px;
  overflow-x: auto;
}

.carousel__list, carousel__dots {
  list-style: none;
  padding: 0;
  margin: 0;
}

.carousel__list {
  width: 3000px;
  position: relative;
}

.carousel li {
  display: inline-block;
  background-color: grey;
  width: 200px;
  height: 200px;
  margin: 20px;
}

.dots {
  margin: 30px auto 50px auto;
  display: flex;
  padding: 0;
  justify-content: center;
}

.dots li {
  background-color: blue;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  list-style: none;
  margin: 0 5px 0 0;
  display: inline-block;
  opacity: 0.2
}

.dots li.active {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="carousel">
  <ul class="carousel__list">
    <li>Slide 1</li>
    <li>Slide 2</li>
    <li>Slide 3</li>
    <li>Slide 4</li>
    <li>Slide 5</li>
  </ul>
</div>

<ol class="dots">
  <li class="active"></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ol>

Upvotes: 0

kastriotcunaku
kastriotcunaku

Reputation: 1179

I've changed some of your code, take a look:

var moveSpace = $('.carousel__list li').outerWidth();

$('.carousel').scroll(function() {
	var activeDot = Math.round(Math.abs($('.carousel__list').position().left / moveSpace)) + 1;
  $('.dots li.active').removeClass('active');
  $('.dots li:nth-child(' + activeDot + ')').addClass('active');
})

$('.dots li').click(function() {
	var id = $(this).data("id");
  var scrollSpace = id * moveSpace;
	$('.carousel').scrollLeft(scrollSpace);
});
.carousel {
  width: 400px;
  overflow-x: auto;
}

.carousel__list,
carousel__dots {
  list-style: none;
  padding: 0;
  margin: 0;
}

.carousel__list {
  width: 1200px;
  position: relative;
}

.carousel li {
  display: inline-block;
  background-color: grey;
  width: 140px;
  height: 140px;
  margin: 20px;
}

.dots {
  margin: 30px auto 50px auto;
  display: flex;
  padding: 0;
  justify-content: center;
}

.dots li {
  background-color: blue;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  list-style: none;
  margin: 0 5px 0 0;
  display: inline-block;
  opacity: 0.2;
  cursor: pointer;
}

.dots li.active {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="carousel">
  <ul class="carousel__list">
    <li>Slide 1</li>
    <li>Slide 2</li>
    <li>Slide 3</li>
    <li>Slide 4</li>
    <li>Slide 5</li>
  </ul>
</div>

<ol class="dots">
  <li class="active" data-id="0" ></li>
  <li data-id="1" ></li>
  <li data-id="2" ></li>
  <li data-id="3" ></li>
  <li data-id="4" ></li>
</ol>

Also JS Fiddle demo: http://jsfiddle.net/Vy33z/105/

Upvotes: 1

Schnatti
Schnatti

Reputation: 89

use offset instead of position. position.left is not changing, because the li element does not change his position compared to his parent.

off = li.offset();
li_left = off.left;

Upvotes: 0

Related Questions