jQuery Animate and Loops - javascript

I made some simple animation for a website with jQuery inside Joomla!, all seems fine but I have a very strange issue during the loop. Even cells are all fixed dims. inside the loop I. You could check it here http://db.tt/uuD00TKc the issue only happens with Firefox.
The JS code is:
jQuery(document).ready(function () {
function loop() {
jQuery("#txt1").animate({
backgroundColor: "#0089BC"
}, 3000, function() {
loop();
});
jQuery("#txt1").animate({
backgroundColor: "#FFF"
}, 3000);
jQuery("#txt2").animate({
backgroundColor: "#0089BC"
}, 9000, function() {
loop();
});
jQuery("#txt2").animate({
backgroundColor: "#FFF"
}, 9000);
jQuery("#txt3").animate({
backgroundColor: "#0089BC"
}, 6000, function() {
loop();
});
jQuery("#txt3").animate({
backgroundColor: "#FFF"
}, 6000);
}
loop();
});
jQuery(document).ready(function () {
jQuery("#img1").hide().fadeIn(3000);
setInterval(function () {
jQuery("#img1").fadeOut(3000).fadeIn(3000);
}, 5000);
jQuery("#img2").hide().fadeIn(9000);
setInterval(function () {
jQuery("#img2").fadeOut(9000).fadeIn(9000);
}, 5000);
jQuery("#img3").hide().fadeIn(6000);
setInterval(function () {
jQuery("#img3").fadeOut(6000).fadeIn(6000);
}, 5000);
});
HTML Code
<div id="home-mosaico">
<div class="row">
<span class="cell-img" id="img1"><img src="http://www.quatrotd.co.uk/images/home/substation-02.jpg" alt="Substation" title="Substation" /></span>
<span class="cell" id="txt1">Engineering<br />and Construction</span>
<span class="cell-img" id="img2"><img src="http://www.quatrotd.co.uk/images/home/substation-01.jpg" alt="Substation" title="Substation" /></span>
</div>
<div class="row">
<span class="cell" id="txt2">Transmission Lines</span>
<span class="cell-img" id="img3"><img src="http://www.quatrotd.co.uk/images/home/transmision_lines-01.jpg" alt="Transmision Lines" title="Transmision Lines" /></span>
<span class="cell" id="txt3">Substations</span>
</div>
</div>
CSS code
/*** Home mosaico ***/
#home-mosaico {
display: table;
width: 940px;
height: 500px;
}
#home-mosaico .row {
display: table-row;
height: 250px;
}
#home-mosaico .cell-img {
display: table-cell;
width: 313px;
background-color: #0089BC;
vertical-align:middle;
text-align:center;
font-size:20px;
line-height: 24px;
font-weight:normal;
color:#ffffff;
}
#home-mosaico .cell {
display: table-cell;
width: 313px;
background-color: #FFF;
vertical-align:middle;
text-align:center;
font-size:20px;
line-height: 24px;
font-weight:normal;
color:#ffffff;
}

