How to avoid accidental click events while dragging? - javascript

I have a slider built using Slick, each slide has a data attribute that get copied to an input field when a slide get clicked then the form with the value on that input field get submited.
The problem is that if i have a a multiple slides "maybe by choosing Kissen=>Sitz from the select boxes above then try to drag the slides to scroll through them that may cause a click event (that happens most of the time but not always) so im wondering if there is an easy way to prevent that accidental clicks?
<form name="product_select" id="product_select_form" action="conctact-details/" method="post">
<input type="text" id="product_id" name="product_id">
</form>
<div class="slick-slider">
<div class="slick-slide" data-product-id="1" data-product-cat="1"><img src="https://www.solodev.com/assets/carousel/image1.png">Orthopädisches Sitzkissen</div>
<div class="slick-slide" data-product-id="2" data-product-cat="1"><img src="https://www.solodev.com/assets/carousel/image2.png">Hämorrhoiden Kissen</div>
<div class="slick-slide" data-product-id="3" data-product-cat="1"><img src="https://www.solodev.com/assets/carousel/image3.png">Rückenkissen</div>
<div class="slick-slide" data-product-id="4" data-product-cat="1"><img src="https://www.solodev.com/assets/carousel/image4.png">Comfort Cushion</div>
<div class="slick-slide" data-product-id="5" data-product-cat="1"><img src="https://www.solodev.com/assets/carousel/image5.png">All-in-one</div>
<div class="slick-slide" data-product-id="6" data-product-cat="1"><img src="https://www.solodev.com/assets/carousel/image6.png">Aufstehkissen</div>
<div class="slick-slide" data-product-id="7" data-product-cat="1"><img src="https://www.solodev.com/assets/carousel/image7.png">Wedge Cushion</div>
</div>
$(document).ready(function() {
$('.slick-slider').hide();
$('.slick-slider').slick({
dots: true,
infinite: false,
speed: 300,
slidesToShow: 4,
slidesToScroll: 4,
responsive: [{
breakpoint: 1024,
settings: {
slidesToShow: 3,
slidesToScroll: 3
}
},
{
breakpoint: 800,
settings: {
slidesToShow: 2,
slidesToScroll: 2
}
},
{
breakpoint: 500,
settings: {
slidesToShow: 1,
slidesToScroll: 1
}
}
]
});
});
$(".slick-slide").click(function() {
$product_id = $(this).data('product-id');
$('#product_id').val($product_id);
$('#product_select_form').submit();
https://jsfiddle.net/arabtornado/gjxnmk4p/198/

$('.slick-slide').on('mousedown', function (evt) {
$('.slick-slide').on('mouseup mousemove', function handler(evt) {
if (evt.type === 'mouseup') {
$product_id = $(this).data('product-id');
$('#product_select_form').submit();
$('#product_id').val($product_id);
}
$('.slick-slide').off('mouseup mousemove', handler);
});
});
Refrance:
How to distinguish mouse "click" and "drag"

I also had trouble with this.
What I did was to track if there are movement between the mousedown event and the mouseup event. I count every movement of the mouse and just add it to a counter.
Every mousedown, I reset the counter to 0.
If the movement is too large, then it is not considered a click.
let dragmovement = 0;
$('#slick-selector').click(function(e){
if(dragmovement <= 20){
// proceed with click event if mouse movement is minimal
// change constant depending on your level of tolerance
console.log("clicked, not dragged")
}
})
$(".#slick-selector").mousedown(function(e){dragmovement = 0;
//onmousedown inside the element, set counter to 0
// start tracking mouse movement
$(document).mousemove(function(){dragmovement++;})
//even mouse movement outside the slick is tracked
//every movement will add +1 to counter
}).mouseup(function(){
$(document).unbind('mousemove')
// release mouse movement tracker
})
`

Related

Embla Carousel - select inner text

I have a carousel built using Embla Carousel (embla-carousel-react).
The elements within the carousel contain an image and some text. The text is not selectable, but I would like it to be.
When I set draggable: false, I can select the text inside the carousel, but now I can no longer scroll the carousel to the next slide.
Is there a way I can have both - select and copy text with a mouse click and drag, and swipe to the next scroll with a more pronounced swipe or scroll gesture?
const EmblaCarousel = ({ children, nextScroll, recordCurrentSlide }) => {
const { height } = useWindowDimensions()
const [viewportRef, embla] = useEmblaCarousel({
axis: "y",
skipSnaps: false,
startIndex: 0,
draggable: true,
dragFree: false,
slidesToScroll: 1,
loop: true,
},
[WheelGesturesPlugin()]);
return (
<div className="embla">
<div className="embla__viewport" ref={viewportRef}>
<div className="embla__container">
{children}
</div>
</div>
<style jsx>{`
:global(.embla__container) {
height: ${height};
}
`}</style>
</div>
);
};
Thanks!
I'm the creator of Embla Carousel and at the time of writing, what you want to achieve isn't possible. This is because Embla calls event.preventDefault() on touch and mouse events when the carousel has draggable: true set.
If you want to discuss this design choice and suggest changes, you may create a new discussion.

Slick JS Custom Navigation not functioning

I have a basic slickJS 1.8 Carousel and trying to modify how pagination looks. There are many stackoverflow similar questions however none worked for me. Carousel works, I can swipe on left and right, dots work fine however I'd like to achieve this presentation when it comes to navigation <- 1/3 -> (where -> or <- is an icon) Here is the setup
var $status = $('.count');
var $slickElement = $('.carousel');
$slickElement.on('init reInit afterChange', function (event, slick, currentSlide, nextSlide) {
//currentSlide is undefined on init -- set it to 0 in this case (currentSlide is 0 based)
var i = (currentSlide ? currentSlide : 0) + 1;
$status.html('<button type="button" class="custom-prev"><</button>' + '<span class="current_slide">' + i + '</span> / <span class="total_slides"> ' + slick.slideCount + '</span>' + '<button type="button" class="custom-next">></button>');
});
$('.carousel').slick({
infinite: false,
speed: 300,
slidesToShow: 4.5,
slidesToScroll: 4,
arrows: true,
nextArrow: $('.custom-next'),
prevArrow: $('.custom-prev'),
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
infinite: true,
dots: true
}
},
{
breakpoint: 600,
settings: {
slidesToShow: 2,
slidesToScroll: 2
}
},
{
breakpoint: 480,
settings: {
slidesToShow: 1,
slidesToScroll: 1
}
}
// You can unslick at a given breakpoint now by adding:
// settings: "unslick"
// instead of a settings object
]
});
Next and Previous buttons appear however navigation to next slides don't work but dots work. Disabled dots for didn't make any difference to my custom next and previous buttons, is there anything I'm doing wrong? I'm not a JS expert hence some guidance would be appreciated.
You can fix this with a few amends here but you will still need to tweak it to get the presentation you want. See comments in code for explanation.
Example: https://codepen.io/alexpetergill/pen/56c63447c77c07e84407f08016cf17b2
var $status = $('.count');
var $slickElement = $('.slick-slider');
// You only need to add the controls on init. Anything more will probably result in issues with behaviour.
$slickElement.on('init', function () {
$status.before('<button type="button" class="custom-prev"><</button>' + '<button type="button" class="custom-next">></button>');
});
$slickElement.on('init reInit afterChange', function (event, slick, currentSlide, nextSlide) {
var i = slick.currentSlide + 1; // This will get you the current slide on init.
$status.html('<span class="current_slide">' + i + '</span> / <span class="total_slides">' + slick.slideCount + '</span>');
});
// I've simplified this for sake of example. You have to bare in mind that if your slidesToShow is more than 1 then your numbered pagination probably wont work how you expect as the number will reflect the first item in a row.
$('.slick-slider').slick({
infinite: false,
speed: 300,
slidesToShow: 1,
slidesToScroll: 1,
arrows: true,
nextArrow: $('.custom-next'),
prevArrow: $('.custom-prev'),
});
// Not having the arrow controls within the slick container probably results in the event listeners not being added. You can simply add them yourself here.
$('.custom-prev').click(function(){
$slickElement.slick('slickPrev');
})
$('.custom-next').click(function(){
$slickElement.slick('slickNext');
})

Force cloning slides in slick

I have a needed that I've not been able to develop.
I'm using slick to show 3 slides, but only the center one shows all the information. I need an infinite slider in order to get all the slides being at the center.
The problem is when the slides are only 3, because it stops. I would need to force the slider clonning the slides as if i had 4 or more slides...
$('.center').slick({
centerMode: true,
centerPadding: '0px',
slidesToShow: 3,
slidesToScroll: 1,
dots: false,
focusOnSelect: true,
adaptiveHeight: true
});
Here I leave you an example with slides enough: https://jsfiddle.net/f580ys4b/1/
And here an example with only 3 slides: https://jsfiddle.net/f580ys4b/2/
Before initiating Slick, check if the number of slide items is larger than slidesToShow. In case it is not, duplicate the children until there are more slide items than slides to show. Can easily be done with jQuery.
var slideCount = jQuery(".slide").length;
if (slideCount <= 3) {
// clone element
jQuery(".center.slider").children().clone(true, true).appendTo(".center.slider");
}
jQuery('.center').slick({
arrows: false,
centerMode: true,
centerPadding: '0px',
slidesToShow: 3,
slidesToScroll: 1,
dots: false,
focusOnSelect: true,
adaptiveHeight: true
});
My solution based on Rohan answer:
In my case I have a slider with filters, when the filtered elements are the same as the elements to be displayed, the infinite dont working. When I reset the slider when filtering I compare the filtered elements with those that should be displayed and if they are equal I duplicate the elements.
$('.slider-productos').on('reInit', function(event, slick, currentSlide, nextSlide) {
// total sliders number - get option slidesToShow number
// ^ ^
if (slick.slideCount === slick.options.slidesToShow) {
// you can clone on slider or all, it depends on how many slider you want to show
//var toClone = $(".slider-productos .slick-track").children('.slick-slide:nth-of-type(2)');
var toClone1 = $(".slider-productos .slick-track").children('.slick-slide:nth-of-type(1)');
var toClone2 = $(".slider-productos .slick-track").children('.slick-slide:nth-of-type(2)');
var toClone3 = $(".slider-productos .slick-track").children('.slick-slide:nth-of-type(3)');
toClone1.clone().appendTo(".slider-productos .slick-track");
toClone2.clone().appendTo(".slider-productos .slick-track");
toClone3.clone().appendTo(".slider-productos .slick-track");
// Set any option only for refresh slider refresh true
// ^ ^
$('.slider-productos').slick('slickSetOption', 'infinite', true, true);
}
});

How to remove slick slide on mobile?

I'm using the awesome Slick slide on a project.
The problem is: I have a carousel with 5 divs inside. 4 images and a video.
On mobile (< 768px) I want the slider to show only the images, not the video.
I tried to hide the video div by css but that's not working.
Any ideas on how to do this? Anyone had this need before?
Look at the «Filtering» demo at the Slick's documentation. Let's use it to solve the issue.
Set breakpoints that you need, using the responsive option.
Catch the breakpoint event and read the activeBreakpoint property of the carousel. Notabene: when the screen width is greater than the last of the breakpoints, this property returns null.
Call slickFilter and slickUnfilter methods:
slickFilter
Argument filter: selector or function
Filters slides using jQuery .filter syntax
slickUnfilter
Removes applied filter
Beware of an infinite loop: these methods cause a re-initialization of the slider, during which the breakpoint event again occurs (unless the breakpoint is null).
Call these methods during initialization too. Don’t forget to define the init handler before the initialization.
Check the result: https://codepen.io/glebkema/pen/NaGGzv
Slides with the .hide-on-mobile class become hidden when the screen width is 700px or less.
var breakpointMobile = 700,
isChanging = false,
isFiltered = false;
$('#breakpointMobile').text( breakpointMobile );
$('#myCarousel').on('init breakpoint', function(event, slick){ /** 2. and 5. **/
if ( ! isChanging ) { /** 4. **/
$('#breakpointValue').text( String(slick.activeBreakpoint) );
isChanging = true;
if ( slick.activeBreakpoint && slick.activeBreakpoint <= breakpointMobile) {
if ( ! isFiltered ) {
slick.slickFilter(':not(.hide-on-mobile)'); /** 3. **/
isFiltered = true;
}
} else {
if ( isFiltered ) {
slick.slickUnfilter();
isFiltered = false;
}
}
isChanging = false;
}
}).slick({
autoplay: true,
dots: true,
responsive: [ /** 1. **/
{ breakpoint: 500 },
{ breakpoint: 700 },
{ breakpoint: 900 }
]
});
body { /** Decorations **/
font-family: 'Open Sans', sans-serif;
}
.my-carousel img {
width: 100%;
}
.my-carousel .slick-next {
right: 15px;
}
.my-carousel .slick-prev {
left: 15px;
z-index: 1;
}
<h3>Slides 2, 3 and 5 become hidden when the screen width is <span id="breakpointMobile"></span>px or less</h3>
<p>Active breakpoint is <b id="breakpointValue"></b>. Try to resize the workspace.</p>
<div id="myCarousel" class="my-carousel">
<div>
<img src="https://via.placeholder.com/900x300/c69/f9c/?text=1" alt="">
</div>
<div class="hide-on-mobile">
<img src="https://via.placeholder.com/900x300/9c6/cf9/?text=2" alt="">
</div>
<div class="hide-on-mobile">
<img src="https://via.placeholder.com/900x300/69c/9cf/?text=3" alt="">
</div>
<div>
<img src="https://via.placeholder.com/900x300/c33/f66/?text=4" alt="">
</div>
<div class="hide-on-mobile">
<img src="https://via.placeholder.com/900x300/099/3cc/?text=5" alt="">
</div>
<div>
<img src="https://via.placeholder.com/900x300/f93/fc6/?text=6" alt="">
</div>
</div>
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/kenwheeler/slick#1.8.0/slick/slick.min.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/kenwheeler/slick#1.8.0/slick/slick-theme.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="//cdn.jsdelivr.net/gh/kenwheeler/slick#1.8.0/slick/slick.min.js"></script>
Slick has the method slickRemove (you have to scroll down a bit):
Remove slide by index. If removeBefore is set true, remove slide preceding index, or the first slide if no index is specified. If removeBefore is set to false, remove the slide following index, or the last slide if no index is set.
I would just call this method and remove the slide with the video if your current screen size is lower than 768px.
You can unslick at a given breakpoint now by adding:
settings: "unslick"
instead of a settings object
To remove slick slider on mobile view add above code snippet to responsive breakpoint like this
$('.responsive').slick({
dots: true,
infinite: false,
speed: 300,
slidesToShow: 4,
slidesToScroll: 4,
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
infinite: true,
dots: true
}
},
{
breakpoint: 600,
settings: "unslick"
}
// You can unslick at a given breakpoint now by adding:
// settings: "unslick"
// instead of a settings object
]
});

Pause Javascript slider for few seconds on clicking a button below it

I have downloaded Menucool slider code. I am using the demo code present in the above link. My requirement is , when I click on the radio button below the slider, I need the slider to pause for few seconds ( for me it's 10 seconds).The default interval is 2.6 seconds.
I have tried to change the time interval by using Jquery onclick.But it is not working.
Below is my html code.
<div id="sliderFrame">
<div id="slider">
<img src="images/image-slider-1.jpg" />
<img src="images/image-slider-2.jpg" />
<img src="images/image-slider-3.jpg" />
<img src="images/image-slider-4.jpg" />
<img src="images/image-slider-5.jpg" />
</div>
</div>
and my javascript code for slider options is
var sliderOptions=
{
sliderId: "slider",
startSlide: 0,
effect: "series1",
effectRandom: false,
pauseTime: 2600,
transitionTime: 500,
slices: 12,
boxes: 8,
hoverPause: 1,
autoAdvance: true,
captionOpacity: 0.3,
captionEffect: "fade",
thumbnailsWrapperId: "thumbs",
m: false,
license: "mylicense"
};
var imageSlider=new mcImgSlider(sliderOptions);
I have tried to change the pausetime to 10000 in another function which executes after clicking the radio buttons.The code is below.
<script type="text/javascript">
$("document").ready(function(){
$(".active").click(function(){
alert("hi");
var sliderOptions=
{
sliderId: "slider",
startSlide: 0,
effect: "series1",
effectRandom: false,
pauseTime: 10000,
transitionTime: 500,
slices: 12,
boxes: 8,
hoverPause: 1,
autoAdvance: true,
captionOpacity: 0.3,
captionEffect: "fade",
thumbnailsWrapperId: "thumbs",
m: false,
license: "mylicense"
};
})
var imageSlider=new mcImgSlider(sliderOptions);
})
</script>
Can someone please help me how to achieve this functionality..
Check the Methods supported by Menucool slider library.
pauseTime option will be used only on mouseout, mouseover events.
To fulfill your requirements, you have to use "switchAuto" function.
Here is the working demo.
Javascript :
$("#changeInterval").change(function(){
var that = this;
if(this.checked && imageSlider.getAuto()) {
imageSlider.switchAuto(); // pause the animation (auto: false)
setTimeout(function(){
that.checked = false; // uncheck the radio button
imageSlider.switchAuto(); // resume the animation (auto: true)
}, 10000); // 10 seconds
}
});
In the above code, I am binding "change" event on radio button (id: changeInterval).
By default in the option list, auto value has been set to true so when we call "switchAuto" function, it changes the auto value to false which stops animation. And after 10 seconds I am again calling the "switchAuto" function to resume the animation.
In this way you can pause animation for specified time.

Categories