Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added outer edge clipping #2635

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

RicardoEPRodrigues
Copy link

Outer edge clipping only affects slick with variable width on.

This new option outerEdgeLimit allows the last element of the slider to stop at its limit, instead of leaving empty space.

Outer edge clipping only affects slick with variable width on.

This new option `outerEdgeLimit` allows the last element of the slider to stop at its limit, instead of leaving empty space.
@leggomuhgreggo
Copy link
Collaborator

Thanks!

@RicardoEPRodrigues
Copy link
Author

I noticed a bug.

When more than one item is visible and the outer edge has been reached, the next button should be disabled, but it stays visible.

Unfortunately I currently don't have time to fix it up. If someone would take a look at that it would be great.

ryanurban added a commit to ryanurban/slick that referenced this pull request Jan 26, 2017
Brings in Slick PR on most recent master branch code:

kenwheeler#2635
ryanurban added a commit to ryanurban/slick that referenced this pull request Feb 15, 2017
@falkartis
Copy link

Hi I have tried to solve the same issue using a different approach unfortunately I didn't check other pull requests before starting to write.
Look at this #2817 and tell me what you think about.

It seems your solution is more efficient, does it work fine?

@RicardoEPRodrigues
Copy link
Author

@falkartis I haven't been able to test it a lot and still haven't fixed the bug I wrote about before.

From what I remember from the code, to fix the bug I need some small conditions here and there (mainly to enable and disable prev-next buttons), but never got around to do them.

@falkartis
Copy link

falkartis commented Mar 29, 2017 via email

@groomain
Copy link

groomain commented May 9, 2017

@RicardoEPRodrigues Exactly what I need. Didn't found the fix for the next button yet. But I'll use this in my website.

Thanks !

@ianthedev
Copy link

Thank you! You are a life saver.

@SrPatinhas
Copy link

I didn't test or check if this was the solution, and even if you already tried this, but, what if we call _.updateArrows(); after the calcs are made? Or just duplicate the code inside (I would prefer not :) )

@SrPatinhas
Copy link

SrPatinhas commented Aug 7, 2017

@RicardoEPRodrigues after a quick test, i saw that this example fiddle with release didn't update the right arrow as well, so, maybe is not a problem with this patch itself.
Fiddle with this fix
But unfortunately, i tried the same example but with your patch, and i saw that the drag of the slide was flickering. so maybe we need to change the position of the track on other function so it doesn't become flickerish when dragged.

But indeed fix the problem that we have with the end of the slide :D 🌮 🎉

nfabredev added a commit to Boaterfly/jquery-slick-rails that referenced this pull request Dec 18, 2017
…hen infinite = false:

When infinite is set to false the last slide would come all the way to the left, thus leaving a whitespace the size of the slider container.

This use [this pull request](kenwheeler/slick#2635) on source library to correct this behavior.
@groomain
Copy link

groomain commented Jan 4, 2018

Anyone found a solution to disable the next button when the outer edge has been reached ?

@RicardoEPRodrigues
Copy link
Author

Unfortunately I didn't get that far. I do suspect there may be a function, that determines if the buttons should be shown, that is being called too early.

@markmaurerrr
Copy link

@kenwheeler @leggomuhgreggo i'm using this lifesaving fix for about one year now in several sliders. Will this ever be finished and integrated into the base?!

@RicardoEPRodrigues
Copy link
Author

I started this for a project I was working on and decided to share it. Since I didn't had the time to fix it, I hoped someone would.

Glad I could help you out!

@myslead
Copy link

myslead commented Apr 18, 2018

@kenwheeler @leggomuhgreggo is this going to be merged in base at some point?

@sanchez089
Copy link

sanchez089 commented May 2, 2018

Fixed the problem with the arrows for me:

Added new condition to the updateArrows function:

Slick.prototype.updateArrows = function() {

        var _ = this,
            centerOffset;

        centerOffset = Math.floor(_.options.slidesToShow / 2);

        if ( _.options.arrows === true &&
            _.slideCount > _.options.slidesToShow &&
            !_.options.infinite ) {

            _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
            _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');

            if (_.currentSlide === 0) {

                _.$prevArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
                _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');

            } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) {

                _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
                _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');

            } else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) {

                _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
                _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');

            }

        }
        if ( _.options.arrows === true &&
            _.slideCount > _.options.slidesToShow &&
            !_.options.infinite && _.options.outerEdgeLimit){

            var lastSlide = _.$slides.last();
            var lastSlideOffsetRight = ($(window).width() - (lastSlide.offset().left + lastSlide.outerWidth()));
            var sliderOffsetRight = ($(window).width() - (_.$slider.offset().left + _.$slider.outerWidth()));
            var lastSlideOffsetSlider = lastSlideOffsetRight - sliderOffsetRight;

            if(lastSlideOffsetSlider > -1) {
                _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
            }
            else {
                _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'true');
            }
        }

    };