Your loop function looks like it will run into some problems. As soon as the loop function starts, it will keep recursively calling itself instantly putting a large strain on the browser as there isn't even a seconds break between calls.
On top of that, as soon as any of the animations are finished, they will also additionally call the loop function again compounding the first issue. While the animations may stack correctly (one after the other on the elements you told it to animate), there is a huge amount of recursion occurring in that loop function.
An alternative for the loop function but still getting the same effect (animation stacking) might be something like:
jQuery(document).ready(function () {
var txt1Animate = function()
{
jQuery("#txt1").animate({
backgroundColor: "#0089BC"
}, 3000, function(){
jQuery(this).animate({
backgroundColor: "#FFF"
}, 3000, txt1Animate);
});
}
var txt2Animate = function()
{
jQuery("#txt2").animate({
backgroundColor: "#0089BC"
}, 9000, function(){
jQuery(this).animate({
backgroundColor: "#FFF"
}, 9000, txt2Animate);
});
}
var txt3Animate = function()
{
jQuery("#txt3").animate({
backgroundColor: "#0089BC"
}, 6000, function(){
jQuery(this).animate({
backgroundColor: "#FFF"
}, 6000, txt3Animate);
});
}
txt1Animate();
txt2Animate();
txt3Animate();
});
This would now correctly wait for the first animation to finish on the element, then do the second and only once the second is complete will it start again. This stops the animation queue from spiraling out of control with 100s to 1000s of animations being queued a second.
Addressing your second part of the question, you are calling fadeOut and then straight away calling fadeIn. While this should queue that animation, that goes for 12 seconds and then you have it already being called again looped by setInterval. This would also create issues in the long term with the queue growing every 10 or so seconds without any chance of finishing.
jQuery(document).ready(function () {
jQuery("#img1").hide().fadeIn(3000);
var img1Fade = function()
{
jQuery("#img1").fadeOut(3000).fadeIn(3000,function()
{
setTimeout(img1Fade,5000);
});
}
jQuery("#img2").hide().fadeIn(9000);
var img2Fade = function()
{
jQuery("#img2").fadeOut(9000).fadeIn(9000,function()
{
setTimeout(img2Fade,5000);
});
}
jQuery("#img3").hide().fadeIn(6000);
var img3Fade = function()
{
jQuery("#img3").fadeOut(6000).fadeIn(6000,function()
{
setTimeout(img3Fade,5000);
});
}
img1Fade();
img2Fade();
img3Fade();
});
Similar to the other code I provided, this loops on itself in a way that won't have a huge queue of animations at once. It nicely waits for the fade in to finish before running setTimeout to loop the function again.
EDIT
Picked up one bug in the code I supplied originally, I was using $ for jQuery however in your code on the site you linked, I required to do jQuery instead.

Mmmh to me it looks like you might have an unclosed DIV or some other unclosed tag somewhere.
Every modern browser tries to solve this common mistake but FF does it in an odd way.
Let us know.

Related

How to increment the progress in javascript progress bar?

I am trying to add a simple javascript progress bar to my website, I found a few scripts, but I always encounter the same problem - I am able to intialize the loader and set it to increment to a given value, but cannot do it in steps. Here is a simple example - https://jsfiddle.net/kimmobrunfeldt/k5v2d0rr/
At the end there is:
bar.animate(1.0);
How can i have it animated in steps? Lets say first to 50% then (after 2 secs) to 75% and then 100%. I've tried
bar.animate(0.5);
bar.animate(0.75);
bar.animate(1);
as well as:
setTimeout(function(){bar.animate(0.5)}, 2000);
setTimeout(function(){bar.animate(0.75)}, 2000);
setTimeout(function(){bar.animate(1)}, 2000);
but it always chooses the last (highest) value, instead of being animated in steps. Any advice appreicated.
bar.animate(0.5);
bar.animate(0.75);
bar.animate(1);
The above code runs simultaneously, and the last one overrides the others.
setTimeout(function(){bar.animate(0.5); console.log("animate")}, 2000);
console.log('timeout 1 called');
setTimeout(function(){bar.animate(0.75); console.log("animate")}, 2000);
console.log('timeout 2 called');
setTimeout(function(){bar.animate(1); console.log("animate")}, 2000);
console.log('timeout 3 called');
Soon as the first timeout is set, it doesn't wait for the delay before setting the next. Check the logs on the console to see what happens.
The problem is that those scripts run simultaneously. Do something like this (or something better):
bar.animate(0.5); // Number from 0.0 to 1.0
setTimeout(function () {
bar.animate(0.75);
}, 2000);
setTimeout(function () {
bar.animate(1.0);
}, 4000);
If you wanted to just animate the bar in sequences for the sake of it, you can do keyframes with CSS too.
The problem is that you're, essentially, queuing up all of your steps to happen simultaneously. Instead, you want to pass a callback to the animate function so when it finishes, you can tell it to move to the next step.
// progressbar.js#1.0.0 version is used
// Docs: http://progressbarjs.readthedocs.org/en/1.0.0/
var bar = new ProgressBar.Line(container, {
strokeWidth: 4,
easing: 'easeInOut',
duration: 1400,
color: '#FFEA82',
trailColor: '#eee',
trailWidth: 1,
svgStyle: {
width: '100%',
height: '100%'
},
text: {
style: {
// Text color.
// Default: same as stroke color (options.color)
color: '#999',
position: 'absolute',
right: '0',
top: '30px',
padding: 0,
margin: 0,
transform: null
},
autoStyleContainer: false
},
from: {
color: '#FFEA82'
},
to: {
color: '#ED6A5A'
},
step: (state, bar) => {
bar.setText(Math.round(bar.value() * 100) + ' %');
}
});
// Keep track of the current value
var value = 0;
setTimeout(function increment() {
value += 0.1;
bar.animate(value, function() {
// Animation has completed, queue up another step
if (value < 1) {
setTimeout(increment, 500);
}
});
}, 1000);
#container {
margin: 20px;
width: 400px;
height: 8px;
position: relative;
}
<script src="https://rawgit.com/kimmobrunfeldt/progressbar.js/1.0.0/dist/progressbar.js"></script>
<div id="container"></div>

