Prevent event overlap in custom jQuery image carousel
I am working on a custom image carousel, using jQuery and CSS. My aim is to make it really lightweight but with (just) enough features: "bullets", auto-advance, responsiveness.
The slider had a bug (described in detail HERE): when I clicked 2 bullets in rapid succession, the transition would overlap, instead of "standing in line". The fix I found is making all the bullets except the active one non-responsive to clicks, instead of queueing the clicks :
- var $elm = $('.slider'),
- $slidesContainer = $elm.find('.slider-container'),
- slides = $slidesContainer.children('a'),
- slidesCount = slides.length,
- slideHeight = $(slides[0]).find('img').outerHeight(false),
- animationspeed = 1500,
- animationInterval = 7000;
-
- // Set (initial) z-index for each slide
- var setZindex = function() {
- for (var i = 0; i < slidesCount; i++) {
- $(slides[i]).css('z-index', slidesCount - i);
- }
- };
- setZindex();
-
- var displayImageBeforeClick = null;
-
- var setActiveSlide = function() {
- $(slides).removeClass('active');
- $(slides[activeIdx]).addClass('active');
- };
-
- var advanceFunc = function() {
- if ($('.slider-nav li.activeSlide').index() + 1 != $('.slider-nav li').length) {
- $('.slider-nav li.activeSlide').next().find('a').trigger('click');
- } else {
- $('.slider-nav li:first').find('a').trigger('click');
- }
- }
-
- var autoAdvance = setInterval(advanceFunc, animationInterval);
-
- //Set slide height
- $(slides).css('height', slideHeight);
-
- // Append bullets
- if (slidesCount > 1) {
- /* Prepend the slider navigation to the slider
- if there are at least 2 slides */
- $elm.prepend('<ul class="slider-nav"></ul>');
-
- // make a bullet for each slide
- for (var i = 0; i < slidesCount; i++) {
- var bullets = '<li><a href="#">' + i + '</a></li>';
- if (i == 0) {
- // active bullet
- var bullets = '<li class="activeSlide"><a href="#">' + i + '</a></li>';
- // active slide
- $(slides[0]).addClass('active');
- }
- $('.slider-nav').append(bullets);
- }
- };
-
- var animationStart = false;
- var slideUpDown = function() {
- animationStart = true;
- // set top property for all the slides
- $(slides).not(displayImageBeforeClick).css('top', slideHeight);
- // then animate to the next slide
- $(slides[activeIdx]).animate({
- 'top': 0
- }, animationspeed, function() {
- animationStart = false;
- });
-
- $(displayImageBeforeClick).animate({
- 'top': "-100%"
- }, animationspeed, function() {
- animationStart = false;
- });
- };
-
- $('.slider-nav a').on('click', function(event) {
- if (animationStart) {
- return false;
- }
- displayImageBeforeClick = $(".slider-container .active");
- activeIdx = $(this).text();
- if ($(slides[activeIdx]).hasClass("active")) {
- return false;
- }
- $('.slider-nav a').closest('li').removeClass('activeSlide');
- $(this).closest('li').addClass('activeSlide');
- // Reset autoadvance if user clicks bullet
- if (event.originalEvent !== undefined) {
- clearInterval(autoAdvance);
- autoAdvance = setInterval(advanceFunc, animationInterval);
- }
-
- setActiveSlide();
- slideUpDown();
- });
I have posted a jsFuddle with all the code HERE .
Questions: How can I queue the clicks? Are there any better alternatives to queueing the clicks?