Added updateArrows to the postSlide function:

Slick.prototype.postSlide = function(index) {

        var _ = this;

        if( !_.unslicked ) {

            _.$slider.trigger('afterChange', [_, index]);
            _.updateArrows();

            _.animating = false;

            _.setPosition();

            _.swipeLeft = null;

            if ( _.options.autoplay ) {
                _.autoPlay();
            }

            if (_.options.accessibility === true) {
                _.initADA();
            }

        }

    };

Now you are able to apply styles to .slick-disabled or :not(.slick-disabled)

@RicardoEPRodrigues
Copy link
Author

When I have time I'll update my branch.

@sanchez089
Copy link

Edited my post:
Added a relativity to the width of the slider

@joaopslins
Copy link

Hey folks, I'm having this issue too and it would be really nice if this PR is merged to the library. Is there anything blocking it? Is it tests? Looking to help so we can have this available for everyone. Thanks!

@RicardoEPRodrigues
Copy link
Author

@joaopslins I don't know why it still hasn't been merged. I created this fix and @sanchez089 contributed to "polish the edge", but still no comment or merge from the developers.

@joaopslins
Copy link

joaopslins commented Feb 6, 2019

@RicardoEPRodrigues I see, I've copy pasted our code here to check if it solves my issue and it does! I just noticed 1 minor issue:

  • After load, the arrows don't appear at first, if I slide one item, they appear, and then can be used normally - only happens when outerEdgeLimit: true.

EDIT: My slick call is as follows:

  $element.slick({
    dots: false,
    arrows: true,
    variableWidth: true,
    infinite: false,
    outerEdgeLimit: true,
  });

@joaopslins
Copy link

Just found another issue, it looks like there is a certain threshold where the last element does not fully appear, the next button appears, but it does not work when clicked. I'll try to work on a shareable example tomorrow.

@joaopslins
Copy link

joaopslins commented Feb 7, 2019

@RicardoEPRodrigues Got the example for the threshold not working on the last element: http://jsfiddle.net/yfvp78xr/19/

The last item does not show fully, the button appears but does not work. Probably your screen resolution can affect this repro but I got this on 1920x1080 and 1366x768 resolutions.


About the arrows not appearing when opening the page, I couldn't reproduce on the fiddle. By debugging, I can see that when the updateArrows() function is called, the calculation is getting the wrong value. In this case, _.$slider.outerWidth() is reading 40000px.

image

Because of that, the last arrow is set as disabled. The slick-track element has the inline style setting width: 40000px. But the example on the fiddleJS also has the inline width: 30000px but the function reads the correct value. I have no clue why it's reading that value.

@joaopslins
Copy link

joaopslins commented Feb 7, 2019

Managed to solve the hidden arrow issue by calling updateArrows() after the .slick() call, not ideal but works for me.

EDIT: Found the culprit. I was setting a display: none class on my slider and removing it in the .init() callback. I've put this so the slider wouldn't flicker while loading the JS on my page, once I removed it, it worked. This issue is specific from my project so I don't believe the code needs changes. I'm just documenting here if someone goes through the same issue.

@joaopslins
Copy link

