Having issue with jquery animation effects - javascript

Live Example Here
Press any of buttons. Can you see shaky slideDown effect? In fact it must be smooth and slow slide down.
If you've pressed for 1 time any of buttons try to press another one. The show and hide animation of forms is awful.
During anim.
After anim.
How to fix this problems?

The shakiness seems to be happening when each of the elements in the tab is hidden or displayed.
Get the height of each of your tabs and implement your resizing animation to those heights rather than individually animating after each element is hidden or displayed.

Try to play with .animate() and .fadeIn() .fadeOut() .fadeTo(time,opacity) instead of just .show() or .hide()

It's loading quite well for me. However it did take a long time for it to load in the first place. If you go to: http://gtmetrix.com/reports/tural.no-ip.org/ANBNA45n You'll see that your page is loading quite slowly and the stuttering effect you are seeing is probably coming from your computer having issues with the amount of information coming in.

You can try and speed things up a bit by making less $(selector) calls.. cache some of your jQuery objects when you are using them multiple times... also remember you can chain functions on jQuery objects.. jQO.addClass("foo").removeClass("bar"); is the same as jQO.addClass("foo"); jQO.removeClass("bar");
like so...
(function(){
var signin = $("#signin"), signup = $("#signup"), signin_f = $("#signin_form"), holder = $("#holder"), signup_f = $("#signup_form"), f_container = $("#form_container");
$(".button").click(function () {
if (counter === 0) {
signin.removeClass('default_radius').addClass('right_radius');
signup.removeClass('default_radius').addClass('left_radius');
$("#first").animate({
marginTop: "-=150px",
}, 500);
}
});
signup.click(function () {
if (counter === 0) {
holder.addClass('red_border').slideDown("slow");
f_container.show();
signup_f.show(0);
} else {
signin_f.hide(0);
holder.switchClass( "green_border", "red_border", 1000 );
f_container.animate({height:"260px"},1000);
signup_f.show(0);
}
counter++;
});
signin.click(function () {
if (counter === 0) {
holder.addClass('green_border').slideDown("slow");
f_container.show();
signin_f.show(1000);
} else {
signup_f.hide(0);
holder.switchClass( "red_border", "green_border", 1000 );
f_container.animate({height:"110px"},1000);
signin_f.show(0);
}
counter++;
});
})();

Related

Using a jquery slider for text instead of images?

