Reputation: 1275
I have a pretty strange problem with the jQuery animate() function on an iphone 5. The scenario:
I attach an event handler to the touchend event on an element, starting an animation. Usually this works pretty fine. But as soon as I scrolled the page once swiping on this element, the animate-function doesn't animate anymore (on all future gestures). The event is fired and the handler is called, but animate doesn't do anything. I tried with the jQuery mobile events and now with oldscool element.attachaddEventListener both leading to the same result. The funny thing is:
A small demonstration page:
<!DOCTYPE html>
<html>
<head>
<title>Testpage</title>
<meta content="width=device-width, initial-scale=1.0, user-scalable=yes" name="viewport">
<script src="/3rdParty/scripts/jquery/jquery-1.8.3.js" type="text/javascript"></script>
<style>
body { padding: 10px;}
#mover { position: relative; width: 100px; background-color: red; color: #fff; padding: 5px; }
#hider { width: 100%; overflow: hidden; }
#touchme { border:1px solid #808080; margin-bottom:10px;line-height: 50px; text-align:center;}
</style>
<script>
$(document).ready(function(){
var elem = document.getElementById('touchme');
elem.addEventListener('touchend', positionHandlerEnd, false );
elem.addEventListener('mouseup', positionHandlerEnd, false );
});
</script>
<script>
function positionHandlerEnd(e) {
$('#mover').animate({left: '+=40px'});
e.preventDefault();
return;
}
</script>
</head>
<body>
<div id="touchme">Touch me</div>
<div id="hider"><div id="mover">This moves</div></div>
<div> dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate</div>
<div> dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate</div>
<div> dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate</div>
</body>
</html>
Any ideas what exactly is happening here? Or any workarrounds?
Upvotes: 1
Views: 2692
Reputation: 11
I just found a solve. It's a bit of a hack imho, but it worked for me. In the touchend event function, do a setTimeout that calls another function which does the animation.
$("div").bind("touchend",TouchEnd);
function TouchEnd (e)
{
timeout = setTimeout(runanimation, 10);
}
It's enough of a delay to avoid the issue of the jquery animate function ceasing to work in safari after touchend / scroll.
Upvotes: 0
Reputation: 190
As I was struggling with the same problem, I stumbled upon a Safari 'setTimeout bug'. It appears that Safari (under IOS6) doesn't execute animations or timers when scrolling. I have no idea why this influences animations after scrolling, but this guy wrote a little script that solved the problem for me. Be sure to check it out:
https://gist.github.com/3755461
I'm not 100% sure if it will cause errors in other browsers (didn't encounter any, yet), but it saved my day and I'm glad to share it with you.
Upvotes: 3
Reputation: 11
I can't duplicate the problem with your code, but I'm having a similar problem right now.
I have an overlay button that runs an animation on left position of an image, just for testing if .animate works.
I also have a touchend eventListener that calls a function which uses .animate to snap the img to a specific position after a touch.
The .animate function no longer works after safari has frozen the DOM to scroll, but everything else does, like .css for instance. Also, if the touchend listener function does not call .animate, the .animate function continues to work when pressing the overlay button after scroll.
I've gone thru the motions of simplifying my code, and still this problem persists. It's irrelevant if i use the js addEventListener or the jquery .bind. So I started slowly picking thru jquery code adding log statements (printing to a div in the page) and noticed that the jQuery.now() function stops returning the current date after scroll, which essentially runs a js function : new Date(). I'm wondering if it has something to do with safari freezing the DOM but I can't seem to find anything more. This does not appear to be happening on android.
What is weird to me at the moment while i look for answers is that in another js file, working in the same page, i can get the date after scroll.
I'm seeing that if the function called on the touchend event does not do an animation, the animate call on this button continues to work. Otherwise it does not.
The following url has a touchend event function that does NOT run .animate :
http://selfconstruc.tv/code/jquery-touchmove/test1.html
The following url has a touchend event function that DOES run .animate :
http://selfconstruc.tv/code/jquery-touchmove/test2.html
Upvotes: 0