Text changing with animation jquery - javascript

I have some code that works, but sometimes it just "jumps" to the other text without respecting the interval.
The code basically changes a header's text on an interval.
var text = ["text1", "text2", "text3","text4","text5"];
var index = 0;
$("#description").fadeOut("slow");
setInterval(function(){
$("#description").html(text[index]).fadeIn("slow");
$("#description").delay(400).fadeOut("slow");
index++;
if (index == 5) {
index = 0;
};
}, 1800);
If you guys can help me make this work,or even improve it I would be very thankful :)
Fiddle: http://jsfiddle.net/erbfqqxb/

I think the problem may be caused when your interval catches up to the time taken for your delays and fades. Try running each animation in the callback so that it is run as a linear process to keep the text from "jumping":
var text = ["text1", "text2", "text3","text4","text5"];
var index = 0;
var description = $("#description");
description.fadeOut("slow", changeText);
function changeText(){
// run the initial animation
description.html(text[index]).fadeIn("slow", function() {
// run the second animation after the first one has finished - can remove the delay if you want to
// the delay here is how long you want the text to be visible for before it starts to fade out
description.delay(400).fadeOut("slow", function() {
index++;
//measure against array length instead of hard coded length
if (index == text.length) {
index = 0;
};
//set the delay before restarting animation sequence (only restart once the sequence has finished)
setTimeout(changeText, 400);
});
});
}
Updated fiddle

Just try as below:
setInterval(function(){
//first stop what you are doing and then fadeIn again
$("#description").stop().html(text[index]).fadeIn("slow",function(){
//set a callback to do all these things once fadeIn is completed
index++;
$("#description").delay(400).fadeOut("slow");
if (index == 5) {
index = 0;
};
});
},1800);
I think the problem was with delay. setInterval time and delay time were conflicting. So the above approach seems better to me.
DEMO

I think this happen due to the line
$("#description").fadeOut("slow");
comment that line it will work fine.

Here is the working code and its more dynamic by using
index == text.length
$(function() {
var text = ["text1", "text2", "text3","text4","text5"];
var index = 0;
$("#description").fadeOut();
setInterval(function(){
$("#description").html(text[index]).fadeIn("slow");
$("#description").delay(400).fadeOut("slow");
index++;
if (index == text.length) {
index = 0;
};
},1800);
});

<pre>Use call back function and remove delay</pre>
JSFIDDLE: http://jsfiddle.net/rajen_ranjith/erbfqqxb/3/.

Related

Multiple instances of Setinterval

I have a little problem with my code.
I have it setup so that by default, a rotating fadeIn fadeOut slider is auto playing, and when a user clicks on a li, it will jump to that 'slide' and pause the slider for x amount of time.
The problem i have is that if the user clicks on multiple li's very fast, then it will run color1() multiple times with will start colorInterval multiple times. This gives a undesired effect.
So what i need help with, is figuring out how to reset my code each time a li is clicked, so whenever ColorClick is clicked, i want to make sure that there are no other instances of colorInterval before i start a new one.
Thanks in advance!
=================================
edit:
I now have another problem, i believe that i fixed the clearInterval problem, but now if you look at var reset, you'll see that it runs color1() each time a li is clicked, which runs multiple intervals, so i need to delete the previous instance of color1() each time it is called, to make sure that it doesnt repeat any code inside multiple times. So when a li is clicked delete any instances of color1()
or
i need that instead of running color1 in var reset, i will go straight to colorInterval instead of running color1() for each li clicked,
so run colorInterval after x amount of time in var reset.
function color1() {
var pass = 0;
var counter = 2;
var animationSpeed = 500;
var $colorContent = '.color-container-1 .color-content-container'
var $li = '.color-container-1 .main-color-container li'
$($li).on('click', function() {
colorClick($(this));
});
function colorClick($this) {
var $getClass = $this.attr("class").split(' ');
var $whichNumber = $getClass[0].substr(-1);
var $Parent = '.color-container-1 ';
pass = 1;
$($colorContent).fadeOut(0);
$($colorContent + '-' + $whichNumber).fadeIn(animationSpeed);
var reset = setTimeout(function() {
clearTimeout(reset);
pass = 0;
color1();
}, 10000);
}
var colorInterval = setInterval(function() {
if (pass > 0) {
clearInterval(colorInterval);
return; //stop here so that it doesn't continue to execute below code
}
$($colorContent).fadeOut(0);
$(($colorContent + '-' + counter)).fadeIn(animationSpeed);
++counter
if (counter === $($colorContent).length + 1) {
counter = 1;
}
}, 7000);
}
You could just clear the interval inside of the click event.
var colorInterval;
$($li).on('click', function() {
clearInterval(colorInterval);
colorClick($(this));
});
//Your other code
colorInterval = setInterval(function() {
//Rest of your code
});
One thing play with is jQuery animations have a pseudo class selector :animated when animation is in progress
if(!$('.your-slide-class:animated').length){
// do next animation
}

