Calculate the Slider Position

Calculate the Slider Position

Link to the project: click here

Fiddle link: click here

I have this slider that my client wanted to work, without any plugin.

The html involved is as follows:

The js/jQuery involved is as follows:

Following is the main part of js involved:

var newSliderWidth = $('#oCarol').width(); // container width is recalculated and updated 

     liW = newSliderWidth; // new li width
     liFW = (liW * $slider.find('li').length); // new width is calculated for the container

     $('.panel-inner li').css('width', liW); // new width is assigned to the li(s)

     $slider.width(liFW); // new width is assigned to the container

     $('.button a').on('click', function (e) { // this determines the left and right buttons' functionality

         e.preventDefault(); // prevent the default 

         if (!animating) {

             var left = Math.abs(parseInt($slider.css('left'))); // find the current slider position
             // 'side' is the amount of distance in pixels that the slider needs to move whenever a left or right arrow is pressed, respectively 
             var side = ($(this).data('direction') == 'right') ? (((left + (liW * iXS)) >= liFW) ? 0 : -(left + liW)) : ((left > 0) ? -(left - liW) : -(liFW - (liW * iXS)));
             rotate(side);

             console.log('Current position is: '+side);



         }

     });

     // whenever a screen resize happens, the slider moves to the first slide

      $('.panel-inner').animate({
          left: 0
      });

At the moment, whenever the screen resize happens, I have to reset the slider to first slide or else the current slide position gets messed up and half of it is shown and half from the next slide gets displayed as well, at the same time.

What I need, is, to somehow display the current slide correctly so that I don't have to reset the slider position to "left: 0px"

Here is an example, this happens when I comment the code where I reset '.panel-inner' to 'left: 0':

3

2 Answers

First, you should move the code that binds the click-handlers for the buttons so it is outside of the window resize-handler. You are rebinding those click-handlers over and over as the windows gets resized.

Second, I think your code is unnecessarily complicated. I think it is easier to keep track of the index of the currently displayed panel and have a function that slides to a panel by its index.

Note that I am using the "margin-left" css property to do the sliding, rather than "left". That's the way I've seen sliding like this implemented before, but I'm not saying one way is better than the other.

Here is what it could look like:

$(function() {
    var animating = false,
        $container = $('.panel'),
        $slider = $('.panel-inner'),
        $panels = $slider.children(),
        currentPanelIndex = 0,
        panelWidth,
        resizeTimerId = null;

    function slideTo(panelIndex) {
        animating = true;
        $slider.stop(true, true).animate({
            "margin-left": -(panelIndex * panelWidth)
        }, 1000, function () {
            animating = false;
            currentPanelIndex = panelIndex;
        });
    }

    function resizeSlider() {
        panelWidth = $container.width();
        $panels.css('width', panelWidth);
        $slider.width(panelWidth * $panels.length);
        $slider.css({ "margin-left": -(currentPanelIndex * panelWidth) });
    }

    $(window).on('resize', function() {
        clearTimeout(resizeTimerId);
        resizeTimerId = setTimeout(function () {
            resizeSlider();
        }, 100);
    });

    $('.button a').on('click', function(e) { 
        e.preventDefault();
        if (!animating) {
            var direction = $(this).data('direction');
            var panelIndex = currentPanelIndex + ((direction == 'right') ? 1 : -1);
            if (panelIndex < 0) {
                panelIndex = $panels.length - 1;
            } else if (panelIndex > ($panels.length - 1)) {
                panelIndex = 0;
            }
            slideTo(panelIndex);
        }
    });

    resizeSlider();
});

Note: It could call slideTo(currentPanelIndex) when the window is resized to make the adjustment, but then it would be animated and if the user keeps resizing, the animations will queue up.

jsfiddle

2

Looks like this will get the expected result :

$(function () {

var conH = $('#knowledge .container').width();

$('.panel-inner li').css({width: conH});

var animating = false,
iXS = 1,
$slider = $('.panel-inner'),
liW = $slider.find('li:first').width(),
liFW = (liW*$slider.find('li').length),
first = true,
index;

$slider.width(liFW);

$(window).on('resize', function () {

    clearTimeout(timeout);

    if (first) {
        first = false;
        var positioned = parseInt($slider.css('left'));
        index = Math.round(positioned/liW);
    }

    var timeout = setTimeout(function () {

        first = true;
        var newSliderWidth = $('#oCarol').width();
        liW = newSliderWidth;
        liFW = (liW * $slider.find('li').length);

        $('.panel-inner li').css('width', liW);
        $slider.width(liFW);

        $('.button a').off('click').on('click', function(e) {

            e.preventDefault();

            if (!animating) {
                var left = Math.abs(parseInt($slider.css('left')));
                var side = ($(this).data('direction') == 'right') ? (((left + (liW * iXS)) >= liFW) ? 0 : -(left + liW)) : ((left > 0) ? -(left - liW) : -(liFW - (liW * iXS)));
                rotate(side);
            }
        });

        $('.panel-inner').css({left: index*liW});

    }, 200);
});

$(window).trigger('resize');

    var rotate = function(leftY) {
        if (!animating) {
            animating = true;
            $slider.stop(true, true).animate({left: leftY}, 1000, function () {
                animating = false;
            });
        }
    }
});

I've added a check on the first resize and then keep clearing the timeout until the user has stopped resizing. Then 200ms after that, it recalculates and repositions.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Elena Rostova
Author

Elena Rostova

Elena Rostova holds a Master's degree in Public Health Journalism. She covers groundbreaking medical research, holistic wellness trends, mental health awareness, and nutritional science.