@RicardoEPRodrigues about the threshold bug I've posted here earlier, I noticed it works as expected if I comment this on line 1232:

            // [...]
            var slideOuterWidth, slideOffset, slideRightBoundary;
            slideOuterWidth = $(slide).outerWidth();
            slideOffset = slide.offsetLeft;
            /* if (_.options.centerMode !== true) {
                slideOffset += (slideOuterWidth / 2);
            } */

            slideRightBoundary = slideOffset + (slideOuterWidth);
            // [...]

Could you explain what was the motivation of this condition? For me it only works if I remove this piece of code.

Removed unnecessary addition to the offset variable, that made the last element inaccessible.

Fixed UpdateArrows where last element width exceeds the window width, now works correctly when last element is reached.
@RicardoEPRodrigues
Copy link
Author

I took some time a fixed 2 or 3 bugs.

Basically I restricted outerEdgeLimit for when centerMode is off, which was creating some issues.

👏 👏 Next Bug

I removed the code referenced by @joaopslins #2635 (comment), thank you! 🎉

👏 👏 Next Bug

I also fixed an annoying bug when the last element has width greater than the window, this would allow the arrows to remain active, which is now fixed! 😄

Try the fixes here: http://jsfiddle.net/RicardoEPRodrigues/284ruc1d/ . Mess around with the widths to test it out.

@joaopslins
Copy link

joaopslins commented Feb 18, 2019

Nice! Thanks for these changes! The center mode really doesn't make much sense with this new option on so the restriction is good.

Just a heads up, I think the jsfiddle you posted didn't include the latest changes, I've pasted the new code on the previous fiddle. Here is an updated version: http://jsfiddle.net/bcgLaj46/

@RicardoEPRodrigues
Copy link
Author

Hey, I just wanted to comment on the lack of updates in the master branch of the Slick. It does appear to be dead or inactive. There are 865 open issues and 169 pull requests dating back to 2014.

Those doing Pull Requests are the ones keeping this alive. Thank you everyone!

@joaopslins
Copy link

Hello again folks,

Got another issue when I used a slidesToScroll option greater than 1.
Steps to reproduce:

  • This fiddle is the same as the previous one, but with slidesToScroll: 2 setting: http://jsfiddle.net/muh1yka9/
  • Go to the last slide
  • Then go to the first one, except you'll notice it stops on Slide 2, the arrow appears, but once clicked no action is performed.

I managed to get this working by adding a new condition on the method slideHandler :

if (_.options.outerEdgeLimit && _.options.centerMode === false) {
    outerEdgeSlideNumber = _.getOuterEdgeSlideNumber();

    if (outerEdgeSlideNumber < index) {
        index = outerEdgeSlideNumber
    }

    if (index < 0) { // new condition
      index = 0;
    }
}

Fiddle with this fix: http://jsfiddle.net/j3dt5suv/3/

I'm not sure if more checks are needed elsewhere but this worked for me, what do you think @RicardoEPRodrigues ?

@RicardoEPRodrigues
Copy link
Author

@joaopslins Hello! On future improvements I invite you to do pull requests on my branch, this way we can workout the kinks more easily 😄

Ok, some notes here:

@RicardoEPRodrigues
Copy link
Author

It turns out that the index bug is from Slick, not from the outerEdgeLimit option, the option basically allows a scenario for the bug to appear.

New fiddle available: https://jsfiddle.net/RicardoEPRodrigues/284ruc1d/

Please comment and report more bugs.

@k-cogswell
Copy link

@RicardoEPRodrigues

I'm trying to use this update in one of my sites but it seems to be breaking my slider. The fiddle you provided (https://jsfiddle.net/RicardoEPRodrigues/284ruc1d/) also doesn't seem to be working?

Maybe I'm missing something here?

@joaopslins
Copy link

For some reason it looks like jsfiddle is broken. Not even the default jsfiddle works (this one).

@k-cogswell I'm using this PR code and it is working well. It will be hard to help you without the jsfiddle working though.

@salugubelly
Copy link

I am looking for this PR to be merged. Please let me know if this can be merged ?

