Slick: Swiping triggers click, not always wanted

Created on 6 Nov 2014  路  21Comments  路  Source: kenwheeler/slick

A change from 1.3.10 where you removed return false is giving me a behavior I don't want.

Swiping a video counts as a click and plays the video offscreen:
http://codepen.io/matthewlein/pen/miFJs

It could be the wistia.js code doing weird stuff, but 1.3.10 was perfect for me. Could this click behavior be opted in or out, or as an alternative the return false, could you instead use a custom event like .trigger('slideClick.slick') or something like that to give people a click hook?

Most helpful comment

Code for the already described solution:

carousel.slick();

var isSliding = false;

carousel.on('beforeChange', function() {
    isSliding = true;
});

carousel.on('afterChange', function() {
    isSliding = false;
});

carousel.find(".foo").click(function() {
    if (isSliding) {
        return;
    }

    // ...
});

All 21 comments

I'm wondering if they have that hooked up to touchstart/touchend.

This is relevant, bear with me. I saw a click triggered when swiping a slide that contained a prettyPhoto.js link (causing the lightbox to open). I then removed the prettyPhoto anchor tag and replaced it with a plain anchor tag around the image. Swiping the plain anchor tag did not trigger a click. That leads me to believe that wistia/prettyPhoto are activating on touchstart/touchend as ken suggested. If the issue was with slick, I would have expected the plain anchor tag to receive a click as well.

Right, it could be wistia. So the question is...should a library trigger standard events, or should it prevent standard events and force opt in through custom events to prevent these?

Does opt-in custom events solve these and other problems? or just make more?

Would it make sense to put a transparent element on top of it, and then pass the event down on click only?

I have a similar issue, but instead my code is all internal. I have an anchor tag, but I show a modal popup through javascript when the user clicks on a link. If the user scrolls slick.js, the JS click event fires and the modal displays. My simplified code and potential solution follows.

<div class="slick-slider">
  <div class="slide-container">
    <!-- Click event is added in JS and handles a Foundation reveal-modal popup for this particular slide -->
    <a href="#" id="slide_id_X">
      <div class="content-container">
        <div class="title">My Title</div>
        <div class="image"><%= image_tag logo(:medium) %></div>
        <div class="description">My description</div>
      </div>
    </a>
  </div>
</div>
$('#slide_id_X').click(function(e) {
  e.preventDefault();
  $('#my_modal').foundation('reveal', 'open', '/content/unauthorized');
});

Potential Solution:

  1. On mousedown, save the starting mouse coordinates
  2. On mouseup, save the final mouse coordinates
  3. On click, compare the starting and final coordinates and if some _significant_ movement occurred, cancel the modal popup.

@kayzee I think that logic is already in slick here: https://github.com/kenwheeler/slick/blob/ef16dc13ebdd0d0a8776b24c5cf19b3178d0e879/slick/slick.js#L1748
But I'm not sure it works in the way we need it to. @kenwheeler maybe you can clarify.

For my case, and probably the others, clicks and touchends should not fire when a swipe triggers a slide advance, only when the swipe isn't long enough and the slide snaps back to place. _shouldClick seems like it should work for this, but it doesn't...

I ran into the same issue and it looked like the click handler was bound to the '.slide-list' element that is created:

https://github.com/kenwheeler/slick/blob/ef16dc13ebdd0d0a8776b24c5cf19b3178d0e879/slick/slick.js#L969

Binding a click event to that element worked for me. You will have to use the event.target to then delegate appropriately.

$('body').on('click', '.slick-list', function(e) {
      ...
});

Fixed on dev

Great work on this plugin @kenwheeler. I'm excited to test out the fix. Does fixed on dev mean locally and not pushed to master? I typically have a master and develop branch (git-flow) but I don't see any other branches in your repo.

Its on master, but beware, there are some breaking changes so I dont recommend using it until I finish up the rest of 1.4 and document everything.

No prob. Thanks again!

I believe this issue is still happening in 1.4. Please see fiddle http://jsfiddle.net/xxue5to9/
Thanks!

So, a click event will fire from swipe. It won't click a link, but your click event will fire @tibineagu . So what would be the ideal resolution? A supressClick option or something?

Thanks for the reply. I would naturally assume click events should fire on click, not on drag (or more exactly when releasing after drag).
The current behaviour makes it almost impossible to build a carousel of items that trigger stuff on click (such as opening modals).

I think expected behaviour is to have the click events work on click (or tap), when the carousel is not moving or swiping. If current behaviour is to be preserved then I think an option that alters it slightly would be a good solution.

I dont think this issue is native to slick. Try swipe clicking this:

http://jsfiddle.net/7un15ke8/

You're right, but in that context i don't think anyone expects to swipe-click on a static element.

I did build a workaround for supressing and unsupressing default click based on slick beforeChange and afterChange events, so my earlier observation can be ignored.

Thank you for getting involved and being so responsive, the plugin is tremendously helpful!

Hey @tibineagu, I'm running into the same issue with my lightboxes that are connected to images in the carousel. What's your workaround using beforeChange and afterChange look like?

@phoenixMag00
Did you get an answer to your question? I need the same fix as you needed. Can you help out?

No action needed. Found a good solutions. Used that kind of event binding @mikerogerz mentioned in this issue: https://github.com/kenwheeler/slick/issues/1015

Code for the already described solution:

carousel.slick();

var isSliding = false;

carousel.on('beforeChange', function() {
    isSliding = true;
});

carousel.on('afterChange', function() {
    isSliding = false;
});

carousel.find(".foo").click(function() {
    if (isSliding) {
        return;
    }

    // ...
});

After searching two days i found this and it helps. What i needed to, was to stop the Default Event while sliding like:
carousel.find(".foo").click(function() {
if (isSliding) {
event.stopImmediatePropagation();
event.stopPropagation();
event.preventDefault();
return;
}
});

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Libig picture Libig  路  3Comments

ericestes picture ericestes  路  3Comments

msavov picture msavov  路  3Comments

jamesinealing picture jamesinealing  路  3Comments

jeremymandel picture jeremymandel  路  3Comments