SetInterval times not running correctly

I've inherited a bug to look at consisting of two images that "flip" and use set interval to time when this happens.
From what I believe the initial change should happen after 4 seconds, then for each image change every 12 seconds (obviously this isn't important at the minute).
At the moment the first image changes at 4 seconds and the second one at around 8.
I'm also open to any improvements that can be made to this code as well.
//SPINNING LOGO
if ($("#flipLogo").length) {
function spinLogo() {
$('#flipLogo').addClass("active");
$('#flipLogo2').addClass("active");
// console.log("yup yup");
setTimeout(function () {
$('#flipLogo').removeClass("active");
$('#flipLogo2').removeClass("active");
}, 4000);
clearInterval();
}
setInterval(function () {
spinLogo();
clearInterval();
}, 12000);
}
I believe you are looking for $.toggleClass to switch between the active states.
Additionally, as Hacketo said you are calling clearInterval wrong - it should be called with the return value of setInterval if you want to stop the interval (I don't think you want to do this?)
Try this:
//SPINNING LOGO
function spinLogo() {
// Flip the active classes on or off
$('#flipLogo').toggleClass("active");
$('#flipLogo2').toggleClass("active");
}
if ($("#flipLogo").length) {
// after 4 seconds
setTimeout(function() {
// flip the logo
spinLogo();
// Set a timer to flip it again every 12 seconds
setInterval(spinLogo, 12000);
}, 4000);
}
Here it is in action:
//SPINNING LOGO
function spinLogo() {
// Flip the active classes on or off
$('#flipLogo').toggleClass("active");
$('#flipLogo2').toggleClass("active");
}
if ($("#flipLogo").length) {
// after 4 seconds
setTimeout(function() {
// flip the logo
spinLogo();
// Set a timer to flip it again every 12 seconds
setInterval(spinLogo, 12000);
}, 4000);
}
.flippable {
width: 100px;
height: 100px;
border: 1px solid black;
text-align: center;
display: none;
color: white;
}
.flippable.active {
display: block;
}
#flipLogo {
background: blue;
}
#flipLogo2 {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="flipLogo" class="flippable active">Logo 1</div>
<div id="flipLogo2" class="flippable">Logo 2</div>
(ps it is bad form to define functions inside if statements, as hoisting will move them them to a place you might not expect)

jQuery: change background color after animation completes

I'm having trouble with my jQuery right now. What I want is that the background color is changed after the animation completes. I haven't been able to figure out how to make it work. I don't understand there are no console errors.
http://jsfiddle.net/4pmzf/
jQuery:
$("#slider").toggle(function () {
$(this).animate({
"height":"100px"
}, 1000).addClass('red');
}, function () {
$(this).animate({
"height":"20px"
}, 1000).removeClass('red');
});
CSS
#slider {
width: 100%;
background: black;
height: 20px;
cursor: pointer;
}
.red {
background: red;
}
This is a specificity issue. The initial background declaration has a higher specificity because it was declared with an id. You could solve this by overwriting it with a more specific selector:
UPDATED EXAMPLE HERE
#slider.red {
background:red;
}
The initial selector, #slider, has a specificity of 100.
The new selector, #slider.red, has a slightly higher specificity of 110.
Aside from this, the background really isn't being changed after the animation completes. I'd suggest adding a callback/complete function to the animation(s)..
CALLBACK EXAMPLE HERE
$("#slider").toggle(function () {
$(this).animate({
"height":"100px"
}, 1000, function(){
$(this).css('background','red');
});
}, function () {
$(this).animate({
"height":"20px"
}, 1000, function(){
$(this).css('background','');
});
});
Also.. rather than changing classes, it's probably better to just modify the CSS.

How to set the time to each content should be shown after the site have already loaded?

