How to add if statements to loop the images around? - javascript

This code makes the 'li' move like I want to but when I get to the last 'li' and click next it keeps moving and the 'li' moves out of the users view. I want to know how to loop it so the first 'li' shows up again.
<script type="text/javascript">
$(document).ready(function() {
$('#right').click(function() {
$('.carousel-inner li').animate({
right: '+=292px'
}, 500);
});
$('#left').click(function() {
$('.carousel-inner li').animate({
right: '-=292px'
}, 500);
});
});
</script>
Here is a Fiddle to see an example

This should solve your problem:
$(document).ready(function () {
var inner = $('.carousel-inner'),
slides = inner.find('li'),
width = slides.eq(0).outerWidth(true),
max = (width * slides.length) - width;
$('#right, #left').on('click', function () {
var currRight = parseInt(inner.css('right'), 10), move;
if (this.id === 'right') {
move = currRight === max ? 0 : currRight+width;
} else {
move = currRight === 0 ? max : currRight-width;
}
inner.animate({ right: move }, 500);
});
});
The top four lines cache elements and set up a few basic variables such as the max right value that can used and the width of the slides.
I've then combined the click events to avoid repetition. The first line of the click event defines currRight as $('.carousel-inner')'s current CSS right value as well as move which is used later on.
if (this.id === 'right'){ /* #right */ }else{ /* #left */ } checks whether the id of the clicked element is right or left. The code inside the if statement just checks to see whether the slider is at zero (the beginning) or max (the end) and then sets the move variable to the correct value.
Here it is working: http://jsfiddle.net/mFxcq/10/
Update: To make the slides move on a timer add this after the click event is attached:
function setTimer(){
clearTimeout(window.slideTimer);
window.slideTimer = setTimeout(function(){ $('#right').trigger('click'); }, 5000);
};
setTimer();
Then add setTimer(); right after inner.animate({ right: move }, 500); and everything will work as expected.
Here it is working: http://jsfiddle.net/mFxcq/14/

Add a totalItems variable which will represent the total number of items in the carousel, and a currentItem variable which will represent the number of the current item being displayed (i.e. a number from 1 to totalItems). Then, simply check if it's the last item, and if it is, move the position back to the first one. Check out the revised fiddle, where it works in both directions. Here's example JavaScript, with everything written out for clarity.
var totalItems = $('.carousel-inner li').length;
var currentItem = 1;
$('#right').click(function () {
if (currentItem === totalItems) {
// We've reached the end -- go to the beginning again
$('.carousel-inner li').animate({
right: '-=' + 292 * (totalItems-1) + 'px'
}, 500);
currentItem = 1;
} else {
$('.carousel-inner li').animate({
right: '+=292px'
}, 500);
currentItem += 1;
}
});
$('#left').click(function () {
if (currentItem === 1) {
// We're at the beginning -- loop back to the end
$('.carousel-inner li').animate({
right: '+=' + 292 * (totalItems-1) + 'px'
}, 500);
currentItem = totalItems;
} else {
$('.carousel-inner li').animate({
right: '-=292px'
}, 500);
currentItem -= 1;
}
});