This may be a little too specific, but I have a jquery slider that I am using <p> classes instead of images to cycle through customer quotes. Basically the problem I am running into right now is when it is static and non moving (JS code is commeneted out) they are aligned how I want them to be. As soon as the JS is un commented, they stretch out of view and you just see a white box?
Any ideas?
How I want each panel to look like:
jsfiddle
So I sort of made this my Friday project. I've changed a whole lot of your code, and added a vertical-align to the quotes and authors.
Here's the fiddle http://jsfiddle.net/qLca2fz4/49/
I added a whole lot of variables to the top of the script so you could less typing throughout.
$(document).ready(function () {
//rotation speed and timer
var speed = 5000;
var run = setInterval(rotate, speed);
var slides = $('.slide');
var container = $('#slides ul');
var elm = container.find(':first-child').prop("tagName");
var item_width = container.width();
var previous = 'prev'; //id of previous button
var next = 'next'; //id of next button
Since you used a % based width I'm setting the pixel widths of the elements in case the screen is reszed
slides.width(item_width); //set the slides to the correct pixel width
container.parent().width(item_width);
container.width(slides.length * item_width); //set the slides container to the correct total width
As you had, I'm rearranging the slides in the event the back button is pressed
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
I combined the prev and next click events into a single function. It checks for the ID of the element targeted in the click event, then runs the proper previous or next functions. If you reset the setInterval after the click event your browser has trouble stopping it on hover.
//if user clicked on prev button
$('#buttons a').click(function (e) {
//slide the item
if (container.is(':animated')) {
return false;
}
if (e.target.id == previous) {
container.stop().animate({
'left': 0
}, 1500, function () {
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
});
}
if (e.target.id == next) {
container.stop().animate({
'left': item_width * -2
}, 1500, function () {
container.find(elm + ':last').after(container.find(elm + ':first'));
resetSlides();
});
}
//cancel the link behavior
return false;
});
I've found mouseenter and mouseleave to be a little more reliable than hover.
//if mouse hover, pause the auto rotation, otherwise rotate it
container.parent().mouseenter(function () {
clearInterval(run);
}).mouseleave(function () {
run = setInterval(rotate, speed);
});
I broke this in to its own function because it gets called in a number of different places.
function resetSlides() {
//and adjust the container so current is in the frame
container.css({
'left': -1 * item_width
});
}
});
//a simple function to click next link
//a timer will call this function, and the rotation will begin :)
And here's your rotation timer.
function rotate() {
$('#next').click();
}
It took me a little bit, but I think I figured out a few things.
http://jsfiddle.net/qLca2fz4/28/
First off, your console was throwing a few errors: first, that rotate wasn't defined and that an arrow gif didn't exist. Arrow gif was probably something you have stored locally, but I changed the 'rotate' error by changing the strings in the code here to your actual variables.
So, from:
run = setInterval('rotate()', speed);
We get:
run = setInterval(rotate, speed);
(No () based on the examples here: http://www.w3schools.com/jsref/met_win_setinterval.asp)
But I think a more important question is why your text wasn't showing up at all. It's because of the logic found here:
$('#slides ul').css({'left' : left_value});
You even say that this is setting the default placement for the code. But it isn't..."left_vaule" is the amount that you've calculated to push left during a slide. So if you inspect the element, you can see how the whole UL is basically shifted one slide's worth too far left, unable to be seen. So we get rid of 'left_value', and replace it with 0.
$('#slides ul').css({'left' : 0});
Now, there's nothing really handling how the pictures slide in, so that part's still rough, but this should be enough to start on.
Let me know if I misunderstood anything, or if you have any questions.
So, a few things:
1) I believe you are trying to get all of the lis to be side-by-side, not arranged up and down. There are a few ways to do this. I'd just make the ul have a width of 300%, and then make the lis each take up a third of that:
#slides ul {
....
width: 300%;
}
#slides li {
width: calc(100% / 3);
height:250px;
float:left;
}
2) You got this right, but JSFiddle automatically wraps all your JS inside a $(document).ready() handler, and your function, rotate needs to be outside, in the normal DOM. Just change that JSFiddle setting from 'onload' to 'no wrap - in head'
3) Grabbing the CSS value of an element doesn't always work, especially when you're dealing with animating elements. You already know the width of the li elements with your item_width variable. I'd just use that and change your code:
var left_indent = parseInt($('#slides ul').css('left')) - item_width;
$('#slides ul').animate({'left' : left_indent}, 1500, function () {
to:
$('#slides ul').stop().animate({'left' : -item_width * 2}, 1500, function () {
4) Throw in the .stop() as seen in the above line. This prevents your animations from overlapping. An alternative, and perhaps cleaner way to do this, would be to simply return false at the beginning of your 'next' and 'prev' functions if #slides ul is being animated, like so:
if ($('#slides ul').is(':animated')) return false;
And I think that's everything. Here's the JSFiddle. Cheers!
EDIT:
Oh, and you may also want to clearInterval at the beginning of the next and prev functions and then reset it in the animation callback functions:
$('#prev').click(function() {
if ($('#slides ul').is(':animated')) return false;
clearInterval(run);
$('#slides ul').stop().animate({'left' : 0}, 1500,function(){
....
run = setInterval('rotate()', speed);
});
});

Does jquery trigger slidedown animation on an element that is already slidedown?

Well I hope the question is self-explanatory. I have the following code:
$(window).scroll(function () {
var scrollTop = $(window).scrollTop();
if (scrollTop > sliderTop) {
$('#slider').slideDown(1000);
} else {
$('#slider').slideUp(1000);
}
});
If I scroll down after a certain point the slideDown function will be called continuously. does JQuery animates it over and over again or is it smart enough to know that the element is already slide down? (currently I'm using a flag to check whether its already slide down).
The animation won't run again. See lines 459-468 in effect.js in the jquery src
doAnimation = function() {
// Operate on a copy of prop so per-property easing won't be lost
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
// Empty animations, or finishing resolves immediately
if ( empty || data_priv.get( this, "finish" ) ) {
anim.stop( true ); // ** here - stopping right after started.
}
};
doAnimation.finish = doAnimation;
But I would still recommend against it to improve code readability. just use a boolean, it doesn't hurt...

jQuery wait for an action to complete on different functions

I have created a newsfeed. The feed switches every 2 seconds. You can also manually switch left/right, or click the panel from the squares at the bottom. The switching between slides is down using jQuery UI Slide.
Right now, if you are in the middle of a slide, and you click left/right/squares, then another slide occurs on top of the existing, still going slide and the whole system is messed up.
How can I prevent other actions occurring if a slide/switch is already in progress?
This is my code:
$(document).ready(function(){
newsfeedTimer = setInterval(newsfeed, displayDuration);
// Manual change of feed (LEFT)
$('#newsfeeds_wrapper > .left').click(function(event){
event.stopPropagation();
feedLeft();
clearInterval(newsfeedTimer);
newsfeedTimer = setInterval(newsfeed, displayDuration);
});
// Very similar code for feed right
// Ignore the other method of switching (if it works for above, I can implement it for this one)
});
function newsfeed() {
feedRight();
}
// Feed to the Right
// jump is used to jump multiple newsfeed instead of one at a time
function feedRight(jump)
{
jump = typeof jump !== 'undefined' ? jump : 1;
var current = $('.newsfeed:first');
var next = $('.newsfeed:nth(' + jump + ')');
current.hide('slide',{duration: transitionDuration}, function(){
// Append as many needed
for( var i = 0; i < jump; i++ ) {
$('.newsfeed:first').appendTo('#newsfeeds');
}
next.show('slide',{direction : 'right' , duration: transitionDuration});
}
I don't want to stop() an animation! I want to disable changing the slides IF there is animation happening!!
without seeing the full breadth of the code, I am shooting myself in the foot here. But here is a direction I would take it. You could also have two functions, one to bind, another to unbind. When animation is initiated, you unbind the left/right controls. When stopped, you bind. Or, set a global variable... ala.
var config = {'inProgress': false};
$('#newsfeeds_wrapper > .left').click(function(event){
if(!config.inProgress){
event.stopPropagation();
feedLeft();
clearInterval(newsfeedTimer);
newsfeedTimer = setInterval(newsfeed, displayDuration);
}
});
in your animation function. Seems like when you cut/paste, some of the code is lost, so lets just assume some animation.
when you enter your animation functions, set config.inProgress = true;
function feedRight(jump)
{
config.inProgress = true;
// removed your code, but just using for simplicity sake
// added a callback
next.show('slide',{direction : 'right' , duration: transitionDuration},
function() {
// Animation complete. Set inProgress to false
config.inProgress = false;
});
)
}

Javascript fade in doesn't visibly animate

So I've created the following function to fade elements in and passed in a div that I want to fade in which in this case is an image gallery popup that I want to show when a user clicks an image thumbnail on my site. I'm also passing in a speed value (iSpeed) which the timeout uses for it's time value. In this case I'm using 25 (25ms).
I've stepped through this function whilst doing so it appears to be functioning as expected. If the current opacity is less than 1, then it is incremented and it will recall itself after the timeout until the opacity reaches 1. When it reaches one it stops fading and returns.
So after stepping through it, I take off my breakpoints and try to see it in action but for some reason my gallery instantly appears without any sense of fading.
var Effects = new function () {
this.Fading = false;
this.FadeIn = function (oElement, iSpeed) {
//set opacity to zero if we haven't started fading yet.
if (this.Fading == false) {
oElement.style.opacity = 0;
}
//if we've reached or passed max opacity, stop fading
if (oElement.style.opacity >= 1) {
oElement.style.opacity = 1;
this.Fading = false;
return;
}
//otherwise, fade
else {
this.Fading = true;
var iCurrentOpacity = parseFloat(oElement.style.opacity);
oElement.style.opacity = iCurrentOpacity + 0.1;
setTimeout(Effects.FadeIn(oElement, iSpeed), iSpeed);
}
}
}
Here's where I'm setting up the gallery.
this.Show = function (sPage, iImagesToDisplay, oSelectedImage) {
//create and show overlay
var oOverlay = document.createElement('div');
oOverlay.id = 'divOverlay';
document.body.appendChild(oOverlay);
//create and show gallery box
var oGallery = document.createElement('div');
oGallery.id = 'divGallery';
oGallery.style.opacity = 0;
document.body.appendChild(oGallery);
//set position of gallery box
oGallery.style.top = (window.innerHeight / 2) - (oGallery.clientHeight / 2) + 'px';
oGallery.style.left = (window.innerWidth / 2) - (oGallery.clientWidth / 2) + 'px';
//call content function
ImageGallery.CreateContent(oGallery, sPage, iImagesToDisplay, oSelectedImage);
//fade in gallery
Effects.FadeIn(oGallery, 25);
}
Could anyone help me out?
Also, I'm using IE10 and I've also tried Chrome, same result.
Thanks,
Andy
This line:
setTimeout(Effects.FadeIn(oElement, iSpeed), iSpeed);
calls Effects.FadeIn with the given arguments, and feeds its return value into setTimeout. This is exactly like foo(bar()), which calls bar immediately, and then feeds its return value into foo.
Since your FadeIn function doesn't return a function, that would be the problem.
Perhaps you meant:
setTimeout(function() {
Effects.FadeIn(oElement, iSpeed);
}, iSpeed);
...although you'd be better off creating that function once and reusing it.
For instance, I think this does what you're looking for, but without recreating functions on each loop:
var Effects = new function () {
this.FadeIn = function (oElement, iSpeed) {
var fading = false;
var timer = setInterval(function() {
//set opacity to zero if we haven't started fading yet.
if (fading == false) { // Consider `if (!this.Fading)`
oElement.style.opacity = 0;
}
//if we've reached or passed max opacity, stop fading
if (oElement.style.opacity >= 1) {
oElement.style.opacity = 1;
clearInterval(timer);
}
//otherwise, fade
else {
fading = true;
var iCurrentOpacity = parseFloat(oElement.style.opacity);
oElement.style.opacity = iCurrentOpacity + 0.1;
}
}, iSpeed);
};
};
Your code has a lot of problems. The one culpable for the element appearing immediately is that you call setTimeout not with a function but with the result of a function, because Effects.FadeIn will be executed immediately.
setTimeout(function(){Effects.FadeIn(oElement, iSpeed)}, iSpeed);
will probably act as you intend.
But seriously, you probably should not re-invent this wheel. jQuery will allow you to fade elements in and out easily and CSS transitions allow you to achieve element fading with as much as adding or removing a CSS class.
T.J. and MoMolog are both right about the bug: you're invoking the Effects.FadeIn function immediately before passing the result to setTimeout—which means that Effects.FadeIn calls itself synchronously again and again until the condition oElement.style.opacity >= 1 is reached.
As you may or may not know, many UI updates that all take place within one turn of the event loop will be batched together on the next repaint (or something like that) so you won't see any sort of transition.
This jsFiddle includes the suggested JS solution, as well as an alternate approach that I think you may find to be better: simply adding a CSS class with the transition property. This will result in a smoother animation. Note that if you go this route, though, you may need to also include some vendor prefixes.

jQuery Animation Jump

The header to my tumblr page seems a bit jumpy when I attempted to animate its growth and shrinkage when it is no longer on the top of the page.
The webpage is Tobacco Endeavors and is a tumblr blog.
<script type="text/javascript">
$(window).scroll(function(){
if ($(this).scrollTop() > 1) {
$("#abracadabra").fadeOut(500, function(){
$("#header").animate({padding:"1.5em 0"}, 500);
});
} else {
$("#abracadabra").fadeIn(500, function(){
$("#header").animate({padding:"1em 0"}, 500);
});
}
});
</script>
Thanks a bunch guys.
The scroll event could fire many times, you need to control concurrency with a flag, like so:
<script type="text/javascript">
window.flag = true;
$(window).scroll(function(){
if ($(this).scrollTop() > 1) {
if (window.flag) {
window.flag = false;
$("#abracadabra").fadeOut(500, function(){
$("#header").animate({padding:"1.5em 0"}, 500, function() {window.flag = true;});
});
}
} else {
if (window.flag) {
window.flag = false;
$("#abracadabra").fadeIn(500, function(){
$("#header").animate({padding:"1em 0"}, 500, function(){window.flag = true;});
});
}
}
});
</script>
UPDATE:
Updated a typo in code. Try new version above.
stop() and fadeTo() can fix some strange issues sometimes :)
jsBin demo
$(window).scroll(function(){
if ($(this).scrollTop() > 1) {
$("#abracadabra").stop().fadeTo(500,0, function(){
$("#header").stop().animate({padding:"1.5em 0"}, 500);
});
} else {
$("#abracadabra").stop().fadeTo(500,1, function(){
$("#header").stop().animate({padding:"1em 0"}, 500);
});
}
});
about your issue:
from the DOCS:
The .fadeOut() method animates the opacity of the matched elements. Once the opacity reaches 0, the display style property is set to none, so the element no longer affects the layout of the page.
causing jumpy result. On the other hand fadeTo() method
With duration set to 0, this method just changes the opacity CSS property, so .fadeTo(0, opacity) is the same as .css('opacity', opacity).
and as you can see affecting nicely the layout of the page.
See jQuery animate, not smooth
..Just set the easing parameter of the animation to linear.
There are also plugins people have made as alternatives if you feel inclined.
jQuery/JavaScript animations can be jumpy at times, and can also depend on an individuals personal hardware setup. What I like to do for animations is make a css class that has a transition, and the add the class. Additionally, make another css class that has the opposite transition, and add that one to animate out. This works pretty well, and if i'm not mistaken, provides increased browser compatibility.

Categories

Resources