I'm looking for some plugin (js/ajax) or tutorial which let me set the time to each content should be shown after the site have already loaded.
For example:
I want my website with a loader and after that display the menu navigation (e.g. slide right to left effect), after the logotype, after the main image of home, etc.).
This website is a good reference for what I want: http://www.smog-bicyclettes.com/
Do you know something like this?
Try using set timeout
setTimeout(function(){
/* Your Function */
},2000);
I'm delegating deciding which animation to run to a single function doAnimation which maintains a counter of the last animation that ran.
We don't need to use setTimeout here because we're relying only on the jQuery animation callbacks to ensure one animation happens when another finishes.
Working example here (updated): http://jsfiddle.net/av8ZA/7/
HTML
<div id="element1"></div>
<div id="element2"></div>
<div id="element3"></div>
<div id="element4"></div>
<div id="element5"></div>
<div id="element6"></div>
CSS
div {
height:100px;
width 200px;
display:none;
}
#element1 {
background: red;
}
#element2 {
background: green;
}
#element3 {
background: blue;
}
#element4 {
background: magenta;
}
#element5 {
background: black;
}
#element6 {
background: yellow;
}
jQuery/Javascript
(function ($) {
var currentCall = 0,
animations = [{
element: "#element1",
type: "slide",
options: {},
time: 1000
}, {
element: "#element2",
type: "blind",
options: {}
}, {
element: "#element3",
}, {
element: "#element4",
type: "size",
time: 300
}, {
element: "#element5",
}, {
element: "#element6",
type: "bounce"
}],
defaults = {
type: "fade",
time: 300,
options: {}
};
function doAnimation() {
if (animations[currentCall] != undefined) {
var anim = animations[currentCall];
$(anim.element).show(
anim.type || defaults.type,
anim.options || defaults.options,
anim.time || defaults.time,
doAnimation);
currentCall++;
}
}
$(document).ready(doAnimation);
})(jQuery);
Of course this is no good if you want concurrent animations, but you didn't state that in the question.
EDIT: I've cleaned up by javascript and defined an array of animations now where you can set options for each animation individually. For all animation types see the jQuery UI documentation for show. I've also defined some default that will be used if you don't specify one of the options for an animation.

jQuery slideUp to show the element and not hide

