kenwheeler / slick

the last carousel you'll ever need
kenwheeler.github.io/slick
MIT License
28.48k stars 5.89k forks source link

"Auto" setting for "slidesToShow" #1071

Closed pavsid closed 9 years ago

pavsid commented 9 years ago

Sometimes the number of slides to show can't be explicitly set - for example when showing a number of logos and you want the slide to fill up the width of the screen, whatever that might be.

I tried enabling variableWidth, but that too seems to depend on slidesToShow when infinite is enabled as sometimes there is a blank space before the next X number of slides are displayed. I also have autoplay enabled if that makes any difference.

Basically, if there was a setting auto for slidesToShow, then the slides should fill the width of the container and if infinite is enabled then they should repeat seamlessly.

simeydotme commented 9 years ago

Hey @pavsid ... sorry but this makes no sense;

If you don't have enough slides to fill a carousel; then do your users a favour and don't load the carousel from the server.... waste of bandwidth and time... the point of a carousel is to display TOO many of something...

or you can and just duplicate your slides and piss people off even more?

pavsid commented 9 years ago

@simeydotme, who said there wasn't enough slides to fill the carousel? Let's say I have a carousel of 20 logos. On a screen 1600px wide it looks fine if I set slidesToShow to 10, but on a screen 1200 px wide 10 is too many.

My point is that there should be a setting to best fit the slides in the carousel based on screen width, and not have to explicitly set the number of slides, or breakpoints all the time.

simeydotme commented 9 years ago

Ah, I misunderstood it sounded like you have too few slides and you want to fill in the gap.... why don't you do the calculation yourself? -- only your own script knows your own dimensions and scenario.

pavsid commented 9 years ago

@simeydotme A calculation for what?? The number of slides to show at a width of 1600, 1200, 1024, 768, 480px, etc?

I presume this "auto" setting would require that the slides have been set a width themselves so the logic knows how many can be shown in the current viewport.

I'm surprised this hasn't been asked before actually, and I thought that maybe there was already a way to do it.

simeydotme commented 9 years ago

Calculate how many slides you can show in the container based on the container's width divided by the slide's width ....

I kind of see what you're getting at now... but its very easy for you to do yourself before the carousel loads :) - you must consider that if @kenwheeler includes every possible functionality, even ones that you can do yourself with ease, then your users will be downloading so much code bloat. :)

Simon

On Wed, Feb 25, 2015 at 3:57 PM, pavsid notifications@github.com wrote:

@simeydotme https://github.com/simeydotme A calculation for what?? The number of slides to show at a width of 1600, 1200, 1024, 768, 480px, etc?

I presume this "auto" setting would require that the slides have been set a width themselves so the logic knows how many can be shown in the current viewport.

I'm surprised this hasn't been asked before actually, and I thought that maybe there was already a way to do it.

— Reply to this email directly or view it on GitHub https://github.com/kenwheeler/slick/issues/1071#issuecomment-75919728.

pavsid commented 9 years ago

@simeydotme Yeah I guess that's a solution, but it would have to recalculate again on window resize, which again is easy enough.

I just thought this might be a feature required by others too, or already possible.

Thanks for your help :-)

simeydotme commented 9 years ago

It's OK, sorry for the confusion!! :smile: I agree it would be nice to calculate based on container, but depending on CSS, and project settings it can be very troublesome to do it in a universal way. I would suggest you don't look at the viewport width for this ... just the carousel container :)

You can leave the issue open and the repo owner can consider the feature still, I was just trying to help with a short-term solution.

Best, Simon

On Wed, Feb 25, 2015 at 4:28 PM, pavsid notifications@github.com wrote:

@simeydotme https://github.com/simeydotme Yeah I guess that's a solution, but it would have to recalculate again on window resize, which again is easy enough.

I just thought this might be a feature required by others too, or already possible.

Thanks for your help :-)

— Reply to this email directly or view it on GitHub https://github.com/kenwheeler/slick/issues/1071#issuecomment-75922855.

hackel commented 7 years ago

Was this closed because this feature request was implemented? Otherwise it should be re-opened.

This would be a very useful feature. Honestly, I couldn't care less how many slides appear at once. I simply want the carousel to operate as a content "overflow." It makes no sense to constantly watch for container size changes and recreating the carousel over and over again. Also, what if the slides are variable-width? It should just resize smoothly as the container size changes, and let the container be responsible for the responsive breakpoints.

warudin commented 6 years ago

I think this issue should be reopened. Instead of needing to definee the 'slidesToShow' per breakpoint it'd be great if this value would be calculated based on the width of the slides, wouldn't it?

neoshamangames commented 6 years ago

I agree. I am looking for this feature.

eliagoris commented 6 years ago

well thats exactly what I need

ramirezcgn commented 6 years ago

I've made a hack to get this work in 1.8 vr., maybe can be useful for someone else:

(function($) {
  'use strict';

  //create temporal object to get slick object
  var getSlick = function() {
    var $tmp = $('<div>').slick();
    var slick = $tmp[0].slick.constructor;
    $tmp.slick('unslick');
    return slick;
  };

  if ($.fn.slick) {
    var Slick = getSlick();
    if (Slick) {
      //hook checkResponsive method
      var checkResponsiveOrig = Slick.prototype.checkResponsive;
      Slick.prototype.checkResponsive = function(initial, forceUpdate) {
        var _ = this;
        if (_.options.autoSlidesToShow && !_.options.infinite && _.options.variableWidth) {
          var sliderWidth = _.$slider.width();
          var width = 0, length = _.$slides.length;
          for (var i = 0; i < length; i++) {
            width += $(_.$slides[i]).outerWidth();
          }
          _.averageSlidesWidth = width / length;
          _.options.slidesToShow = Math.floor(sliderWidth / _.averageSlidesWidth) || 1;
          //force update arrows
          if (_.lastSlidesToShow !== _.options.slidesToShow) {
            _.lastSlidesToShow = _.options.slidesToShow;
            if (initial === true) {
              _.currentSlide = _.options.initialSlide;
            }
            _.refresh(initial);
          }
        }
        return checkResponsiveOrig.apply(this, arguments);
      };
      //hook getLeft method
      var getLeftOrig = Slick.prototype.getLeft;
      Slick.prototype.getLeft = function(slideIndex) {
        var _ = this;
        if (_.options.autoSlidesToShow && !_.options.infinite && _.options.variableWidth) {
          var targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
          if (targetSlide[0]) {
            var diff = 0;
            if (slideIndex) {
              var sliderWidth = _.$slider.width();
              var otherSlidesWidth = (_.slideCount - slideIndex) * _.averageSlidesWidth;
              if (otherSlidesWidth < sliderWidth) {
                diff = sliderWidth - otherSlidesWidth;
              }
            }
            return (targetSlide[0].offsetLeft - diff) * -1;
          }
          return  0;
        }
        return getLeftOrig.apply(this, arguments);
      };
    }
  }
})(jQuery);

if someone wants to add this code to the repo will be great, I don't have enough knowledgement about all the code...

andrewg211 commented 6 years ago

Thanks @ramirezcgn saved me many hours having to figure this out, hopefully your code will be committed soon.

chancer4 commented 6 years ago

Can someone help me with where @ramirezcgn's code should go? I would love to have this feature but its a little over my js skill level. thanks

andrewg211 commented 6 years ago

Hi @chancer4 you'd just add it to a new JS file. Then include it after slick.

eg

<script type="text/javascript" src="./js/lib/slick/slick.min.js"></script>
<script type="text/javascript" src="./js/extraSlickOptions.js"></script>

Then init slick, something like below.

var myTabs = (function () {

  initSlick = function(){
    var $nav = $('#deal-types ul');
    $nav.slick({
      dots: false,
      infinite: false,
      speed: 300,
      prevArrow: false,
      nextArrow: false,
      autoSlidesToShow: true,
      variableWidth: true,
    });
  }

  return {
    initSlick: initSlick,
  }
})();

myTabs.initSlick();

SagaraZD commented 5 years ago

@ramirezcgn Thanks man. this is saved my day :)

rinellei commented 5 years ago

@ramirezcgn thx, for help, but can you help with integrate to ajax. After add this hack I have one slide to show (default slick parameter, I think). I have func to callback after successful ajax:

function InitSlick($Slick) {
    if(!$Slick.hasClass('slick-initialized')) {
        AutoSlick($);
        // slider
        $Slick.slick({
            draggable: false,
            speed: 250,
            // slidesToShow: show_default,
            autoSlidesToShow: true,
            slidesToScroll: 1,
            infinite: false,
            prevArrow: "<button class='prev_btn'><i class='fas fa-chevron-left'></i></button>",
            nextArrow: "<button class='next_btn'><i class='fas fa-chevron-right'></i></button>"
        });
    }
}

and have callback:

function getS(num, param){
    if(num != ''){
    $.ajax({
    type: "POST",
    url: "pages.php",
    data: "numb=" + num,
    success: function(msg){     
        var Slider = $('#pages_preview');
        $(Slider).slick('unslick'); /* ONLY remove the classes and handlers added on initialize */
        $('.page').remove();            
        $('#pages_preview').html(msg);          
        HideDataPreloader('pages'); 
        InitSlick($(Slider));
    }
    });
    }
}
davidfrancisraj commented 4 years ago

will the fix work for vertical slide?

tdrdimov commented 4 years ago

What I did to work around this one is a hidden input field with a value of the slider array count which then I pull the value from that field and set to the slidesToShow option.

Gourab-Brand-Impetus commented 10 months ago

https://react-slick.neostack.com/docs/example/variable-width/

Go with this, works wonders!

Abhishek332 commented 6 months ago

Calculate how many slides you can show in the container based on the container's width divided by the slide's width ....

I kind of see what you're getting at now... but its very easy for you to do yourself before the carousel loads :) - you must consider that if @kenwheeler includes every possible functionality, even ones that you can do yourself with ease, then your users will be downloading so much code bloat. :)

Simon

On Wed, Feb 25, 2015 at 3:57 PM, pavsid notifications@github.com wrote:

@simeydotme https://github.com/simeydotme A calculation for what?? The number of slides to show at a width of 1600, 1200, 1024, 768, 480px, etc? I presume this "auto" setting would require that the slides have been set a width themselves so the logic knows how many can be shown in the current viewport. I'm surprised this hasn't been asked before actually, and I thought that maybe there was already a way to do it. — Reply to this email directly or view it on GitHub #1071 (comment).

my bad I didn't get on this issue before, I just created whole carousal from scratch to handle autoSlidesToShow 🥲.