Reputation: 841
I've spent the past few days now working on an image slider for a products page, and I've managed to build what I feel is a satisfactory enough slider, however the final touches I want to add to it are rather than static movements from one image to the next, you see a physical sliding animation, the only issue I am having is that it is allowing multiple clicks, meaning the values are thrown completely out and it just breaks. I was wondering how to check when a function is running so that it can't run it again until it is finished, or i was thinking perhaps i could use .finish() so that the user isn't forced to wait for the animation to finish before each click, so that if they want to quick scroll it will rush the previous animation to the final value.
Here is a jsfiddle link of the (current) working slider.
If you change .css() to .animate() on lines 12 and 24, you will see the issue I am having when you click multiple times on the arrows.
HTML
<div id="imageSlider">
<div id="imagesContainer">
<div class="left imagePane" id="selectedImage">
<div class="sliderImageAlign">
<p style="height: 100px; width: 75px; line-height: 100px; text-align: center;">1</p>
</div>
</div>
<div class="left imagePane">
<div class="sliderImageAlign">
<p style="height: 100px; width: 75px; line-height: 100px; text-align: center;">2</p>
</div>
</div>
<div class="left imagePane">
<div class="sliderImageAlign">
<p style="height: 100px; width: 75px; line-height: 100px; text-align: center;">3</p>
</div>
</div>
<div class="left imagePane">
<div class="sliderImageAlign">
<p style="height: 100px; width: 75px; line-height: 100px; text-align: center;">4</p>
</div>
</div>
<div class="left imagePane">
<div class="sliderImageAlign">
<p style="height: 100px; width: 75px; line-height: 100px; text-align: center;">5</p>
</div>
</div>
</div>
<div id="imagesUp">
<div id="imagesArrowUp"></div>
</div>
<div id="imagesDown">
<div id="imagesArrowDown"></div>
</div>
</div>
jQuery
$(document).ready(function () {
var imageHeight = $("#selectedImage").height(),
containerHeight = $("#imagesContainer").height(),
imageSliderHeight = $("#imageSlider").height() - ($("#imagesDown")[0].offsetHeight + $("#imagesUp")[0].offsetHeight);
$("#imagesDown").on('click', function () {
if (containerHeight > imageSliderHeight) {
var containerPos = $("#imagesContainer").position().top,
containerNewPos = containerPos - imageHeight;
if (imageSliderHeight < (containerHeight + containerPos)) {
$("#imagesContainer").css({
top: containerNewPos + 'px'
}, 800);
}
}
});
$("#imagesUp").on('click', function () {
var containerPos = $("#imagesContainer").position().top,
containerNewPos = containerPos + imageHeight;
if (containerNewPos < imageHeight) {
$("#imagesContainer").css({
top: containerNewPos + 'px'
}, 800);
}
});
});
CSS
* {
color: RGB(0, 0, 0);
font: 14px Arial;
margin: 0;
padding: 0;
text-decoration: none;
}
.left {
float: left;
}
.right {
float: right;
}
#imageSlider {
border: 1px solid RGB(0, 0, 0);
box-shadow: 0px 0px 10px RGB(200, 200, 200);
float: left;
height: 450px;
margin-right: 20px;
overflow: hidden;
position: relative;
width: 87px;
}
#imagesContainer {
position: absolute;
top: 35px;
width: 100%;
}
#imagesUp,
#imagesDown {
background: RGB(20, 100, 150);
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
height: 35px;
position: absolute;
width: 100%;
}
#imagesUp {
border-bottom: 1px solid RGB(0, 0, 0);
top: 0;
}
#imagesDown {
border-top: 1px solid RGB(0, 0, 0);
bottom: 0;
}
#imagesArrowUp,
#imagesArrowDown {
border-left: 20px solid transparent;
border-right: 20px solid transparent;
margin: 0 auto;
margin-top: 10px;
height: 0;
width: 0;
}
#imagesArrowUp {
border-bottom: 15px solid RGB(200, 230, 240);
}
#imagesArrowDown {
border-top: 15px solid RGB(200, 230, 240);
}
#selectedImage {
background: RGBA(20, 100, 150, 0.4);
}
.sliderImageAlign {
border: 1px solid RGB(0, 0, 0);
height: 100px;
margin: 5px;
width: 75px;
}
Upvotes: 0
Views: 210
Reputation: 123428
Just check if you're element is still moving while you're clicking with the jQuery :animated
pseudoclass, e.g. in this way
$("#imagesUp").on('click', function () {
var ic = $("#imagesContainer");
...
if (ic.is(':not(:animated)') && containerNewPos < imageHeight) {
ic.animate({
top: containerNewPos + 'px'
}, 800);
}
});
doing so the animation will be possible only if a previous animation has completed.
You may also check that condition as first statement inside your handler and move all the necessary logic inside that statement, depending on your convenience.
As a sidenote I would suggest to refactor your code, caching a reference to the moving element and use a single event handler, both for imageUp and imageDown element and thus you may calculate the new top properties (and condition to run the animation) only looking at the id
attribute of the element clicked.
Upvotes: 1