Take a look at this fiddle for a working approach. For the right click.
Basically, each time you click "Right", you'll test to compare the distance traveled by the items and compare that to the maximum distance allowed based on the total number of items.
var slideWidth = 292;
$('#right').click(function() {
if(parseInt($('.carousel-inner li').css('right')) == slideWidth*($('.carousel-inner li').length-1)) {
$('.carousel-inner li').animate({
right: '0px'
, 500);
}
else {
$('.carousel-inner li').animate({
right: '+=' + slideWidth + 'px'
}, 500);
}
});

Related

Slider Ignoring If Conditional When Clicked Multiple Times

I have jQuery slider that slides items through a container div every 5 seconds by animating the left property by 1400px. Once the left property reaches -2800px an if conditional starts resetting the left property while also removing items from the front of the row and appending them to the back of the list, so that the sliding loop continues infinitely. This slider also has left and right buttons that will allow the user to cycle through the images if they would like to.
The problem I have encountered is that if you click the sliders multiple times in quick succession then the left property goes outside of the -2800px boundary set in the if conditional. I am assuming this is because the multiple click events are all fired off before the left property reaches the -2800px. How can I stop this from happening? Is there a function that will stop multiple functions from firing before the first one is complete? Here is a jsFiddle (I changed the widths for displays sake) :
http://jsfiddle.net/25tt5vmp/
My jQuery:
$(document).ready(function () {
var myTimer = setInterval(slide, 5000);
function slide() {
var left = $('#sliderList').css('left');
left = left.substring(0, left.length - 2);
if (left <= -2800) {
$('#sliderList').css('left', '-1400px');
var slide = $('#sliderList li:first');
$('#sliderList').children('li:first').remove();
$('#sliderList').append(slide);
$('#sliderList').animate({ left: "-=1400px" }, "slow", "swing");
}
else {
$('#sliderList').animate({ left: "-=1400" }, "slow", "swing");
}
}
$('#sliderLeft').click(function () {
var left = $('#sliderList').css('left');
left = left.substring(0, left.length - 2);
if (left <= -2800) {
$('#sliderList').css('left', '-1400px');
var slide = $('#sliderList li:first');
$('#sliderList').children('li:first').remove();
$('#sliderList').append(slide);
$('#sliderList').animate({ left: "-=1400px" }, "slow", "swing");
clearInterval(myTimer);
myTimer = setInterval(slide, 5000);
}
else {
$('#sliderList').animate({ left: "-=1400" }, "slow", "swing");
clearInterval(myTimer);
myTimer = setInterval(slide, 5000);
}
});
$('#sliderRight').click(function () {
var left = $('#sliderList').css('left');
left = left.substring(0, left.length - 2);
if (left >= 0) {
$('#sliderList').css('left', '-1400px');
var slide = $('#sliderList li:last');
$('#sliderList').children('li:last').remove();
$('#sliderList').prepend(slide);
$('#sliderList').animate({ left: "+=1400px" }, "slow", "swing");
clearInterval(myTimer);
myTimer = setInterval(slide, 5000);
}
else {
$('#sliderList').animate({ left: "+=1400" }, "slow", "swing");
clearInterval(myTimer);
myTimer = setInterval(slide, 5000);
}
});
});
There is one easy solution. Use a blocking-variable. Generate a variable:
var blockedSlider = false;
Then, set it to true when starting the animation.
On every click, you check, if the blockedSlider is true or false, and only fire the animation if false.
And after your animation is done, set the blockedSlider to false again. That's it.

image loop in carousel jquery

I have a carousel that animates to the right depending on the li width.
After reaching the end it keeps animating until the last image is the only one you see. With a blank space to the right. How would I set it to loop so there is no blank space and the first images appears again?
My move right jquery code.
$('#right').click(function () {
if (currentItem === totalItems) {
$inner.animate({
right: '-=' + width * (totalItems-1) + 'px'
}, speed);
currentItem = 1;
} else {
$inner.animate({
right: '+=' + width
}, speed);
currentItem += 1;
}
});
So after getting to the end it rewinds to the first image.
EDIT: Here is a FIDDLE if you guys want to see.

javascript - Need onclick to go full distance before click works again

I have this javascript function I use that when clicked goes a certain distance. This is used within a scroller going left to right that uses about 7 divs. My question is how do I get the click to go the full distance first before the click can be used again? The issue is if the user rapidly clicks on the arrow button it resets the distance and sometimes can end up in the middle of an image instead of right at the seam. What code am I missing to accomplish this?
$(function () {
$("#right, #left").click(function () {
var dir = this.id == "right" ? '+=' : '-=';
$(".outerwrapper").stop().animate({ scrollLeft: dir + '251' }, 1000);
});
});
I would've thought that the easiest way would be to have a boolean flag indicating whether or not the animation is taking place:
$(function () {
var animating = false,
outerwrap = $(".outerwrapper");
$("#right, #left").click(function () {
if (animating) {return;}
var dir = (this.id === "right") ? '+=' : '-=';
animating = true;
outerwrap.animate({
scrollLeft: dir + '251'
}, 1000, function () {
animating = false;
});
});
});
works for me: http://jsfiddle.net/BYossarian/vDtwy/4/
Use .off() to unbind the click as soon as it occurs, then re-bind it once the animation completes.
function go(elem){
$(elem).off('click'); console.log(elem);
var dir = elem.id == "right" ? '+=' : '-=';
$(".outerwrapper").stop().animate({ left: dir + '251' }, 3000, function(){
$("#right, #left").click(go);
});
}
$("#right, #left").click(function () {
go(this);
});
jsFiddle example
You can see in this simplified example that the click event is unbound immediately after clicking, and then rebound once the animation completes.
Use an automatic then call like this
var isMoving = false;
$(function () {
$("#right, #left").click(function () {
if (isMoving) return;
isMoving = true;
var dir = this.id == "right" ? '+=' : '-=';
$(".outerwrapper").stop().animate({ scrollLeft: dir + '251' }, 1000).then(function(){isMoving = false}());
});
});
I think that you miss the fact that when you make stop() you actually position the slider at some specific point. I.e. if your scroller is 1000px and you click left twice very quickly you will probably get
scrollLeft: 0 - 251
scrollLeft: -2 - 251
So, I think that you should use an index and not exactly these += and -= calculations. For example:
$(function () {
var numberOfDivs = 7;
var divWidth = 251;
var currentIndex = 0;
$("#right, #left").click(function () {
currentIndex = this.id == "right" ? currentIndex+1 : currentIndex-1;
currentIndex = currentIndex < 0 ? 0 : currentIndex;
currentIndex = currentIndex > numberOfDivs ? numberOfDivs : currentIndex;
$(".outerwrapper").stop().animate({ scrollLeft: (currentIndex * divWidth) + "px" }, 1000);
});
});
A big benefit of this approach is that you are not disabling the clicking. You may click as many times as you want and you can do that quickly. The script will still works.
This will work perfectly fine:
var userDisplaysPageCounter = 1;
$('#inventory_userdisplays_forward_button').bind('click.rightarrowiventory', function(event) {
_goForwardInInventory();
});
$('#inventory_userdisplays_back_button').bind('click.leftarrowiventory', function(event) {
_goBackInInventory();
});
function _goForwardInInventory()
{
//$('#inventory_userdisplays_forward_button').unbind('click.rightarrowiventory');
var totalPages = $('#userfooterdisplays_list_pagination_container div').length;
totalPages = Math.ceil(totalPages/4);
// alert(totalPages);
if(userDisplaysPageCounter < totalPages)
{
userDisplaysPageCounter++;
$( "#userfooterdisplays_list_pagination_container" ).animate({
left: "-=600",
}, 500, function() {
});
}
}
function _goBackInInventory()
{
//$('#inventory_userdisplays_back_button').unbind('click.leftarrowiventory');
if(userDisplaysPageCounter > 1)
{
userDisplaysPageCounter--;
$( "#userfooterdisplays_list_pagination_container" ).animate({
left: "+=600",
}, 500, function() {
});
}
}
I second BYossarian's answer.
Here is a variation on his demo, which "skips" the animation when the user clicks several times quickly on the buttons :
$(function () {
var targetScroll = 0,
outerwrap = $(".outerwrapper");
$("#right, #left").click(function () {
// stop the animation,
outerwrap.stop();
// hard set scrollLeft to its target position
outerwrap.scrollLeft(targetScroll*251);
if (this.id === "right"){
if (targetScroll < 6) targetScroll += 1;
dir = '+=251';
} else {
if (targetScroll > 0) targetScroll -=1;
dir = '-=251';
}
outerwrap.animate({ scrollLeft: dir }, 1000);
});
});
fiddle

jquery slide back and forth or slide round

Please i need help sliding images using jquery back and forth, or just to go round. right now it slides upto the last element and rushes back to the first div and begins again, not beautiful at all,i know i should call back a function to do that but i keep getting mistakes. thanks in advance, this is my jquery code below
$(document).ready(function() {
var currentPosition = 0;
var slideWidth = 190;
var slides = $('.slider_move');
var numberOfSlides = slides.length;
var slideShowInterval;
var speed = 5000;
slideShowInterval = setInterval(changePosition, speed);
slides.wrapAll('<div id="slidesHolder"></div>')
slides.css({ 'float' : 'left' });
$('#slidesHolder').css('width', slideWidth * numberOfSlides);
function changePosition() {
if(currentPosition == numberOfSlides - 1) {
currentPosition = 0;
} else {
currentPosition++;
}
moveSlide();
}
function moveSlide() {
$('#slidesHolder')
.animate({'marginLeft' : slideWidth*(-currentPosition)});
}
});​
Instead of:
if(currentPosition == numberOfSlides - 1) {
currentPosition = 0;
} else {
currentPosition++;
}
You need to move the first slide to the very end (and adjust the position of the container at the same time):
if (currentPosition > 0) {
$('#slidesHolder').css('marginLeft',0)
.children().first().appendTo('#slidesHolder');
} else {
currentPosition += 1;
}
http://jsfiddle.net/mblase75/qatry/
Or, to optimize the whole thing a little more, you can eliminate the currentPosition variable and the moveSlide sub-function, and just use a callback in the .animate method:
function changePosition() {
$('#slidesHolder').animate({
'marginLeft': 0-slideWidth
}, function() {
$('#slidesHolder').css('marginLeft', 0)
.children().first().appendTo('#slidesHolder');
});
}
http://jsfiddle.net/mblase75/8vaCg/

jQuery append (or appendTo) with Animation

I have a UL-LI e.g.
<ul>
<li id="1">item-1</li>
<li id="2">item-2</li>
<li id="3">item-3</li>
<li id="4">item-4</li>
</ul>
I would like to move one of the items to another position in the list. e.g. item-2 to AFTER item-4.
Normally I can do this by deleting the item and then appending it after another.
But I would like to do this to happen visually with animation. As in, item-2 descends to after item-4.
How can I achieve this?
IDs should not start with numbers...
$('#two').slideUp(500, function () {
$('#four').after(this);
$(this).slideDown(500);
});
Here is a demo: http://jsfiddle.net/jasper/8JFBA/
Or if you always want to add the element to the end:
$('#two').slideUp(500, function () {
$('ul').append(this);
$(this).slideDown(500);
});
Here is a demo: http://jsfiddle.net/jasper/8JFBA/1/
Update
Ok, so if you want the element to slide to it's new location here ya go:
//absolutely position the element and give it a top property so it doesn't go to the top of the container
$('#two').css({ position : 'absolute', top : $('#two').position().top });
//now get the offset to the bottom of the list by getting the top offset and height for the last list-item
var lastOffset = ($(this).children().last().position().top + $(this).children().last().height());
//now animate the element to the new position
$('#two').animate({ top : lastOffset }, 1000, function () {
//when the animation is done, re-add the element to the new position in the list and reset it's position and top values
$(this).appendTo('ul').css({ position : 'relative', top : 0 });
});
And a demo: http://jsfiddle.net/jasper/8JFBA/3/
Update
You can animate not only the element being moved to the end of the list but you can animate the rest of the list items as they move up:
var $LIs = $('ul').children(),
liHeight = 20;
$LIs.on('click', function () {
var index = ($(this).index()),
$LIsAfter = $LIs.filter(':gt(' + index + ')');
console.log(index);
$(this).css({ position : 'absolute', top : $(this).position().top });
$.each($LIsAfter, function (i) {
$(this).css({ position : 'absolute', top : ((i + index + 1) * liHeight) });
});
$(this).stop(true, true).animate({ top : (($LIs.length - 1) * liHeight)}, 1000, function () {
$(this).appendTo('ul').css({ position : 'relative', top : 0 });
});
$.each($LIsAfter, function (i) {
$(this).stop(true, true).animate({ top : ((index + i) * liHeight) }, 1000, function () {
$(this).css({ position : 'relative', top : 0 });
});
});
});
Here is a demo: http://jsfiddle.net/jasper/8JFBA/8/
This isn't quite complete, there is still a bug or two, but it should help get anyone started on the idea.
I tried to implement a smoother transition when you descend and below is my version..
You need to try out the demo to understand how it works.. Select value from the drop down and hit Descend to see the animation.
DEMO
Edit: Updated top position of $from before addClass('active') to start from the exact position and not top: 0px. Thanks to Jasper for finding this issue.
var $from = $('#from');
var $to = $('#to');
$('button').click (function () {
var from = $from.val();
var to = $to.val();
var $li = $('ul li');
var $fromEl = $('#' + from);
var $toEl = $('#' + to);
//only descending
if (from == to || $li.index($fromEl) > $li.index($toEl)) return;
var destX = $toEl.position().top;
$toEl.after('<li id="tmpLi2"></li>');
$('#tmpLi2').animate({height: $fromEl.outerHeight()}, 1000);
//add a blank li for smooth animation
$fromEl
.after('<li id="tmpLi1"> </li>')
.css ('top', $fromEl.position().top)
.addClass ('active' )
.animate({
top: (destX)
},
1000,
function() {
$toEl.after(this);
$('#tmpLi2').remove();
$(this).removeClass('active');
});
$('#tmpLi1').slideUp(function() { $(this).remove()});
});

Categories

Resources