jQuery's slideUp effect hides the element by sliding it up, while slideDown shows the element. I want to show my div using slideUp. can anyone guide me ? thanks
$("div").click(function () {
$(this).hide("slide", { direction: "down" }, 1000);
});
http://docs.jquery.com/UI/Effects/Slide
It's a little more complex than just saying slideUpShow() or something, but you can still do it. This is a pretty simple example, so you might find some edge-cases that need adressing.
$("#show-animate-up").on("click", function () {
var div = $("div:not(:visible)");
var height = div.css({
display: "block"
}).height();
div.css({
overflow: "hidden",
marginTop: height,
height: 0
}).animate({
marginTop: 0,
height: height
}, 500, function () {
$(this).css({
display: "",
overflow: "",
height: "",
marginTop: ""
});
});
});
Here's a fiddle showing the slideUp/slideDown methods, the same effects using animate, and a modified version using animate that goes in reverse: http://jsfiddle.net/sd7zsyhe/1/
Since animate is a built-in jQuery function, you don't need to include jQuery UI.
To get the opposite of slideUp and slideDown. Add these two functions to jQuery.
$.fn.riseUp = function() { $(this).show("slide", { direction: "down" }, 1000); }
$.fn.riseDown = function() { $(this).hide("slide", { direction: "down" }, 1000); }
I found a tricky way...
you can set div with css style bottom:0px,
add call
$("#div).slideDown();
will show with the slideUp-to-show effect you want.
Jquery toggle
This toggle effect is only for up and down. Jquery UI is for every other direction
For those who donĀ“t use the Jquery UI but want to add the function to Jquery Library:
jQuery.fn.slideUpShow = function (time,callback) {
if (!time)
time = 200;
var o = $(this[0]) // It's your element
if (o.is(':hidden'))
{
var height = o.css({
display: "block"
}).height();
o.css({
overflow: "hidden",
marginTop: height,
height: 0
}).animate({
marginTop: 0,
height: height
}, time, function () {
$(this).css({
display: "",
overflow: "",
height: "",
marginTop: ""
});
if (callback)
callback();
});
}
return this; // This is needed so others can keep chaining off of this
};
jQuery.fn.slideDownHide = function (time,callback) {
if (!time)
time = 200;
var o = $(this[0]) // It's your element
if (o.is(':visible')) {
var height = o.height();
o.css({
overflow: "hidden",
marginTop: 0,
height: height
}).animate({
marginTop: height,
height: 0
}, time, function () {
$(this).css({
display: "none",
overflow: "",
height: "",
marginTop: ""
});
if (callback)
callback();
});
}
return this;
}
Credits: #redbmk answer
Despite the name, slideDown can actually slide your element both ways. Use absolute position if it is required to animate inside the parent element:
#slideup {
position:fixed;
bottom:0;
background:#0243c9;
color:#fafefa;
width:100%;
display:none;
padding: 20px;
}
#littleslideup {
position:absolute;
bottom:0;
background:#000;
color:#fff;
display:none;
padding:10px;
z-index:100;
}
#slidedown {
position:fixed;
top:0;
background:#c94333;
color:#fafefa;
width:100%;
display:none;
padding: 20px;
}
button {
display:inline-block;
font-size:16px;
padding:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="position:relative">This amounts to 70% of the total timber stand area of the region (not including the dwarf pine and shrubby alder) and is more than the total area of all other stone birch forests growing in the Magadan, Khabarovsk, Primorye and Sakhalin regions and other areas of its distribution.
<div id="littleslideup">Absolute-positioned element</div>
</div>
<span style="color:red">Click >> </span>
<button onclick="jQuery('#slideup').slideDown(1500);" >"Slideup"</button>
<button onclick="jQuery('#slidedown').slideDown(1500);" >"Slidedown"</button>
<button onclick="jQuery('#littleslideup').slideDown(1500);">"Slideup" inside element</button>
<div>Finally, closing the subject of volcanic activity, it must be said that the stone birch stands by its functional reaction quite adequately in order to re ect the character and intensity of the physical, chemical and thermic processes, stipulated by volcanism as well as the in uence upon biota and ecosystems.</div>
<div id="slideup">Could be a bottom cookie warning bar</div>
<div id="slidedown">Could be a top cookie warning bar</div>
I've got some downvotes so I checked my answer and indeed I didn't answered correctly the OP question, sorry. So I'm gonna try to fix that.
First, the slideUp() method in JQuery is intended to hide the element rather than reveal it. It is basically the opposite of slideDown() which shows your element by sliding it down.
By knowing that I think we agree that there is no magic function right there to do a slide up effect to show an element (in JQuery).
So we need to do a little bit of work to get what we need: slid up reveal effect. I found out some solutions and here is one I think simple to implement:
https://coderwall.com/p/9dsvia/jquery-slideup-to-reveal
The solution above works with the hover event, for the click event try this modified code:
http://jsfiddle.net/D7uT9/250/
The answer given by #redbmk is also a working solution.
Sorry for my misunderstanding the first time.
OLD ANSWER
It's an old post, but if someone is looking for a solution here is my recommandation.
We can, now, use slideToggle() to achieve this effect (without the need of jQuery UI).
$(".btn").click(function () {
$("div").slideToggle();
});
Documentation: http://api.jquery.com/slidetoggle/
Having encountered this with a student looking to "slide up always hide" an error container, I advised he simply use CSS transitions:
.slide-up {
transition: 1s ease-out;
transform: scale(1);
}
.slide-up[aria-hidden="true"] {
transform: scale(0);
height: 0;
}
jQuery(document).ready(function($) {
const $submitButton = $(".btn");
const $someDivs = $("div");
const $animatedSlidingTargets = $(".slide-up");
$someDivs.on("click", function() {
$animatedSlidingTargets.attr("aria-hidden", true);
});
});
For #Jason's answer, whether slide-up to show and slide-down to hide, you still need to use the { direction: "down" } option in jQuery:
$(".btnAbout").on("click", function () {
// Slide-up to show
$("#divFooter").show("slide", { direction: "down" }, 1000);
});
$("#btnCloseFooter").on("click", function () {
// Slide-down to hide
$("#divFooter").hide("slide", { direction: "down" }, 1000);
});
But this requires jquery-ui, or else you'll hit the TypeError: something.easing[this.easing] is not a function error:
<script defer src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>

Categories

Resources