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.
Related
I am struggling to achieve what should be a simple task.
Page Loads
User freely scrolls down through different sections.
When a specific DIV reaches the centre of the page I would like to pause/prevent scrolling down until the DIV has been moved horizontally across to the left a fixed number of pixels.
Then the user can be allowed to continue scrolling down the page.
Also, I would like to achieve the opposite effect if the user scrolls up i.e. scroll the div to the right a fixed number of pixels before continuing up.
Below is a sample of my code.
$(window).scroll(function() {
sD = $(this).scrollTop();
// $('.features-2-item').width();
if (sD > (f2Pos.top + 100) && sD < f2Pos.top + 2000 + 100) {
// if scroll distance is greater than the top position of
// the statements when they are centred in the viewport,
// and less than the top position of statements centred
// plus the height of 4 statements, prevent user from
// scrolling, then run function to change statements.
sD = f2Pos.top + 100;
var scroll = $(window).scrollTop();
// console.log(('up or down: ' + xSlide + ' > - ' + statementWidth + ' || ' + scroll + ' < ' + position));
if (xSlide > -statementWidth || scroll < position) {
slideStatements();
}
}
if (sD > f2Pos.top + 2000) {
// if scroll distance is greater than the top positon of
// the statements, centred in the viewport, plus the
// height of 4 statements, the user has scrolled through
// all of the statements and should be allowed to resume
// scrolling. Scrolling should be adjusted to take away
// the distance equal to the height of 4 statements.
sD = sD - 2000 + 100;
}
});
var statementWidth = $('.features-2-item').width();
var xSlide = statementWidth;
var position = $(window).scrollTop();
function slideStatements() {
var st = $(this).scrollTop();
if (st > lST) {
// Going Down
if (cS) {
// disallow scrolling until after statement slides
cS = false;
xSlide = Math.floor(xSlide + 32);
$(window).one('scroll.slideStatements', function() {
$(".features-2-container").css("transform", "translateX(" + xSlide + "px)");
});
// allow scrolling after statement slides
cS = true;
}
} else {
// Going Up
if (cS) {
// disallow scrolling until after statement slides
cS = false;
xSlide = Math.floor(xSlide - 32);
$(window).one('scroll.slideStatements', function() {
// $sS.slick("slickPrev");
$(".features-2-container").css("transform", "translateX(" + xSlide + "px)");
});
// allow scrolling after statement slides
cS = true;
}
}
lST = st - 1;
}
Any suggestion swould be great.
regards
Hi I'm not an expert here but I would like to share my method.
In my opinion the hardest part is how to prevent the scrolling. So we are not going to prevent it, instead we are going to take some advantage of it.
Let's say we have 3 sections like
<section>...</section>
<section class='stuart'>
<div class='kevin'></div>
</section>
<section>...</section>
And style like
.stuart {
height: 600px;
}
.kevin {
position: absolute;
width: 50px;
height: 50px;
background: tomato;
}
So stuart is a our container and kevin is a box inside.
Our goal is simple, when kevin goes up and pass the middle of window we will keep it at that middle (vertical) and move it from left to right (horizontal) until the end of stuart pass.
Code will be like
if (stuart.top < windowHeight / 2 &&
stuart.top + stuart.height - kevin.height > windowHeight / 2) {
let distance = windowHeight / 2 - stuart.top
kevin.classList.add('fixed')
kevin.style.left = distance + 'px'
}
The important part is the distance which always relate to the position of stuart, so you will no need to do anything about opposite effect.
Final example here.
Bad news, you need to calculate the height of container by yourself or a fixed position may not work in your case or other things but I hope this idea will help you in some way. Thanks.
I'm trying to set up an application and I need to animate several items at one time.
function getData() {
for(i=0, i<data.length, i++) {
...
animate(ID, top, left);
}
}
function animate (ID, top, left) {
$("#" + ID).animate({top: top, left: left}, {duration: 1000, queue: false});
}
What this does is, that it gets data from server through AJAX, gets ID, top and left position. I have divs with these IDs and I need to animate them to position given in left and top coordinates. Problem is, that when I call that function all elements jump to given position except the last one, which animates as it should. Where could be an issue?
You can use JQuery multiselection:
$("#element0, #element1").fadeIn()
In your case:
function getData() {
var ids = ""
for(i = 0; i < data.length; i++) {
// retrieve 'id', top and left
ids += "#" + id
if (i < data.length - 1) {
ids += ","
}
}
animate(ids, top, left);
}
function animate (ids, top, left) {
$(ids).animate({top: top, left: left}, {duration: 1000, queue: false});
}
This animate all your element, selected by 'id', simultaneously.
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.
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);
}
});
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()});
});