I've found that there seems to be a problem using css transitions properties when they are initially set to auto. To circumvent this I've set the initial css properties using jquery, before adding the css transition property.
The issue I'm having is that when I define the transitional properties immediately after setting the initial css properties, I get weird behaviour. EXAMPLE: http://jsfiddle.net/3zUDc/10/
However, when I delay setting the transitional properties by a few milliseconds, I get the intended behaviour, but the code seems uglier. EXAMPLE: http://jsfiddle.net/3zUDc/9/
Is there a way to accomplish the behaviour seen in the second example without putting the css transitions and destination parameters in the setTimeout block?
Thanks for any help!
.show() is an answer...
$('a:first').click(function(){
$(this).css({'width': $(this).width() / $(this).parent().width() * 100 + '%', 'height': $(this).height()});
$('a:first').show().css({
'-webkit-transition': 'all 3s',
'-moz-transition': 'all 3s',
width: '100%',
height: '100px',
backgroundColor: 'black'
});
});
Here is the jsfiddle demo
You can add .css('left') to the end of your css declaration: http://jsfiddle.net/YDt7G/
The reason this works (or doesn't work) is because the browser's javascript engine optimises code that changes the DOM. So it doesn't update the DOM instantly after every line of code and is basically putting all the code into one DOM update.
Adding the .css('left') forces browser's javascript engine to look at the DOM and in-turn update the DOM beforehand.
Related
I'm having some major headache trying to apply CSS3 transitions to a slideshow trough JavaScript.
Basically the JavaScript gets all of the slides in the slideshow and applies CSS classes to the correct elements to give a nice animated effect, if there is no CSS3 transitions support it will just apply the styles without a transition.
Now, my 'little' problem. All works as expected, all slides get the correct styles, the code runs without bugs (so far). But the specified transitions do not work, even though the correct styles where applied. Also, styles and transitions work when I apply them myself trough the inspector.
Since I couldn't find a logical explanation myself I thought someone here could answer it, pretty please?
I've put together a little example of what the code is right now: http://g2f.nl/38rvma
Or use JSfiddle (no images): http://jsfiddle.net/5RgGV/1/
To make transition work, three things have to happen.
the element has to have the property explicitly defined, in this case: opacity: 0;
the element must have the transition defined: transition: opacity 2s;
the new property must be set: opacity: 1
If you are assigning 1 and 2 dynamically, like you are in your example, there needs to be a delay before 3 so the browser can process the request. The reason it works when you are debugging it is that you are creating this delay by stepping through it, giving the browser time to process. Give a delay to assigning .target-fadein:
window.setTimeout(function() {
slides[targetIndex].className += " target-fadein";
}, 100);
Or put .target-fadein-begin into your HTML directly so it's parsed on load and will be ready for the transition.
Adding transition to an element is not what triggers the animation, changing the property does.
// Works
document.getElementById('fade1').className += ' fade-in'
// Doesn't work
document.getElementById('fade2').className = 'fadeable'
document.getElementById('fade2').className += ' fade-in'
// Works
document.getElementById('fade3').className = 'fadeable'
window.setTimeout(function() {
document.getElementById('fade3').className += ' fade-in'
}, 50)
.fadeable {
opacity: 0;
}
.fade-in {
opacity: 1;
transition: opacity 2s;
}
<div id="fade1" class="fadeable">fade 1 - works</div>
<div id="fade2">fade 2 - doesn't work</div>
<div id="fade3">fade 3 - works</div>
Trick the layout engine!
function finalizeAndCleanUp (event) {
if (event.propertyName == 'opacity') {
this.style.opacity = '0'
this.removeEventListener('transitionend', finalizeAndCleanUp)
}
}
element.style.transition = 'opacity 1s'
element.style.opacity = '0'
element.addEventListener('transitionend', finalizeAndCleanUp)
// next line's important but there's no need to store the value
element.offsetHeight
element.style.opacity = '1'
As already mentioned, transitions work by interpolating from state A to state B. If your script makes changes in the same function, layout engine cannot separate where state A ends and B begins. Unless you give it a hint.
Since there is no official way to make the hint, you must rely on side effects of some functions. In this case .offsetHeight getter which implicitly makes the layout engine to stop, evaluate and calculate all properties that are set, and return a value. Typically, this should be avoided for performance implications, but in our case this is exactly what's needed: state consolidation.
Cleanup code added for completeness.
Some people have asked about why there is a delay. The standard wants to allow multiple transitions, known as a style change event, to happen at once (such as an element fading in at the same time it rotates into view). Unfortunately it does not define an explicit way to group which transitions you want to occur at the same time. Instead it lets the browsers arbitrarily choose which transitions occur at the same time by how far apart they are called. Most browsers seem to use their refresh rate to define this time.
Here is the standard if you want more details:
http://dev.w3.org/csswg/css-transitions/#starting
Is there a way to use a callback function after the screen is done resizing an element?
For example:
element.css('height', 'auto', function() {
element.css('height', element.height() - 6);
});
In words: when the element is reset to it's default height. The DOM needs to re-evaluate the height of the element. That takes a bit of time, but that time varies from client to client. So I don't want to use a setTimeOut function and slow down the script much more then needed.
So how can I execute some JavaScript just after the element's height is reset?
PS: I already tried the jQuery animate function. But still that callback function doesn't seem to wait long enough for the element to actually obtain it's original height.
Even tough the comments weren't helpful at all. I found something that actually seems to work. It waits for the height change to process and instantly process the next rule afterwords.
element.css('height', 'auto').delay(1).css('height', element.height() - 6);
My first Stackoverflow question. The tween seems to run because it calls the brute function at the end. However, there's no tween happening.
window.onload=init();
function init() {
testImg = document.getElementById("testImg");
createjs.Tween.get(testImg).wait(2000).to({alpha: 1}, 600).call(brute);
}
function brute() {
// why this function get called if there's no visible tween?
console.log("testImg alpha is " + testImg.alpha)
testImg.style.opacity=1;
}
#testImg {
opacity: .3;
background: url("http://oyos.org/oyosbtn_466x621.jpg");
}
<script src="https://code.createjs.com/tweenjs-0.6.2.min.js"></script>
<body>
<div id="testImg">
here is the div
</div>
</body>
TweenJS isn't really optimized to tween styles on HTML elements, since it was developed to tween properties directly on objects. There is a CSS plugin that can help, particularly when dealing with properties that have suffixes (like "px" on width/height, etc)
However, it can definitely be done. There are a few issues with your code:
As you mentioned in your comment above, you have to target the "opacity" instead. The alpha property is what EaselJS DisplayObjects use.
You have to target the testImg.style instead, since the opacity lives on that element, and not on the testImg directly. Setting opacity/alpha on the #testImg will do nothing
Unfortunately, TweenJS doesn't know how to read CSS properties set on elements using CSS classes or selectors. The getComputedStyle is very expensive to look up, and is required to determine what the current style of the element is.
You can totally make your demo work, but you have to consider these things. Here is an updated snippet (from this pen):
createjs.Tween.get(testImg.style) // Target the style
.to({opacity:0.3}) // Set the property initially
.wait(2000)
.to({opacity: 1}, 600)
.call(brute); // Tween the opacity instead
You could also use the change event to update the opacity yourself:
createjs.Tween.get(testImg)
.set({alpha:0}) // Still requires an initial set
.wait(2000)
.to({alpha:1})
.call(brute)
.on("change", function(event) {
// Every time the tween is updated, set the opacity
testImg.style.opacity = testImg.alpha;
});
Note that the CSS plugin I mentioned above can handle the computedStyle lookup now (a fairly recent addition).
Hope that sheds some light on the behaviour.
Cheers,
I'm trying to change the line-height property with jQuery using this:
jQuery(document).ready(function () {
var windowWidth = $(window).width();
$('h1').css({
'top': Math.floor(windowWidth * 0.0964) + 'px',
'left': Math.floor(windowWidth * 0.0872) + 'px',
'line-height': '0.9em !important'
});
});
If I use the inspector and check the element style, I can see the top and left property but not the line-height, can someone explain to me what's wrong?
And here's the jsFiddle I made just to be sure I'm not crazy!
http://jsfiddle.net/p4DU6/4/
Tested it in FF, Chrome, IE8 and IE9
Don't use !important. There's no need for that.
It works for me if you remove that.
Your inline style will have higher specificity than anything else in your CSS anyway, so no need to use !important.
This is discussed here: How to apply !important using .css()?
The problem seems to be the !important statement. There is a bug report for jquery and a way to work around it, namely creating new classes and combining them:
http://bugs.jquery.com/ticket/11173
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.