An animate function and Internet Explorer - javascript

I know this is a long shot because it is a large script and I doubt anyone will want to read through all this but here it goes.
I have an animation function that animates the style properties of a list of elements. This function can be found here. Now I know all about cross browser opacity and I can set it manually i.e. I can set the opacity of an element to .5 (50 in IE's case) and it works perfect in every browser. Just when I try to animate my opacity property through my function it does not move.
As you can see in there I have a lot of code just to get IE's method of alpha(opacity=x) working.
For an example of it please see this fiddle. Sorry about it being so messy. If you click the paragraph tag that says Fade to .5 opacity on click. in any browser other than IE it will fade to 0, not .5 because I am testing stuff. Now if you click the same tag in IE nothing happens.
I doubt anyone will be able to help with such a complicated and specific problem but any suggestion will be much appreciated.

Looks like you're implementing your opacity logic twice, both in css() and animate(). That's bad design IMO no matter how much you're aiming for high performance. Once you fix that, animate() will be dependant on a working css() function, and since that works, animate() will work.

Related

Angular ng-style does not update in Safari

I've built a pretty simple carousel in Angular using CSS animations and it works great in Chrome, but when I decided to test in Safari I noticed the click and drag functionality does not work. I've been struggling with this for the past few days and I hope you can help.
After some investigation, I've come to the conclusion that the $scope.getAnimatorStyles method is being properly invoked but the ng-style="getAnimatorStyles()" is not updating the dom as expected.
I've tried to following with no luck.
Force a scope update by calling $scope.$apply()
Watch $scope.animationDelay and apply the styles directly to the DOM
Force the browser to reflow by calling .offsetHeight
Update $scope.animationDelay inside $timeout
The odd thing is that if I apply the styles to the document body it works which makes me think that Angular is doing something weird to the directive.
Here is a codepen with the slider code: http://codepen.io/jabes/pen/KNpEbq
Any help is very much appreciated.
Edit #1:
So I've made some progress by forcing a reflow. On click and drag I change the display property which works somewhat, but this also resets the animation so this is not a solution. I've also taken a couple GIFs to illustrate how the browser is not rendering properly.
Here is Chrome (http://recordit.co/fcmIdVntjC), notice how the animator element is moving along with the cards and when I change the delay property it also changes position along with the cards.
Here is Safari (http://recordit.co/V2bwhL877J), notice how the animator element is static while the cards animate and when I change the delay it moves but the cards do not change position.
Edit #2:
Okay so I've isolated the HTML/CSS and stripped out all Angular and JavaScript and the problem still persists. Safari does not update the animation position when animation-delay is changed in the element's style property.
Edit #3:
This issue seems unrelated to Angular altogether. I have created another post that illustrates a css animation bug in Safari: CSS Animation Delay Bug In Safari
Have you tried doing a console.log on the style object that is being generated and returned by the getAnimatorStyles() function? Perhaps there's something happening there that you're not expecting.
Also, can you copy/paste that same style object back into the template definition, just to test it and see if anything different happens?
When I'm totally stuck, I always double-check the basics just to rule them out. Sometimes, it is just a basic error that we overlook because we're looking for a more difficult problem which doesn't exist.

Safari jittering/jumping (bug?) on first "focus" event of page load

I'm currently fighting a very frustrating bug on Safari, and I'm not sure where else to turn.
It seems most elements (but not all, and I can't discern the differentiating factor) that will trigger a focus event will cause all elements on the page that are transitioned or animated to jump ~2px to the top and left. And this only occurs on the first focus event after the page loads.
It's a little annoying to see the bug, as it's in the logged-in portion of droplr.com, and I have been completely unable to distill down a simpler case on JSFiddle.
If you have/create an account and log-in, click on this edit icon for a drop:
You'll see that on the first focus of the page, things jitter. Here's the timeline when there's a single drop on the page and I trigger focus on an offending element:
With more drops, it's just more of the same, but it seems to max out around 40 paints. And the profiler doesn't suggest anything nefarious. Just a trip through jQuery internals.
If instead of laying elements out via a translate3d or matix3d, I simply use top and left, this bug goes away. After hours and hours of debugging this, I'm at a complete loss.
Hoping someone has seen something similar, could take a look, or could give me advice on debugging next steps.
Thanks so much!
Update: Dave Desandro suggested it was the 3d acceleration kicking in, so I tried it out with a translate instead, and sure enough, that did not cause the jitter. I have no idea why the hardware acceleration would be firing up with a focus event though, and only once.
I've tried setting a transformZ of 0 on page load to go ahead and ramp-up the hardware, but no luck there, either. Any more ideas are welcomed.
I've had this issue a while back and honestly I don't remember what exactly was the cause but here are some of the steps I followed:
Check that you don't have hide() and show() for the same element in the next line or vice versa.
Example:
el.show()
el.hide()
Change Custom fonts to "Arial"
For the elements you don't want focus events add this code at the bottom of your scripts:
noFocusElem.off('focus');
This will make sure to remove any focus handlers you might have added by mistake
Finally place your css before any scripts. It's a know fact that adding css rules after an inline style has been applied may cause jitter especially if you're using line-hieght property
Hope this helps :)
I've had this happen when using custom font kits. Could this be the issue? Some events cause custom fonts to re-draw, which can cause a ever so slight "jitter" in page display.
Sometimes, manually setting heights and widths on all the parent HTML elements can reduce the flicker.
I know this question was posted a while ago and this is a bit of a long shot but here goes:
Maybe as a starting point go back to chrome and look at the composite layering:
Hit this into the address bar:
about:flags
You will be able to enable composite borders from within there. The red borders generally indicate a rendering issue:
http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
What I have found from time to time is that although there are rendering issues in Chrome the browser copes pretty well with hiding them from me. In other webkit based browsers however the result can be more noticable (i.e. android).
I've also seen flickering occur when z-indexes are being used in conjunction with content that is being transformed.
Either way it would be great to know how you resolved this issue (if you did). Post an answer to your own question perhaps?
A way to avoid spending time fixing load time twitches; you could set the page to hidden then make elements visible with the load. If your page is slow to load, you may want to have a spinner default to visible, then have load hide it. Then you could come back to the issue when you have nothing better to do.
Just my 2c worth.
The first thing I would try:
First in chrome, whack in 'about:flags' (yes I know you're not using Chrome). Find the 'Composited render layer borders' and turn it on. Once this feature is switched on you'll get a rough idea of what is being rendered/hardware accelerated.
See: http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
and look for any rendering problems. These are normally caused by z-indexes. Play around with any z-indexes and hide/show certain elements until the rendering issues are resolved. Then work from there. translate-z hacks and opacity can also cause problems.
From experience I've found rendering problems in other webkit browsers can be diagnosed using chrome. Flickering is a common occurrence on the stock android browser.
Secondly: take a look at the focus event itself and try things like preventing the default behaviour. Seems like a long shot to me but give it a go.
I haven't tested this, so I will be very surprised if it works... but here's an idea:
$(document).ready(function() {
$(document).focus(function(e) {
e.preventDefault();
});
$(document).click(function() {
$(document).unbind();
});
});
I've been running into the same issue recently and found something that fixed it in my case.
Check for anything that's hidden offscreen like:
text-indent: -9999px;
left: -9999px;
Removing any instance of these from the 3d accelerated elements (including children) stopped the content jump on focus for me.

Why are [my] CSS3/jQuery transitions so imperfectly smooth, and how do I make them more smooth?

As much as I've searched for information about this all over the internet, I can't find anything about it, so I've come here for help.
What's been bugging me: That no matter which method I use -- a jQuery .animate, or a css3 transition, [my] animations don't appear to be perfectly smooth. I didn't understand why they appear this way at first, and it's so subtle I ended up having to do some video capping to prove it. But it's definitely there -- the animations are juttery. Sometimes a frame happens too fast, and sometimes too slow.
Flip it back and forth six or seven times, and you'll hopefully see what I'm talking about.
I can understand this with jQuery -- JS execution isn't perfect. A quick profiling shows that indeed, when using jQuery anim, some frames get triggered too soon and some frames are late. But with CSS3?
What do people do to solve this problem?
I am moving the container using the margin-left CSS property and .animate of jQuery and is pretty smooth. Use the arrow keys to use it (left and right)
The current version of that project its now full of images, text, iframes and is still smooth.
Set this JS before your code:
jQuery.fx.interval = 100;

Updating IE7's element-layout

I've been working on a complex web-application and have tested it with 'normal Browsers' and ie >= 8. Now I need to get it to work in IE7 wich, of course, is a mess. I'm getting lots of troubles that when you play with an elements style, especially with positioning, IE7 has a lot of rendering bugs.
To be specific, I'm using Script.aculo.us' "BlindDown"-effect, which updates top- and left-values of an element in a nice animation. After the animations done the element suddenly disappears and I found out it's set to left: 1649px even though its left-value is set to something 'normal'.
This is a bug in IE7. I found out if you set zoom:1 on that element its layout gets updated and the element will be rendered properly again, at its proper position. But what you have to do if zoom is already set to 1 is to set it to zoom:2 and zoom:1 again so the element will actually get updated.
This is madness. However you can't do much about this. But I'm getting tired of the rather hacky zoom:2->zoom:1 thing so I'm asking if there is a way to update an element's layout without something stupid like that zoom:2/1-thing. Maybe there's a function or a more clever way to do this. If you have an idea, anything's appreciated.

How do you fix the flickering that occurs when you use slideToggle in jQuery?

I have a simple unordered list that I want to show and hide on click using the jQuery slideUp and slideDown effect. Everything seems to work fine, however in IE6 the list will slide up, flicker for a split second, and then disappear.
Does anyone know of a fix for this?
Thanks!
Apologies for the extra comment (I can't upvote or comment on Pavel's answer), but adding a DOCTYPE fixed this issue for me, and the slideUp/Down/Toggle effects now work correctly in IE7.
See A List Apart for more information on DOCTYPES, or you can try specifying the fairly lenient 4/Transitional:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
Just let IE6 flicker. I don't think it's worth it to invest time in a dying browser when your base functionality works well enough. If you're worried about flickering for accessibility reasons, just sniff for IE6 and replace the animation with a generic show() and hide() instead. I recommend avoiding complicated code for edge cases that don't matter.
$(document).ready(function() {
// Fix background image caching problem
if (jQuery.browser.msie) {
try {
document.execCommand("BackgroundImageCache", false, true);
} catch(err) {}
}
};
Apparently.
Oli's fix only seems to apply to flickering backgrounds, which is not the case here.
Ryan McGeary's advice is solid, except for when the client/your boss absolutely demand that IE6 not act like it has fetal alcohol syndrome.
I found the solution here: Slide effect bugs in IE 6 and 7 since version 1.1.3
Added a doctype declaration to the top of the file (why wasn't it there before? who knows!) and the flicker vanished, never to be seen again.
From what I've heard and tried (including the other suggestions here) there are still situations where the flicker will continue to be noticeable, especially when you don't have the choice of easily leaving quirks mode.
In my case I had to stay on quirks mode for now and the other suggestions still didn't fix the problem for me. I ended up adding a little workaround until we can finally leave quirks mode:
//Start the slideUp effect lasting 500ms
$('#element').slideUp(500);
//Abort the effect just before it finishes and force hide()
//I had to play with the timeout interval until I found one that
// looked exactly right. 400ms worked for me.
setTimeout(function() {
$('#element').stop(true, true).hide();
}, 400);
This code does not depends on the browser (no browser detection), works great and reproduces the behaviour of the method .slideUp
$("#element").animate({
height: 1, // Avoiding sliding to 0px (flash on IE)
paddingTop: "hide",
paddingBottom: "hide"
})
// Then hide
.animate({display:"hide"},{queue:true});
Dunno if someone will read this answer, but here is a workaround for those who, like me, can't add a document type to the page (thank you Sharepoint 2007 default templates) without spending a few days on a complete template revision.
On a DOCTYPE-less document, the flickering occurs when an element height reaches 0. So the workaround I've found is to animate my elements to an height of 1px, rather than 0.
Like this:
$(".slider").click(function (e) {
$(this).animate({"height" : "1px"});
});
Hope it will help.
N.B: don't forget that in order to slideDown the element, you have to previously store its initial height somehow (node property, rel attribute hack, etc).
I'm working with a carousel that has marked-up copy over some background slides. The slide transition is a fade. Everything's fine so far.
But some parts of the copy fade-in after the slide loads. And then fade-out right before the slide transition. This copy, an unordered list of links (UL > LI*2 > A), faded-in over the slide background. This, too, is fine in every browser except IE. IE had a flickering background on the UL.
What was happening is that there were two simultaneous fade-Ins running: the background image on the slide & the UL. I used sergio's prototyping setTimeout function to run the UL fadeIn() after the slide had completed loading. Then, I called another setTimeout to make the slide transition right after the UL fadeOut().
setTimeout is your friend when combating IE flicker.
We had the same problem today. Not only in IE6, but also in IE8! I've fixed it by hiding the div somewhat earlier, by using a timeout:
var pane = $('.ColorPane');
var speed = 500;
window.setTimeout(function() { pane.css('display', 'none'); }, speed - 100);
pane.slideUp(speed);
Hope it helps some of you out there.
I posted a quick fix solution over at http://blog.clintonbeattie.com/how-to-solve-the-jquery-flickering-content-problem/
In short, add overflow:hidden to the containing element that you are sliding in/out. Hope this helps!

Categories