@shielakn
Copy link

How do you do this without changing the slick.js? Please let me know

@salugubelly
Copy link

salugubelly commented Dec 20, 2019 via email

@tylik1
Copy link

tylik1 commented Feb 26, 2020

Unfortunately this fix doesn't work properly. When you use mobile slider and drag to the end, several times, then you won't be able to drag back.
Or if you click the next arrow and the slides are at the end, then you won't be able to click prev button, until you click the same amount of times, you clicked the next button.

My solution was to count how many items can fit in the visible area, and put that number in slidesToShow. Then combined with variableWidth gave me desired behavior. Though on screen resolution change there is still the need to update slidesToShow

@RicardoEPRodrigues
Copy link
Author

Hey, @tylik1 can you show us the changes in a jsfiddle? So we can try them out and correct the code.

If you'd like you can make a pull request with the changes on my repository! 😄

@gauravmanerkar
Copy link

Hi, any update?

@tylik1
Copy link

tylik1 commented Oct 13, 2020

Hey, @tylik1 can you show us the changes in a jsfiddle? So we can try them out and correct the code.

If you'd like you can make a pull request with the changes on my repository! 😄

I've implemented this, more like a hack. I'm calculating the width of the slider container, then counting number of slides, that fits that container, to pouplate slidesToShow. Sorry, don't have much time to create a fiddle, but will post some code here, hopefully it will become a bit clear.

function sliderMenu() {
       //Slick container
        var $sliderMenu = $('.js_object_detail-nav__items');

        //Slick container width
        var sliderMenuWidth = $sliderMenu.width();

        //Calculated total width of slides
        var sliderMenuChildrenWidth = 0;

        //Amount of slides fitting in a visible area
        var sliderMenuChildLastVisibleIndex = 0;

        $sliderMenu.children('.object-detail-nav__item').each(function (ind) {
           //Loop through each slide and add its width to a variable
            sliderMenuChildrenWidth += $(this).width()
            
           // If slider container element width is bigger then calculated slides width, then increment visible index of slides
            if (sliderMenuWidth > sliderMenuChildrenWidth) {
                sliderMenuChildLastVisibleIndex += 1
            }
        });

            $sliderMenu.slick({
                slidesToShow: sliderMenuChildLastVisibleIndex,
                slidesToScroll: sliderMenuChildLastVisibleIndex,
                infinite: false,
                variableWidth: true
            });
    }

@ianthedev
Copy link

ianthedev commented Oct 30, 2020

The swipeToSlide option becomes unstable. Here is a demo.

@agzwt
Copy link

agzwt commented Oct 30, 2020

Hey @RicardoEPRodrigues

I have added Version: 1.9.0 in my project it is working good

White spacing issues solved and it is working properly but I have seen the new issue is that when I use the

variableWidth: true,
infinite: false,
outerEdgeLimit: true,

slider next arrow not disable on last slide.

@higorch
Copy link

higorch commented Dec 8, 2021

Slick Slider

$('.items').slick({
    infinite: false,
    slidesToShow: 1,
    variableWidth: true,
    centerMode: true,
    centerPadding: '0',
    outerEdgeLimit: true,
});

OR

$('.items').slick({
    infinite: false,
    slidesToShow: 1,
    variableWidth: true,
    outerEdgeLimit: true,
});

@mrleblanc101
Copy link

mrleblanc101 commented Sep 21, 2022

I have one weird issue.
Without this fix, I have empty whitespace at the end of variableWidth slick slider which is normal, but unwanted in my case.

Capture d’écran, le 2022-09-21 à 13 46 45

With this fork,it fix the first slider, but the second slider cannot be scrolled at all.
The second carrousel has both arrow disabled, but it's not on the last slide as you can tell from the first screenshot.

Capture d’écran, le 2022-09-21 à 13 43 45

EDIT: The issue was caused by display: flex; on the parent of the Slider.
Caused an incorrect calculation of _.$slider.outerWidth() and sliderOffsetRight.
It worked after removing the flex.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.