Reputation: 454
So I was trying to wrap my head around this issue, and I asked the question yesterday: Carousel('pause') isn't working on mobile devices
I found the symptom so I'm asking a new question with a new focus.
The question title is not telling everything, because it would be too large: This is only happening on phones, using mobile browsers, On desktop is totally fine.
Basically, if you have a Bootstrap 4 carousel, and you have any element that is inside of the div with the id of the carousel and you want to attach an event on that element (like a click) to pause the carousel, it wont work AT ALL, the slider keeps cycling.
I've tried click, mousedown, mouseup, I've tried setting the selector's click event on body, tried calling a click event on a selector that is outside to pause it, used parents, etc, and it wouldn't work.
Created a button that is right outside the carousel, attached a click event to it and it works. I'm using the latest BS (4.4.1)
This is my code:
Blade file:
<div id='slider'>
<button class='pause-carousel' role='button'>Pause from outside</button>
<div id='sme-directory-gallery' class='carousel slide' data-ride='carousel'>
<button class='pause-carousel-2' role='button'>Pause from inside</button>
<div class='carousel-inner'>
@foreach($directoryInfo->videos as $index => $video)
<div class='item carousel-item {{ $index === 0 ? 'active' : '' }}' data-slide-number='{{ $index }}'>
<div class='video-mask'></div>
<div class='d-flex justify-content-center'>
<div class='embed-responsive embed-responsive-21by9'>
<iframe class='embed-responsive-item player' src='{{ 'https://www.youtube.com/embed/' . substr($video->url, strrpos($video->url, 'v=') + 2) }}' allowfullscreen></iframe>
</div>
</div>
</div>
@endforeach
@foreach($directoryInfo->images as $index => $image)
<div class='item carousel-item {{ ($index + sizeof($directoryInfo->videos)) === 0 ? 'active' : '' }}' data-slide-number='{{ $index + sizeof($directoryInfo->videos) }}'>
<div class='d-flex justify-content-center'>
<img src='{{ asset('storage/' . $image->path) }}' class='img-fluid' alt='imagen'>
</div>
</div>
@endforeach
<a class='carousel-control-prev' href='#sme-directory-gallery' role='button' data-slide='prev'>
<div class='rounded-circle'>
<span class='carousel-control-prev-icon' aria-hidden='true'></span>
<span class='sr-only'>Previous</span>
</div>
</a>
<a class='carousel-control-next' href='#sme-directory-gallery' role='button' data-slide='next'>
<div class='rounded-circle'>
<span class='carousel-control-next-icon' aria-hidden='true'></span>
<span class='sr-only'>Next</span>
</div>
</a>
</div>
<ul class='carousel-indicators list-inline'>
@foreach($directoryInfo->videos as $index => $video)
<li class='list-inline-item my-2 {{ $index === 0 ? 'active' : '' }}'>
<a id='carousel-selector-{{ $index + sizeof($directoryInfo->videos) }}' class='sme-gallery-anchor' data-slide-to='{{ $index }}' data-target='#sme-directory-gallery'>
<img src='{{ 'https://img.youtube.com/vi/' . substr($video->url, strrpos($video->url, 'v=') + 2) . '/mqdefault.jpg' }}' class='img-fluid'>
<div class='text-white sme-gallery-middle-icon'>
<span class='fas fa-play'></span>
</div>
</a>
</li>
@endforeach
@foreach($directoryInfo->images as $index => $image)
<li class='list-inline-item {{ $index + sizeof($directoryInfo->videos) === 0 ? 'active' : '' }}'>
<a id='carousel-selector-{{ $index + sizeof($directoryInfo->videos) }}' data-slide-to='{{ $index + sizeof($directoryInfo->videos) }}' data-target='#sme-directory-gallery'>
<img src='{{ asset('storage/' . $image->path) }}' class='img-fluid'>
</a>
</li>
@endforeach
</ul>
</div>
</div>
Javascript:
$(document).ready(function () {
$('.carousel-indicators').scrollLeft(0);
$('#sme-directory-gallery').carousel();
$('.pause-carousel').on('click', function () {
$('#sme-directory-gallery').carousel('pause'); // it works
});
$('.pause-carousel-2').on('click', function () {
$('#sme-directory-gallery').carousel('pause'); // it wont work
});
$('#sme-directory-gallery .video-mask').mouseup(function () {
var iframe = $(this).closest('.item').find('iframe');
var iframe_source = iframe.attr('src');
if (iframe_source.includes('?rel=0')) {
iframe_source = iframe_source.replace('?rel=0', '');
}
iframe_source = iframe_source + '?autoplay=1';
iframe.attr('src', iframe_source);
$(this).toggle();
$('#sme-directory-gallery').carousel('pause');
});
$('#sme-directory-gallery').on('slide.bs.carousel', function (e) {
$('#sme-directory-gallery').carousel('cycle');
var iframeID = $(this).find('iframe').attr('id');
if (iframeID != undefined) {
callPlayer(iframeID, 'stopVideo');
}
$('.video-mask').show();
$('#sme-directory-gallery').find('iframe').each(function (key, value) {
var url = $(this).attr('src');
if (url.includes('?autoplay')) {
var new_url = url.substring(0, url.indexOf('?'));
$(this).attr('src', new_url);
}
});
setTimeout(() => {
var scrollTo = $('.list-inline-item.active').position().left;
if ($('.list-inline-item.active').index() > 0) {
scrollTo = $('.list-inline-item.active').prev('.list-inline-item').position().left;
}
var finalOrFirst = 0;
if (e.direction === 'right') {
if ($('.list-inline-item.active').is(':last-child')) {
finalOrFirst = 99999;
}
} else {
if ($('.list-inline-item.active').is(':first-child')) {
finalOrFirst = -99999;
}
}
var currentScroll = $('.carousel-indicators').scrollLeft();
var scrollResult = currentScroll + scrollTo + finalOrFirst;
$('.carousel-indicators').animate({scrollLeft: scrollResult}, 500);
}, 10);
});
});
What exactly is happening here, how do I fix it?
Thanks in advance.
Upvotes: 1
Views: 4060
Reputation: 141
I have a problem similar to this one: in some case the code doesn't work in some case works. The only difference I have found is about the presence of the class "pointer-event" in the tag of the carousel element.
To solve this problem I have use a boolean variable with the event "slide.bs.carousel" to avoid carousel to slide when paused.
<section id="slideshow" class="carousel slide">
<div class="carousel-inner" id="images" >
<div class="carousel-item " >
<img src="..." class="d-block w-100" alt='bla bla bla' >
</div>
<div class="carousel-item " >
<img src="..." class="d-block w-100" alt='bla bla bla' >
</div>
<div class="carousel-item " >
<img src="..." class="d-block w-100" alt='bla bla bla' >
</div>
</div>
<a class="carousel-control-pause" href="#slideshow" role="button" >
<span class="pause-icon">
||
</span>
<span class="play-icon d-none">
|>
</span>
</a>
<a class="carousel-control-prev" href="#slideshow" role="button" data-slide="prev" >
<--
</a>
<a class="carousel-control-next" href="#slideshow" role="button" data-slide="next" >
-->
</a>
</section>
$(document).ready(function(){
var carousel = $('#slideshow').carousel({
interval: 5000,
ride: true
});
var carousel_paused = false;
//on init the carousel is paused
$('#slideshow .carousel-control-pause').on('click', function(e){
e.preventDefault();
var hideclass= "d-none";
var pause= $(this).children(".pause-icon");
if( $(pause).is(":hidden"))
{
//play
$(pause).removeClass(hideclass);
$(this).children(".play-icon").addClass(hideclass);
carousel.carousel('cycle');
carousel_paused = false;
}
else
{
//pause
$(pause).addClass(hideclass);
$(this).children(".play-icon").removeClass(hideclass);
carousel.carousel('pause');
carousel_paused = true;
}
});
carousel.on('slide.bs.carousel', function (e) {
console.log("slide pre");
//prevent slide if paused
if(carousel_paused)
e.preventDefault();
});
carousel.on('slid.bs.carousel', function (e) {
console.log("slide done");
});
});
The code is for example and is not tested in mobile.
Upvotes: 0
Reputation: 249
If you use .carousel()
as a varaible it will work. var slider = $('#element').carousel();
And you can use in all events. slider.carousel('pause');
, for starting again: slider.carousel({'pause': false});
When you use multiple element click events:
$('#btn1, #btn2').click(function(){
slider.carousel('pause');
});
In an another event (hover):
$('#yourSlider').hover(function(){
slider.carousel('pause');
}, function(){
slider.carousel({'pause': false});
});
If you don't assign it to a variable, the carousel will be restarted within each event.
I added an examp (it works):
$(function(){
var slider = $('#carouselExampleSlidesOnly').carousel({
interval: 1000
});
$('#pause').click(function(){
slider.carousel('pause');
});
$('#start').click(function(){
slider.carousel({'pause': false});
});
});
.carousel-item{
padding-top: 45px;
text-align: center;
height:150px;
width:100%;
color:#fff;
background-color: #666;
font-size: 2rem;
font-weight: 700;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container p-4">
<button id="pause" class="btn btn-sm btn-warning">Pause</button>
<button id="start" class="ml-2 btn btn-sm btn-primary">Start</button>
</div>
<div id="carouselExampleSlidesOnly" class="carousel slide" data-ride="carousel" style="width: 90%; marign:auto">
<div class="carousel-inner">
<div class="carousel-item active">
Slide 1
</div>
<div class="carousel-item">
Slide 2
</div>
<div class="carousel-item">
Slide 3
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
Upvotes: 1
Reputation: 125
Set the pause to false and that will take care of the issue
$('.carousel').carousel({
pause: "false"
});
you can see an example here: https://jsfiddle.net/KyleMit/XFcSv/
Upvotes: 1
Reputation: 260
Try this to catch the issue:
Put console.log or alert() to check if event is triggered or not.
$('.pause-carousel-2').on('click', function () {
console.log('Button Clicked');
$('#sme-directory-gallery').carousel('pause'); // it wont work
});
Case 1:
If "Button Click" is not printed in console, then you may try:
$('body').on('click','.pause-carousel-2',function(){ ...
Case 2:
If "Button Click" is printed, then there is a workaround for this issue, which you can try.
Use Trigger
$('.pause-carousel-2').on('click', function () {
$('.pause-carousel').trigger("click");
});
and hide the Pause button which is outside
Please share your result, will try to fix your issue.
Upvotes: 1