Search code examples
jqueryfunctionslideshowslideimage-gallery

How to start a jQuery function only, when the previous execution is finished?


I'm trying to build a full width image carousel / gallery for my portfolio by myself. My first idea was to just move the whole image block gallery_wrapper to the left or right with a positive or negative margin-left (Or do you think this is a bad idea?). For both directions there is a button control which executes the jQuery function BUT if I fire the button very fast the function will again be executed while the previous one isn't finished yet which leads to wrong calculations. So I thought I could set up a variable, which I called slide_executed. In normal state the value would be true, but while the function is fired, the value is set to false. With a simple if statement I could check if slide_executed is true and only then fire the next slide.

Well, the problem is: it doesn't work. If I click to fast on the button, the slides will still be offset. What can I do?

...

So here is my HTML (A lot of galleries I saw, were built with unordered lists. Is that actually a better way, than using nested divs?):

 <div id="gallery_wrapper">
 <div class="image" class="first active">
      <div class="image_content">
           <img src="http://placekitten.com/g/1000/1000" alt="Slideshow Image 2" width="100%" style="background-color: green;" />
      </div>
 </div>
 <div class="image">
      <div class="image_content" style="background-color: gray;">
           <img src="http://placekitten.com/g/1200/1000" alt="Slideshow Image 2" width="100%" />
      </div>
 </div>
 <div class="image">
      <div class="image_content">
           <img src="http://placekitten.com/g/1000/900" alt="Slideshow Image 3" width="100%" style="background-color: blue;" />
      </div>
 </div>
 <div class="image last">
      <div class="image_content">
           <img src="http://placekitten.com/g/1000/1100" alt="Slideshow Image 4" width="100%" />
      </div>
 </div>
 </div>
 <div class="overlay">
      <button class="left">Left</button>
      <button class="right">Right</button>
 </div>

And this is the CSS:

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    width: 100%;
    overflow: hidden;
}

#gallery_wrapper {
    margin: 0;
    padding: 0;
    width: 400%; /* 100 x Anzahl der Slides */
    height: 100%;
    overflow: scroll;
    direction: rtl;
    vertical-align: middle;
}

.image {
    margin: 0;
    padding: 0;
    height: 100%;
    width: 25%; /* 100 : Anzahl der Slides */
    float: left;
}

.image_content {
    position: absolute;
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}

.image img {
    margin: 0;
    padding: 0;
    height: 100%;
    width: auto;
    display: block;
    margin-left: auto;
    margin-right: auto;
    margin-top: 0;
    margin-bottom: 0;
}

.overlay {
    bottom: 0px;
    position: fixed;
    background-color: green;
    font-size: 20;
    height: 50px;
    width: 100%;
    text-align: center;
    vertical-align: middle;
}

.overlay button {
    background-color: yellow;
    height: 50px;
    text-align: center;
    vertical-align: middle;
}

Yeah and this one is my jQuery solution:

$(document).ready(function () {

var slide_width = +$('.image_content').outerWidth();
var slide_executed = true;

var slide_right = function () {
    slide_executed = false;
    console.log(slide_executed);
    var left_indent = parseInt($('#gallery_wrapper').css('margin-left')) - slide_width;
    $('#gallery_wrapper').animate({
        'margin-left': left_indent
    }, {
        queue: false,
        duration: 500
    });
    slide_executed = true;
    console.log(slide_executed);
};

var slide_left = function () {
    slide_executed = false;
    console.log(slide_executed);
    var right_indent = parseInt($('#gallery_wrapper').css('margin-left')) + slide_width;
    $('#gallery_wrapper').animate({
        'margin-left': right_indent
    }, {
        queue: false,
        duration: 500
    });
    slide_executed = true;
    console.log(slide_executed);
};

$('.left').click(function () {
    if (slide_executed == true) {
        slide_left();
    };
});

$('.right').click(function () {
    if (slide_executed == true) {
        slide_right();
    };
});

});

Here is a Fiddle of the whole thing…


Solution

  • This should disable controls.

    $('.left').click(function () {
        if (!$('#gallery_wrapper').is(':animated')) {
            slide_left();
        };
    });
    
    $('.right').click(function () {
        if (!$('#gallery_wrapper').is(':animated')) {
            slide_right();
        };
    });
    

    $().animation is non-blocking function, so even animation is not complete slide_executed will be set to true