I'm having a strange issue with jQuery and a fading loop. Let's see a bit of code (here on JSFiddle: http://jsfiddle.net/4fcvze4m/1/):
$('.spin-block').each(function(index) {
$(this).delay(index * 200 + 800).fadeIn();
})
.spin-block {
display: none;
margin: 5px;
padding: 10px;
background: #a00000;
color: #fff;
}
<div class="spin-block">1</div>
<div class="spin-block">2</div>
<div class="spin-block">3</div>
<div class="spin-block">4</div>
<div class="spin-block">5</div>
<div class="spin-block">6</div>
<div class="spin-block">7</div>
<div class="spin-block">8</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
That's basically it.
So, sometimes (it's very random), one of this block don't show up, Mostly 5th or 6th. It can work perfectly 30 times a row and have this issue on the next refresh. I tried a workaround with this :
$('.spin-block')
.each(function(index) {
$(this).delay(index * 200 + 800).fadeIn();
})
.promise().done(function() {
console.log('debug');
$(this).fadeIn();
});
When everything is ok, the 'debug' log show off, but when there's one missing, the console remain empty, even if next .spin-block appears. And if i force some blocks not to show, then this workaround nicely works and fade in the remaining ones (after the end of the animation, but i don't care) :
var i = 800;
$('.spin-block')
.each(function() {
i += 200;
if (i > 1400) {
$(this).delay(i).fadeIn();
}
})
.promise().done(function() {
console.log('debug');
$(this).fadeIn();
});
There it is. Have you any idea of what's going on ? It's totally random, on any browser as far as i tested. Thank you!
Please note: This is not happening on the Fiddle I posted. I know it comes from my own JS file, but I don't have the possibility to put everything here. Besides, this is pretty much the first thing that happen in my init function.
I believe, the issue you are facing is due to the class of Divs being altered dynamically during run-time and the asynchronous nature of how jQuery animations work.
This JSFiddle explains the same. Essentially, it is the same set of Divs you had created initially. But instead of just animating them (iterating through $.each), I am introducing one more statement after the $.each which will remove the class associated with one of the Divs. See code below:
$(function () {
$('.spin-block').each(function (index) {
$(this).delay(index * 200 + 800).fadeIn(1000, fnCallback(index));
});
//Removing class dynamically for div 5 alone.
$('.spin-block').eq(4).removeClass('spin-block');
});
You would expect this to animate all Divs and then removeClass from the 5th Div. But what really happens is, animation starts, simultaneously Class "spin-block" is removed from Div 5, thus blocking Div5 from being animated!
Related
I'm having an issue trying to get .fadeIn(), .fadeOut(), and .hide() to behave properly when an element is hovered over.
Let's say I have a container, .post-box.
.post-box contains two divs: .description and .quote. The .quote div is initially hidden so that when .post-box is hovered over, it fades in and takes the place of the .description div, which gets hidden with .hide().
When .post-box is hovered out of, .quote fades out and .description is faded in again.
$(document).ready(function() {
var description = $('.description');
var quote = $('.quote');
var postBox = $('.post-box');
postBox.hover(function() {
$(this).find(description).clearQueue().stop(true, true).hide(0, function() {
quote.fadeIn(300);
});
}, function() {
$(this).find(quote).clearQueue().stop(true, true).fadeOut(300, function() {
description.fadeIn(300);
});
});
});
It seems that I've got this concept working fairly well except for one issue. If you quickly hover over .post-box, quickly hover out, and then quickly hover over again, you're presented with both the .quote and .description divs showing at the same time (see example screenshot here).
I thought I was preventing them from firing at the same time based on how my functions are set up, but I must be missing something important for this to be happening.
Here is my fiddle so you can see it in action.
Could somebody please lead me in the right direction?
My guess would be to also clear the animation queue for the quote element on hover.
$(this).find(quote).clearQueue().stop(true, true).hide();
I've updated the fiddle accordingly .
I have a <div> on my web page that I would like to have an opacity of 1 while you're hovering over it, but when the mouse is not hovering over it I would like it to fade to an opacity of 0.3. My problem is that currently when I hover over the <div> it starts fading in and out several times (rather than just once). I'm not sure if this is why, but I suspect it's because it detects the mouse rolling over the multiple <div>s that are within the one that I set to fade out.
Here is a very simplified segment of my web page to illustrate what I have so far:
<div id="div1">
<div id="div2" onmouseover="fadeElementTo('div1', 500, 1)" onmouseout="fadeElementTo('div1', 500, 0.3)">
<div id="div3">
<div id="div4">
</div>
</div>
<button id="myButton" onclick="doACoolAnimation()" ></button>
</div>
</div>
My fadeElementTo() function is pretty simple:
function fadeElementTo(eid, speed, opacity, callback) {
$("#" + eid).fadeTo(speed, opacity, callback);
}
In case it's relevant, I also have a button that animates the same div by simply moving it left or right when the button is clicked.
function doACoolAnimation() {
var hiddenState = GLOBAL_VAR.hiddenState;
// If the <div> is already hidden, make it visible
if (hiddenState == null || hiddenState == 1) {
GLOBAL_VAR.hiddenState = 0;
$("#div1").animate({
left: "0px"
}, 1500);
}
// Otherwise, hide it
else {
GLOBAL_VAR.hiddenState = 1;
$("#div1").animate({
left: "-800px"
}, 1500);
}
}
Any ideas what might be causing my bug? And better yet, what can I do to fix it?
Try onmouseenter instead of onmouseover and use jQuery to attach/bind those events rather than the attributes so it works the same across all browsers.
$('#outer').mouseenter(function() {
$('#log').append('<div>Handler for .mouseenter() called.</div>');
});
see here
Use mouseenter event to stop event bubbling, and stop method to make sure you clear unfinished animations on that element.
$('#div2').mouseenter(function(){
$('#div1').stop().fadeTo(500,1);
});
It detects the events multiple times. For example, if you want to change the size, going on and off fast changes the size even when the mouse is not on the div. The code needs to exit the program when the mouse is not on the div. To do that, you might include the code in something that kills the code when the mouse is not on top of the div so that the queued fades/animations do not run.
Edit:
Try looking at the JQuery documentation to see if there is anything that you can use.
You might able to use these:
I've seen a few questions about a similar issue, but I haven't found a solution that makes sense to me yet. The problem is on the JSFiddle here: http://jsfiddle.net/twchapman/EEXjR/2/
Click on Portfolio to see the behavior.
The functions I wrote:
function changeTab(tab) {
active = tab;
$("#" + tab).slideDown(animspeed);
}
function change(tab) {
if (tab == active) return;
$("#" + active).slideUp(animspeed, function () {
changeTab(tab);
});
}
I'm only using Chrome, but I'm pretty sure you'll get this error on any browser: when the page loads, it slides the content div down, and clicking the links (only Portfolio actually works at the moment) will slide the current div up, then the correct one down.
It's working almost completely as intended, but with one minor issue: when the animations begin, the div's height "jumps", and it's momentarily taller while the animation takes place, then "jumps" to the correct size when finished.
The two common solutions I've found have suggested: 1. Add a width to the style of the div, which already exists, and 2. change the height/margin parameters of the slide function when it's called. To me, the second solution seems like it shouldn't be necessary, as I don't provide any options other than an animation length.
I'm hoping this is just me missing something and being silly, not a big problem with the way I'm doing things.
The problem comes from padding which at times can make jQuery animations jittery.
A fast solution for your problem is to leave your Js untouched and use a natural box model for your layout.
In your css just include:
* { -webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
I really suggest to read this Paul Irish blog post and to include this code in all your projects.
Here's a working demo: http://jsfiddle.net/gleezer/EEXjR/3/
Update your js.
function change(tab) {
if(tab == active) return false;
console.log(tab);
console.log(active);
if($("#" + active).length){ //check element is exists.
$("#" + active).slideUp(animspeed, function() {changeTab(tab)})
}else{
changeTab(tab);
}
}
I am making a chat-like interface which can be seen here (best viewed in Chrome right now):
http://qas.im/web/sms.php
The temporary username:password is temp_guest:password
My problem is that when you click one of the chats, it doesnt automatically scroll to the bottom when I use this code:
$(".messages").attr({ scrollTop: $(".messages").attr("scrollHeight") });
What could be wrong? The messages div has a css of:
.messages {
height:400px;
overflow: auto;
}
For people who are wondering: Page isnt HTML validated yet but I will be cleaning it up soon. Most of the page is auto-generated which is challenging to make the code look pretty ;P
If you are using jQuery 1.6 or later, use prop instead of attr.
Working example: http://jsfiddle.net/FishBasketGordo/PNwj3/
I found two issues.
The first is that you were trying to set all .message DIVs to the height of the first DIV, so if the first DIV was hidden, it would never work.
The second was that jQuery's attr function is only for node attributes.
This method works better, and scrolls all the divs correctly:
$(".messages").each(function(idx, node) { node.scrollTop = node.scrollHeight; });
Alternatively, you can improve performance by using this selector:
$(".messages:visible").each(function(idx, node) { node.scrollTop = node.scrollHeight; });
Which works on visible message nodes.
I use the following snippet to make an element's background lightblue, then slowly fade to whiite over 30 seconds:
$("#" + post.Id).css("background-color", "lightblue")
.animate({ backgroundColor: "white" }, 30000);
Two questions.
First, instead of fading to white, is there a way to fade opacity to 100%? That way I don't have to change "white" if I choose to change the page's background color?
Second, about once out of every 10 or 15 times, the background stays lightblue and fails to fade to white. I'm using the latest versions of jQuery and the UI core. What could be going wrong?
EDIT: Bounty is for a solution to problem regarding second question.
EDIT2:
Apparently I got downvoted into oblivion because I said I rolled my own solution but didn't show it. My bad. I didn't want to be self-promoting. My code works 100% of the time and doesn't require jQuery. A demonstration and the code can be found at:
http://prettycode.org/2009/07/30/fade-background-color-in-javascript/
For your second question: in my experience this is usually because a Javascript error has occurred somewhere else on the page. Once there is one Javascript exception, the rest of the page stops running Javascript. Try installing Firebug (if you haven't already), then open up the "Console" tab and enable it. Then any javascript errors or exceptions will be printed to the console.
Another thing to try (which kinda contradicts my last statement...) is to disable all your browser plug-ins to see if you can recreate. Sometimes they interfere with scripts on the page (particularly GreaseMonkey.)
If you could provide a sample HTML snippet which reproduces this animation problem it would be a lot easier for us to help you. In the script I have pasted below, I can click it all day, as fast or slow as I like, and it never fails to animate for me.
For the first question: I know you said you'd found a workaround, but the following works for me (even on IE6) so I thought I'd post it, since it may be different from what you were thinking. (Note that setting CSS "opacity" property through jQuery.css() works on IE, whereas IE does not support the "opacity" property directly in CSS.)
<html>
<head>
<style>
body { background-color: #08f; }
#test { background-color: white; width: 100px; }
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script>
var myOpacity = 0.125;
$(function(){
$('#test').css('opacity', myOpacity);
$('a').click(function(){
myOpacity = 1.0 - myOpacity;
$('#test').animate({ opacity: myOpacity });
return false;
});
});
</script>
</head>
<body>
<p>Click me</p>
<div id="test">Test</div>
</body></html>
Dont forget the color plugin.
See here
When the color fails to animate to blue you could try to use the callback function to log a message to the console. You can then check that the event actually fired and completed. If it does then you could potentially use two animates. The first one to animate to a halfway house color then the use the callback to animate to white (so you get two bites of the cherry, if the outer fails but completes the callback has a second go)
It would be good if you could try to recreate the issue or give a url of the issue itself.
e.g
$("#" + post.Id).css("background-color", "lightblue")
.animate({ backgroundColor: "#C0D9D9" }, 15000, function(){
$(this).animate({ backgroundColor: "#ffffff" }, 15000)
});
You could always use something like this, avoiding the JQuery animate method entirely.
setTimeout(function() { UpdateBackgroundColor(); }, 10);
UpdateBackgroundColor() {
// Get the element.
// Check it's current background color.
// Move it one step closer to desired goal.
if (!done) {
setTimeout(UpdateBackgroundColor, 10);
}
}
Also, you may be able to remove the "white" coding by reading the background color from the appropriate item (which may involve walking up the tree).
It is possible to have jQuery change the Opacity CSS property of an item (as mentioned in another answer), but there's two reasons why that wouldn't work for your scenario. Firstly, making something "100% opaque" is fully visible. If the item didn't have any other modifications to its opacity, the default opacity is 100%, and there would be no change, so I'm guessing you meant fading to 0% opacity, which would be disappearing. This would get rid of the light blue background, but also the text on top of it, which I don't think was your intent.
A potentially easy fix for your situation is to change the color word "white" to "transparent" in your original code listing. The color plugin may not recognize that color word (haven't checked documentation on that yet), but setting the background color to "transparent" will let whatever color behind it (page background, if nothing else) shine through, and will self-update if you change your page background.
I'll answer your first question.
You can animate opacity like this:
.animate({opacity: 1.0}, 3000)
I think you can try using fadeOut/fadeIn too..
What about:
$("#" + post.Id).fadeIn( "slow" );
You could possibly have two divs that occupy the same space (using position: absolute; and position: relative; setting the z-index on one higher to make sure one is above and the other is below. the top one would have a transparent background and the one below would have a background color. then just fadeout the one below.
As for the second question:
If you think the default animation classes from JQuery are not properly working you could try Bernie's Better Animation Class. I have some good experiences with that library.
Animate only works for numbers. See the jquery docs. You can do opacity but you can't do background color. You can use the color plug in. Background-color uses strings like 'red', 'blue', '#493054' etc... which are not numbers.