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

Selecting the slide that is clicked upon #81

Closed
ChristophLabacher opened this issue Mar 12, 2015 · 10 comments
Closed

Selecting the slide that is clicked upon #81

ChristophLabacher opened this issue Mar 12, 2015 · 10 comments

Comments

@ChristophLabacher
Copy link

If several slides are visible, it would be a nice feature to have a non-selected slide selected when clicked upon.

$('.slider .slide').click(function()    {
    var index =  $(this).index();
    landingSlider.flickity('select', index);    
});

This solution is causing trouble however when wrapAround is set to true: when the selected slide is the first one and the slide that is clicked upon is the last one (or the other way around) instead of going directly to the (already visible) slide it makes the slider spin around one time (similar to the behavior of .flickity( 'previous', true ); in a slider with wrapAround set to false). I would want it to behave the same way a click on the next/previous arrow does in this situation.

I tried to fix this problem (very roughly) be using the method mention above in the edge cases, however this did not change anything:

$('.slider .slide').click(function()    {
    var index =  $(this).index();
    var selected = landingSlider.flickity('selectedIndex'); 

    if (selected == 0 && index == 4)    {
        landingSlider.flickity('previous', true);   
    } else if (selected == 4 && index == 0) {
        landingSlider.flickity('next', true);   
    } else  {
        landingSlider.flickity('select', index);    
    }

});

So if these is easily achievable I would appreciate being pointed in the right direction, otherwise this might be a feature request ;)

@desandro
Copy link
Member

desandro commented Mar 12, 2015

Thanks for this request! You can do this with staticClick

// Flickity v1
$gallery.on( 'staticClick', function( event, pointer, cellElement, cellIndex ) {
  if ( typeof cellIndex == 'number' ) {
    $gallery.flickity( 'select', cellIndex );
  }
});
// Flickity v2
$gallery.on( 'staticClick.flickity', function( event, pointer, cellElement, cellIndex ) {
  if ( typeof cellIndex == 'number' ) {
    $gallery.flickity( 'select', cellIndex );
  }
});

See jQuery CodePen demo or vanilla JS demo. I've also linked to these demos in Extras

@ChristophLabacher
Copy link
Author

Thank you for your quick help!

The example you provided is of course a much way to achieve the same thing my code does.
However this does not solute my problem: when wrapAround is set to true, the slider spins around really quick instead of behaving like the previous button was clicked:

http://codepen.io/ChristophLabacher/pen/pvxYjR

Maybe there is no easy way of achieving this (I've looked into the code of flickity, and it seems like caching those edge cases requires deep access to the sliders position x), but I'm afraid I am just not having the right idea.

I also noticed that the staticClick event is only fired when draggable is set to true. Is there a similar event (that also includes the cellElement and cellIndex information) for sliders that are not draggable?

Again, thank you for your help!

@desandro
Copy link
Member

Try this code to resolve wrapAround: http://codepen.io/desandro/pen/wBYbrZ

var flkty = $gallery.data('flickity');
$gallery.on( 'staticClick', function( event, pointer, cellElement, cellIndex ) {
  if ( typeof cellIndex == 'number' ) {
    var len = flkty.cells.length;
    cellIndex = getClosestIndex( cellIndex, flkty.selectedIndex, len );
    cellIndex = getClosestIndex( cellIndex, flkty.selectedIndex, -len );
    $gallery.flickity( 'select', cellIndex );
  }
});

function getClosestIndex( index, selectedIndex, delta ) {
  var deltaIndex = index + delta;
  return Math.abs( deltaIndex - selectedIndex ) < Math.abs( index - selectedIndex ) ? deltaIndex : index;
}

I also noticed that the staticClick event is only fired when draggable is set to true.

Try this code for wrapAround + draggable: false http://codepen.io/desandro/pen/ZYqNrO

var flkty = $gallery.data('flickity');
$gallery.on( 'click', function( event ) {
  var clickedCell = flkty.getParentCell( event.target );
  var cellIndex = clickedCell && utils.indexOf( flkty.cells, clickedCell );
  if ( typeof cellIndex == 'number' ) {
    var len = flkty.cells.length;
    cellIndex = getClosestIndex( cellIndex, flkty.selectedIndex, len );
    cellIndex = getClosestIndex( cellIndex, flkty.selectedIndex, -len );
    $gallery.flickity( 'select', cellIndex );
  }
});

function getClosestIndex( index, selectedIndex, delta ) {
  var deltaIndex = index + delta;
  return Math.abs( deltaIndex - selectedIndex ) < Math.abs( index - selectedIndex ) ? deltaIndex : index;
}

@ChristophLabacher
Copy link
Author

Works like a charm – Thank you!

@Yetispapa
Copy link

Nice one! Thanks

@ovbm
Copy link

ovbm commented Apr 25, 2017

Hi, this solution from 13th of May 2015 doesn't seem to work anymore. Any idea why that is?

@ovbm
Copy link

ovbm commented Apr 25, 2017

Found the error, for jquery it's 'staticClick.flickity' and not just 'staticClick' event.

@cameroncowden
Copy link

Successfully implemented the May 2015 solution (wrapping, draggable) with one modification - if you aren't using jQuery, you'll need to change the line that reads:
$gallery.flickity( 'select', cellIndex );

In my case, I initialize the gallery with vanilla JS as flktythumbs like so:
var flktythumbs = new Flickity( vtc, { // options });

So I change the line which selects the new slide to:
flktythumbs.select( cellIndex );

@nicooprat
Copy link

nicooprat commented Jan 30, 2018

What if cellElement is a link? How can I prevent click if slide is not selected? Tried this without success:

$(slider).on('staticClick.flickity', (e, pointer, cellElement, cellIndex) => {
  e.originalEvent.preventDefault()
  e.originalEvent.stopPropagation()
  e.preventDefault()
  e.stopPropagation()
  pointer.preventDefault()
  pointer.stopPropagation()
})

Any idea? For now I had to prevent it in another event:

$(sliderChild).click(e => e.preventDefault())

@CorySchulz
Copy link

This should really be a standard feature in Flickity since any time a person is interacting with a carousel of items they expect it to go to any slide they click on

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

No branches or pull requests

7 participants