How do I make elements trigger to appear one after another, with a small interval?

I have a series of four elements. The first of which (#pro1) will appear on scrolling to a particular point on the page (this currently works), and the following three will trigger to appear one after another, with a small changeable interval in between each.
Any help would be greatly appreciated! A huge thank you in advance!
Here is the code for the first element, just needing to make the others appear after this one appears (#pro2, #pro3, #pro4, etc)
<script>
$(window).one("scroll", function() {
$('#pro1').each(function () {
var topOfWindow = $(window).scrollTop(),
bottomOfWindow = topOfWindow + $(window).height();
var imagePos = $(this).offset().top;
if(imagePos < bottomOfWindow-200 && imagePos >= topOfWindow-500){
$(this).addClass('bigEntrance2');
}else{
$(this).removeClass('bigEntrance2');
}
});
});
</script>
The key is using setInterval to call repeatedly the function that will create (or show if they are already created) the next elements.
It is important to not forget to clear the interval when the job is done.
Without the html and the css is difficult to realise exactly what you want to achieve, but from the next example you shouldn't have problems to update yours.
var interval = null;
var elementId = 1;
var numElements = 4;
var delay = 1000; //ms
$(document).ready(function()
{
//your first "pro1" element show up
var element = "<div>Im the pro" + elementId + " element!</div>";
$('body').append(element);
//in that moment we set the interval
interval = setInterval(show_next_element, delay);
});
function show_next_element()
{
//increment the counter elementId
elementId++;
//create the next element
var element = "<div>Im the pro" + elementId + " element!</div>";
//add it to the DOM
$('body').append(element);
//when our last element is created we clear the interval
if(elementId >= numElements)
clearInterval(interval);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hope it helps!

setTimeout not working, other methods of queuing in a for loop?

Code below (the divs are shaded in my real example, I want to sequentially decrease their opacity to 0 so each disappears, in order.
I tried to doing this without using setTimeout, but all of the divs disappeared simultaneously - its good to know that the part of the code that changes the opacity works, but I cant seem to get them to work sequentially.
When I try to use setTimeout (which I presume I am implementing incorrectly),nothing happens!
Any help would be really appreciated with this, I'm fairly new to JavaScript and haven't touched it in a while and tutorials haven't been able to help me.
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<div id="div4"></div>
<script type="text/javascript">
// the divs that we want to cycle through are named here.
var divs = ["#div1", "#div2", "#div3", "#div4"];
var divsLength = divs.length;
for (var i = 0; i < divsLength; i++) {
setTimeout(function(){
$(divs[i]).fadeTo(1000, 0, function() {
});
},1500);
};
</script>
</body>
Here's a way you should be able to do this without setTimeout:
function doFade(items, index) {
$(items[index]).fadeTo(1000, 0, function() {
doFade(items, index + 1);
});
}
doFade(divs, 0);
If you're targetting browsers that support ES5 (most modern versions do), then you can further simplify doFade:
function doFade(items, index) {
$(items[index]).fadeTo(1000, 0, doFade.bind(this, items, index + 1));
}
working jsfiddle
You can use a recursive function to do that kind of thing, something like that :
function seqFade($el){
$el.first().fadeOut(500, function(){ //Take the first element and fade it out
seqFade($el.slice(1)); //Recall the function when complete with the same set of element minus the first one.
})
}
seqFade($('div')); //Call the function
http://jsfiddle.net/L2fvdfy2/
In your code, it could look like that :
function seqFade($el){
$el.first().fadeOut(500, function(){
seqFade($el.slice(1));
})
}
seqFade($('#div1, #div2, #div3, #div4'));
It's because when the timeout finally fires the variable "i" only has the last index value. Also the loop will start all the timeouts at almost the same time.
There are other ways to accomplish it but this might work with minimal changes to your code.
Try this:
<script type="text/javascript">
var divs = ["#div1", "#div2", "#div3", "#div4"];
var divsLength = divs.length;
for (var i = 0; i < divsLength; i++) {
setTimeout((function(index) {
return function(){
$(divs[index]).fadeTo(1000, 0, function() { });
}
)(i)),1500 + (i * 1500));
};
</script>
</body>
This will create an instance of the function with it's own copy of the index when it was called. Also increasing the timeout of each timeout will have them execute sequentially.
try this:
// the divs that we want to cycle through are named here.
var divs = ["#div1", "#div2", "#div3", "#div4"];
(function fade(i) {
$(divs[i]).fadeTo(1000, 0, function() {
setTimeout(function() {fade(++i);}, 500);
});
})(0);
for (var i = 1; i <= divsLength; i++) {
setTimeout(function(){
$(divs[i]).fadeTo(1000, 0, function() {
});
},1000*i);
lets try this

a setInterval within a for loop in Javascript

My code below needs to put in a setInterval within a for loop. I basically need to put in a 10 second pause between the next iteration of the for loop. This is for a very basic script which shows banners in a div for 10 seconds before moving onto the next one. It existing setInterval is code I got off another website as I ran out of options. Any help? And if you don't mind explaining the logic to me so that I know for the future :)
$("document").ready(function() {
// bannerChange
function bannerChange(banner,div,milliseconds) {
var length = banner.length;
for(i=0;i<length;i++) {
(function(i) {
setInterval(function() {
var url = banners[i].url;
var img = banners[i].image;
$("#"+div).html("<a href='"+url+"' target='_Blank'><img src='www/images/banners/"+img+"' /></a>");
},milliseconds)
})(i);
}
}
function showBanner(bannerName, bannerDiv, milliseconds) {
var url = "www/scripts/ajax/getBanners.php";
$.post(url, {name: bannerName}, function(data) {
if(data.response == true) {
bannerChange(data.banners,bannerDiv,milliseconds);
}
});
}
// Run banners
showBanner("Test Banner","test",10000);
});
Here's an updated version based on the comment:
// Start by getting the banners:
var banners = [];
var currentBanner;
function getBannersFromServer(...) {
// TODO: make ajax call to server for banners
// push the banners into a queue for later
for (var i in bannerFromServer) {
banners.push(bannersFromServer[i]);
}
}
// Then run through them:
function showNextBanner() {
// advance to next banner
currentBanner++
// go back to the beginning after the last banner is displayed
if(currentBanner >= banners.length) currentBanner = 0;
// pull a banner out of the queue
var banner = banners[currentBanner];
// TODO: Show the banner in the div
// do it again in 10 seconds
showNextBanner();
}
// start it all
getBannersFromServer();
getNextBanner();
Try using:
.delay()
Here is a great example of this function in use!
Try this
var i=0;//Global Variable
function bannerChange(banner, div, milliseconds) {
var length = banner.length;
setInterval(function() {
var url = banners[i].url;
var img = banners[i].image;
$("#"+div).html("<a href='"+url+"' target='_Blank'><img src='www/images/banners/"+img+"' /></a>");
i++;
if(i >= length) i=0;//To reiterate from first
},milliseconds);
}
Hope this solves your problem.

Help with JQuery Callback

As per my previous question, I have a working animation which fades in and out each element within the div slideshow. The problem is that I want this animation to continue from the beginning once it has reached the last element. I figured that was easy and that I'd just place an infinite loop inside my JQuery function, but for some reason if I insert an infinite loop, no animation displays and the page hangs. I also cannot find anything in the documentation about how properly place a callback. How can I get this code to restart from the beginning of the animation once it finishes iterating over each object and why is an infinite loop not the right way to go about this?
<div id="slideshow">
<p>Text1</p>
<p>Text2</p>
<p>Test3</p>
<p>Text4</p>
</div>
<script>
$(document).ready(function() {
var delay = 0;
$('#slideshow p').each(
function (index, item)
{
$(this).delay(delay).fadeIn('slow').delay(800).fadeOut('slow');
delay += 2200;
}
);
});
</script>
You could do something like this:
$(function() {
var d = 2200;
function loopMe() {
var c = $('#slideshow p').each(function (i) {
$(this).delay(d*i).fadeIn('slow').delay(800).fadeOut('slow');
}).length;
setTimeout(loopMe, c * d);
}
loopMe();
});
You can give it a try here.
Instead of keeping up with a delay, you can just multiple it by the current index in the loop...since the first index is 0, the first one won't be delayed at all, then 2200ms times the amount of elements later, do the loop again. In the above code d is the delay, so it's easily adjustable, and c is the count of elements.
This solution is in my opinion more elegant, also more natural, it is easier to control, to correctly edit values of delays etc. I hope you'll like it.
$(document).ready(function () {
var elementsList = $('#slideshow p');
function animationFactory(i) {
var element = $(elementsList[i % elementsList.length]);
return function () {
element.delay(200).fadeIn('slow').delay(800).fadeOut('slow', animationFactory(i + 1));
};
}
animationFactory(0)();
});

Categories

Resources