The Bootstrap carousel is a strange beast. I've tried tweaking $next to prevent infinite looping but end up either breaking it or preventing the slides from going backwards when reaching the end.
I would like the carousel to only slide within the list and not infinitely loop.
Any help would be appreciated.
$next = $next.length ? $next : this.$element.find('.item')[fallback]()
if ($next.hasClass('active')) return
if ($.support.transition && this.$element.hasClass('slide')) {
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$next.addClass(type)
$next[0].offsetWidth // force reflow
$active.addClass(direction)
$next.addClass(direction)
this.$element.one($.support.transition.end, function() {
$next.removeClass([type, direction].join(' ')).addClass('active')
$active.removeClass(['active', direction].join(' '))
that.sliding = false
setTimeout(function() {
that.$element.trigger('slid')
}, 0)
})
} else {
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$active.removeClass('active')
$next.addClass('active')
this.sliding = false
this.$element.trigger('slid')
}
Update: This is unrelated to "autoplay" I'm specifically referring to manually pressing the left and right buttons.
For the carousel to not infinitely loop (using Bootstrap 3.0.0), and stop at the last slide unless the "next" arrow is clicked, the following is the best way to do it:
$('.carousel').carousel({
interval: 5000,
wrap: false
});
Setting the wrap option to false tells the carousel to stop cycling through the slides automatically. I hope this answers your question correctly.
You could just add some code to the page to hide the appropriate carousel controls after a slid event:
$('#myCarousel').on('slid', '', function() {
var $this = $(this);
$this.children('.carousel-control').show();
if($('.carousel-inner .item:first').hasClass('active')) {
$this.children('.left.carousel-control').hide();
} else if($('.carousel-inner .item:last').hasClass('active')) {
$this.children('.right.carousel-control').hide();
}
});
This example assumes the markup used on the Twitter Bootstrap example carousel.
Make sure to hide the left one when you open the page.
Add attribute data-wrap="false" in Div
The easiest way to do this is as follows:
//intro slider
$('#carousel_fade_intro').carousel({
interval: 2500,
pause: "false"
})
//Stop intro slider on last item
var cnt = $('#carousel_fade_intro .item').length;
$('#carousel_fade_intro').on('slid', '', function() {
cnt--;
if (cnt == 1) {
$('#carousel_fade_intro').carousel('pause');
}
});
Not sure if this is only relevent to the newest version of Bootstrap but setting data-wrap="false" on the outermost carousel container will prevent it from proceeding past the final slide.
source: http://getbootstrap.com/javascript/#carousel-options
For people looking for a solution for Bootstrap 3 working for multiple carousels on same page try this:
$(function() {
// init carousel
$('.carousel').carousel({
pause: true, // init without autoplay (optional)
interval: false, // do not autoplay after sliding (optional)
wrap:false // do not loop
});
// init carousels with hidden left control:
$('.carousel').children('.left.carousel-control').hide();
});
// execute function after sliding:
$('.carousel').on('slid.bs.carousel', function () {
// This variable contains all kinds of data and methods related to the carousel
var carouselData = $(this).data('bs.carousel');
// get current index of active element
var currentIndex = carouselData.getItemIndex(carouselData.$element.find('.item.active'));
// hide carousel controls at begin and end of slides
$(this).children('.carousel-control').show();
if(currentIndex == 0){
$(this).children('.left.carousel-control').fadeOut();
}else if(currentIndex+1 == carouselData.$items.length){
$(this).children('.right.carousel-control').fadeOut();
}
});
Please let me now if this is not working in your case.
if you are using bootstrap 3 use this
$('.carousel').carousel({
wrap: false
});
The codes posted here have two problems: doesn't work if you have more than one carousel on the same page and doesn't work if you click on the indicator dots. Also, in Bootstrap 3 the event has changed name.
The below code is an updated version of this code. And here you can find a more detailed explanation
checkitem = function() {
var $this;
$this = $("#slideshow");
if ($("#slideshow .carousel-inner .item:first").hasClass("active")) {
$this.children(".left").hide();
$this.children(".right").show();
} else if ($("#slideshow .carousel-inner .item:last").hasClass("active")) {
$this.children(".right").hide();
$this.children(".left").show();
} else {
$this.children(".carousel-control").show();
}
};
checkitem();
$("#slideshow").on("slid.bs.carousel", "", checkitem);
Related
I have a product page and for every product is a modal, and for every modal is a owl slider.
When I a product for the first time it shows up well but when I close that product and open another product the owl slider is broken.
I tried (or I feel like I tried) every solution I found on internet but still I can't figure it out.
Here is my jQuery:
var owlCarousel = $('.owl-carousel');
$('.modal').on('shown.bs.modal', function (event) {
owlCarousel.owlCarousel({
loop: true,
items: 1,
margin: 100
});
});
$('.modal').on('hidden.bs.modal', function (event) {
$('.owl-carousel').trigger('destroy.owl.carousel');
});
I hope I explained my problem well!
Note: When I open a second product this error shows up every second I wait
TypeError: null is not an object (evaluating 'this.e._checkVisibile')
On line 620 in owl.carousel.js change this:
Owl.prototype.onThrottledResize = function() {
window.clearTimeout(this.resizeTimer);
this.resizeTimer = window.setTimeout(this.e._onResize, this.settings.responsiveRefreshRate);
};
to this:
Owl.prototype.onThrottledResize = function() {
if(this.e !=null) {
window.clearTimeout(this.resizeTimer);
this.resizeTimer = window.setTimeout(this.e._onResize, this.settings.responsiveRefreshRate);
}
};
worked for me :)
Try checking for the visible owl carousel element and call owlCarousel and destroy events on it.
var owlCarousel;
$('.modal').on('shown.bs.modal', function (event) {
owlCarousel = $('.owl-carousel:visible');
owlCarousel.owlCarousel({
loop: true,
items: 1,
margin: 100
});
});
$('.modal').on('hidden.bs.modal', function (event) {
owlCarousel.trigger('destroy.owl.carousel');
});
I got this wonderful pieve of code to auto update my thumbnails on click and on bs.slide function. It works properly when auto updating via the timer interval, clicking the next arrow, or clicking on the respective thumbnail in the carousel.
$('#myCarousel').carousel({
interval: 4000
});
var selectorIdx = 1;
var numItems = 12;
// handles the carousel thumbnails
$('.carousel-selector').click(function () {
selectorIdx = $(this).closest('li').index();
$('#myCarousel').carousel(selectorIdx)
});
$('#myCarousel').on('slide.bs.carousel', function () {
$('#myCarousel')
.find('.carousel-selector')
.removeClass('selected')
.eq(selectorIdx).addClass('selected')
.end()
.find('.item').removeClass('selected')
.eq(selectorIdx).addClass('active');
if (selectorIdx < (numItems - 1)) {
selectorIdx++;
}
else {
selectorIdx = 0;
}
});
However the carousel thumbs do not auto update when the prev arrow is clicked, how can this code be updated to reflect that action?
Rough Fiddle, you can see when you hit the prev arrow the thumbs still update going forward instead of backward.
http://jsfiddle.net/gward90/xr8qzxmg/12/
Thank You
Here is how I would change your code to select the thumbnail. http://jsfiddle.net/xr8qzxmg/15/
$('#myCarousel').on('slide.bs.carousel', function (e) {
selectorIdx = $(e.relatedTarget).index();
$(this)
.find('.carousel-selector').removeClass('selected')
.eq(selectorIdx).addClass('selected')
.end()
.find('.item').removeClass('selected')
.eq(selectorIdx).addClass('active');
});
I've taken over a project that was built by someone else. The site features a custom slideshow on the home page. I've made some changes to the look/feel of the slideshow per client requests, but the last thing it needs is autoplay.
Below is the script for the slideshow. I know about setInterval but I'm not sure where to put it, or if the code needs to be adjusted a bit before dropping that in.
$(document).ready(function() {
// A little script for preloading all of the images
// It"s not necessary, but generally a good idea
$(images).each(function(index, value){
// Ski first image since it is already loaded
if( index != 0 ) {
$("<img/>")[0].src = this;
}
});
// Feature Slider Navagitaion
$('.feature .ei-slider-nav li a').click( function(e) {
e.preventDefault();
var thisLink = $(this);
var navIndex = thisLink.parent('li').index();
thisLink.parents('ul').children('li').removeClass('active');
thisLink.parent('li').addClass('active');
// Is this item already active?
if( !$('.feature .ei-slider-title .ei-slider-title-item:eq('+navIndex+')').hasClass('active')) {
// Fade in/out feature image
$('.feature .ei-slider-large img').animate({opacity: 0}, 500, function() {
// Support for non-opacity browsers
$(this).css('visibility', 'hidden');
// Load new feature image
$(this).attr('src', images[navIndex]);
$(this).attr('alt', imagesAlt[navIndex]);
$(this).css('visibility', 'visible');
$('.feature .ei-slider-large img').animate({opacity: 1}, 500);
});
// Fade in/out feature text
$('.feature .ei-slider-title .ei-slider-title-item.active').fadeOut(500, function() {
$(this).parent().children().removeClass('active');
$('.feature .ei-slider-title .ei-slider-title-item:eq('+navIndex+')').addClass('active').fadeIn();
});
// Fade in/out feature credit
$('.content .ei-slider-credit span.active').fadeOut(500, function() {
$(this).parent().children().removeClass('active');
$('.content .ei-slider-credit span:eq('+navIndex+')').addClass('active').fadeIn();
});
}
});
// Feature Slider Learn More
$('.feature .ei-slider-title-item-learn').click( function(e) {
e.preventDefault();
thisPrev = $(this).prev();
if( thisPrev.css('display') == 'none') {
thisPrev.slideDown();
thisPrev.css('visibility', 'visible');
thisPrev.animate({'opacity': 1}, 500, function() {
});
$(this).html('Hide');
} else {
thisPrev.animate({'opacity': 0}, 500, function() {
thisPrev.slideUp();
thisPrev.css('visibility', 'hidden');
});
$(this).html('Hide');
$(this).html('Learn More');
}
});
});
Thanks!
This would probably be a little bit easier if there were a way to keep track of the current state of the slideshow outside the context of clicking on a slide's navigation link. The first thing I would add, right above $('.feature .ei-slider-nav li a').click( function(e) {... would be:
var eiSlider = {
currentSlideIndex: 0,
nextSlide: null, // we will define this later
autoPlay: null // we will define this later too
};
Then, inside of the function I mentioned above, as the first order of business inside of the check for whether the slide is already active, I'd add this:
// Set the currentSlide index on the global eiSlider tracking object
eiSlider.currentSlide = navIndex;
Next, you'll want to make a function to handle advancing the slideshow automatically:
eiSlider.nextSlide = function() {
var currentSlideIndex = eiSlider.currentSlideIndex,
nextSlideIndex = currentSlideIndex + 1,
totalSlides = $('.ei-slider-large img').length;
// If we are already at the end of the images, loop back to the beginning
if ( nextSlideIndex < totalSlides ) {
nextSlideIndex = 0;
}
// Trigger a click to move forward to the next slide
$('.feature .ei-slider-nav li:eq(' + nextSlideIndex + ') a').trigger('click');
};
I've also moved the work of setting the "active" class on a given slide's nav link to happen inside of the logic around making sure the slide you clicked on wasn't already active, to make sure it doesn't get set incorrectly.
Finally, you can use setInterval (at the bottom of all of the above code) to handle the autoplay portion.
// Auto-advance the slides every 5 seconds. Adjust the value as necessary
eiSlider.autoPlay = window.setInterval(function(){
eiSlider.nextSlide();
}, 5000);
Your final, updated code would look something like this:
$(document).ready(function() {
// A little script for preloading all of the images
// It"s not necessary, but generally a good idea
$(images).each(function(index, value){
// Ski first image since it is already loaded
if( index !== 0 ) {
$("<img/>")[0].src = this;
}
});
// Object for basic state tracking and namespacing of slideshow functions
var eiSlider = {
currentSlideIndex: 0,
nextSlide: null, // we will define this later
autoPlay: null // we will define this later too
};
// Feature Slider Navagitaion
$('.feature .ei-slider-nav li a').click( function(e) {
e.preventDefault();
var thisLink = $(this),
navIndex = thisLink.parent('li').index();
// Is this item already active?
if( !$('.feature .ei-slider-title .ei-slider-title-item:eq('+navIndex+')').hasClass('active')) {
thisLink.closest('li').siblings().removeClass('active');
thisLink.closest('li').addClass('active');
// Set the currentSlide index on the global eiSlider tracking object
eiSlider.currentSlideIndex = navIndex;
// Fade in/out feature image
$('.feature .ei-slider-large img').animate({opacity: 0}, 500, function() {
// Support for non-opacity browsers
$(this).css('visibility', 'hidden');
// Load new feature image
$(this).attr('src', images[navIndex]);
$(this).attr('alt', imagesAlt[navIndex]);
$(this).css('visibility', 'visible');
$('.feature .ei-slider-large img').animate({opacity: 1}, 500);
});
// Fade in/out feature text
$('.feature .ei-slider-title .ei-slider-title-item.active').fadeOut(500, function() {
$(this).parent().children().removeClass('active');
$('.feature .ei-slider-title .ei-slider-title-item:eq('+navIndex+')').addClass('active').fadeIn();
});
// Fade in/out feature credit
$('.content .ei-slider-credit span.active').fadeOut(500, function() {
$(this).parent().children().removeClass('active');
$('.content .ei-slider-credit span:eq('+navIndex+')').addClass('active').fadeIn();
});
}
});
// Feature Slider Learn More
$('.feature .ei-slider-title-item-learn').click( function(e) {
e.preventDefault();
thisPrev = $(this).prev();
if ( thisPrev.css('display') === 'none') {
thisPrev.slideDown();
thisPrev.css('visibility', 'visible');
thisPrev.animate({'opacity': 1}, 500, function() {});
$(this).html('Hide');
} else {
thisPrev.animate({'opacity': 0}, 500, function() {
thisPrev.slideUp();
thisPrev.css('visibility', 'hidden');
});
$(this).html('Hide');
$(this).html('Learn More');
}
});
// Function to handle slide advancement
eiSlider.nextSlide = function() {
var currentSlideIndex = eiSlider.currentSlideIndex,
nextSlideIndex = currentSlideIndex + 1,
totalSlides = $('.ei-slider-large img').length;
// If we are already at the end of the images, loop back to the beginning
if ( currentSlideIndex < (totalSlides - 1) ) {
nextSlideIndex = 0;
}
// Trigger a click to move forward to the next slide
$('.feature .ei-slider-nav li:eq(' + nextSlideIndex + ') a').trigger('click');
};
// Auto-advance the slides every 5 seconds. Adjust the value as necessary
eiSlider.autoPlay = window.setInterval(function(){
eiSlider.nextSlide();
}, 5000);
});
Bear in mind this answer makes a few assumptions, the main one being that the eiSldier namespace is available; if it's not, just use a different namespace than the one I provided, OR add these three new items to the existing namespace so it doesn't get overwritten. The only change in that case would not be defining eiSlider as an object with three properties, but instead defining simply eiSlider.currentSlide = 0, and then proceeding to define the other two functions the way they already are defined later on in the example.
If the eiSlider namespace already exists, it's entirely possible that currentSlide or some equivalent property exists on it already, so you could take advantage of that if it does, rather than making a duplicate (or worse, overriding it in a way that could cause errors in the rest of its functionality).
One thing I should note that the code above doesn't currently do is stop/clear the autoplay out when you manually click on a slide's navigation link. That's a pretty important usability issue that will need to get cleaned up. You can accomplish this by using clearInterval(eiSlider.autoPlay), but to make that really work correctly, you'd need to separate out the code that handles slide advancement from the actual click event.
Check out this slightly modified JS Bin that shows the auto-advance working as intended, plus the changes I mentioned above with clearInterval:
http://jsbin.com/gumaqefere/1/edit?html,js,console,output
I am struggling to find a solution to repeat action when user did already one time. For example, when user comes on site there is carousel which can be swiped, slided, and eventually opened in order to see full gallery. I have managed to do that but when the user made this action and closes modal box, he is not able to repeat the same action. Anyone has idea how to solve it?
Here is js
$(document).ready(function () {
// - jQuery
// Swipe feature
$('#myCarousel').swiperight(function () {
$('#myCarousel').carousel('prev');
});
$('#myCarousel').swipeleft(function () {
$('#myCarousel').carousel('next');
});
// Swipe feature for modal
$('#modal-carousel').swiperight(function () {
$('#modal-carousel').carousel('prev');
console.log('swipe_right');
});
$('#modal-carousel').swipeleft(function () {
$('#modal-carousel').carousel('next');
console.log('swipe_left');
});
// Additional toolbar with "close" button appears
$(window).on('shown.bs.modal', function () {
$('modal').modal('show');
$('#toolbar').css('display', 'block'); //.css('position','fixed')
$('.carousel-inner').css('overflow', 'visible');
// Remove entirely in final version
$('.item').css('background', 'none')
console.log('fires toolbar');
});
$(window).on('hidden.bs.modal', function () {
$('modal').modal('show');
$('#toolbar').css('display', 'none'); //.css('position','absolute')
$('.carousel-inner').css('overflow', 'hidden');
// Remove entirely in final version
$('.item').css('background', '#60b1ff')
console.log('closes toolbar when modal is closed');
});
// Closes modal on toolbar
$('.trigger').click(function () {
$('.modal').modal('hide');
});
/* Modal Carousel from version 3. adjusted to version 2.3 */
/* activate the carousel */
$("#modal-carousel").carousel({
interval : false,
});
/* when clicking a image */
$(".thumbnail").click(function () {
var content = $(".carousel-inner");
content.empty();
var id = this.id;
var repo = $('#img-repo .item');
var repoCopy = repo.filter('#' + id).clone();
var active = repoCopy.first();
var next = repoCopy.last();
active.addClass('active');
content.append(repoCopy);
// show the modal
$('#modal-gallery').modal('show');
});
// Carousel pause - prevents automatic slideshow
$('.carousel').carousel({
pause : true,
interval : false
});
// Close window
$('.modal-backdrop').modal({
show : false
});
}); //end of script
Problem is at the content.empty(); which after executed action stays empty. Any ideas how to solve this?
Fiddle
Fiddle 2 with working carousel. Just imagine that you are able to open one of those images in modal.
I'm creating a feature content slider using jQuery and I have hit a few snags trying to get rid of the last few bugs. It is inspired by http://kleientertainment.com/ so check it out and you'll see what im going for. Any suggestions on achieving this effect even with totally new code would be helpful!
The idea is a simple div swap, but with custom animations for each slide that fire when it is loaded. It also MUST fade to black in between each transition, whether autoplay or clicked.
lets get to the code and bugs:
$(document).ready(function () {
//START SLIDES HIDDEN
$('.slide').css({
'position': 'absolute',
'display': 'none'
});
//RUN FIRST SLIDE
runSlideShow(1);
animation1_swap();
//AUTOPLAY FUNCTION
function runSlideShow(slideNumber) {
$('#slide' + slideNumber).fadeIn(1000).delay(10000).fadeOut(1000, function () {
if (slideNumber == 4) {
animation1_swap();
runSlideShow(1);
}
if (slideNumber == 3) {
animation4_swap();
runSlideShow(4);
}
if (slideNumber == 2) {
animation3_swap();
runSlideShow(3);
}
if (slideNumber == 1) {
animation2_swap();
runSlideShow(2);
}
});
//NAVIGATION BUTTONS
$('#bullet1').click(function () {
$('.slide:visible').stop(true, true).fadeOut(1000, function () {
animation1_swap();
runSlideShow(1);
});
});
$('#bullet2').click(function () {
$('.slide:visible').stop(true, true).fadeOut(1000, function () {
animation2_swap();
runSlideShow(2);
});
});
$('#bullet3').click(function () {
$('.slide:visible').stop(true, true).fadeOut(1000, function () {
animation3_swap();
runSlideShow(3);
});
});
$('#bullet4').click(function () {
$('.slide:visible').stop(true, true).fadeOut(1000, function () {
animation4_swap();
runSlideShow(4);
});
});
}
});
CSS info: .slide sets the dimensions, and #slideX are the individual background images for each. #bulletX are the nav buttons.
Also, the animationX_swap() are the animations specific to that slide. They live in another file and would have made this post way too long.
The bugs:
Right now, the autoplay function is great, you can watch it all day and not see a hiccup. The trouble comes when the nav buttons are used, particularly #bullet1. If i click #bullet1, then go to 2, then back to 1, the autoplay seems to be sped up as the slide fades out before it is supposed to. I am a total beginner but I made it this far, can anyone help me clean this up and essentially reimagine http://kleientertainment.com/ 's slider?
Just discovered jQuery cycle plugin http://malsup.com/jquery/cycle/ from another post.
I remade my slider with that and it preforms exactly as needed. Good stuff!