OneMoreQuestion OneMoreQuestion - 3 months ago 14
Javascript Question

How to make JQuery slider load sets of elements at a time

I am experimenting with making an infinite horizontal tab slider using JQuery.

My goal is have the slider load only the first 10 slides on page load, when the next page button is clicked, it then loads the next 10 slides, and so on. It should not load all slides in the beginning to save loading time, and only load the next 10 when right arrow is clicked.

Currently (please see fiddle), the slider loads one more slide at a time and depending on the size of the browser it will also cut off parts of each slide. How do I fix this? Thanks.

Here is the Javascript code I currently have

var element = $('.tab-container li');
var slider = $('.tab-container');
var sliderWrapper = $('.wrapper');
var totalWidth = sliderWrapper.innerWidth();
var elementWidth = element.outerWidth();
var sliderWidth = 0;
var positionSlideX = slider.position().left;
var newPositionSlideX = 0;

sliderWrapper.append('<span class="prev-slide"><</span><span class="next-slide">></span>');

element.each(function() {
sliderWidth = sliderWidth + $(this).outerWidth() + 1;
});

slider.css({
'width': sliderWidth
});

$('.next-slide').click(function() {
if (newPositionSlideX > (totalWidth - sliderWidth)) {
newPositionSlideX = newPositionSlideX - elementWidth;
slider.css({
'left': newPositionSlideX
}, check());
};
});

$('.prev-slide').click(function() {
if (newPositionSlideX >= -sliderWidth) {
newPositionSlideX = newPositionSlideX + elementWidth;
slider.css({
'left': newPositionSlideX
}, check());
};
});

function check() {
if (sliderWidth >= totalWidth && newPositionSlideX > (totalWidth - sliderWidth)) {
$('.next-slide').css({
'right': 0
});
} else {
$('.next-slide').css({
'right': -$(this).width()
});
};

if (newPositionSlideX < 0) {
$('.prev-slide').css({
'left': 0
});
} else {
$('.prev-slide').css({
'left': -$(this).width()
});
};
};

$(window).resize(function() {
totalWidth = sliderWrapper.innerWidth();
check();
});
check();

Answer

You can simplify this a lot by tracking the index of the left-most slide that's visible. It's a more common practice.

var element = $('.tab-container li');
var slider = $('.tab-container');
var sliderWrapper = $('.wrapper');
var firstVisibleSlide = 0;
var nextButton;

sliderWrapper.prepend('<span class="prev-slide"><</span>').append('<span class="next-slide">></span>');

nextButton = $(".next-slide");

$('.next-slide').click(function() {
  if (slider.prop("offsetLeft") + slider.width() > nextButton.prop("offsetLeft")) {
        move(1);
  }
});

$('.prev-slide').click(function() {
  if (firstVisibleSlide > 0) {
    move(-1);
  };
});

function move(dif){ 
  var left;

  firstVisibleSlide += dif; 
  left = -1 * element.eq(firstVisibleSlide).prop("offsetLeft");
  slider.css({
      'left': left + "px"
  });
}

If you are going to load images, and you want them to lazy load for performance, you can set them as background properties as they show. It's pretty easy to track the last visible slide just as you are tracking the first visible slide above, and you can load as few or as many in advance of showing as you wish.

Updated fiddle here.

Comments