iOS 7 fullscreen web app delay in firing javascript touchend - javascript

I have a standalone web application that used to work fine with iOS 6.
With iOS 7 I noticed that there is a significant delay (several seconds) in firing the javascript touchend event after a finger swipe. The behavior is not consistent, sometimes the first swipe generates the event immediately and only the following ones are delayed.
Is this a known issue and/or there is a workaround?
Thanks.

I was experiencing this same problem with an HTML5 game I'm developing. Sometimes the touchend would seem to fire immediately, and other times there would be a delay of several seconds before it fired.
I stumbled upon this post reminding me of the setTimeout 0 trick for pushing a block of javascript onto the queue for later processing. I was doing a bit of "heavy-lifting" (some DOM manipulation) inside the touchend event handler, and this appeared to disrupt its firing.
I wrapped the code inside my touchend handler with a setTimeout, and that eliminated the delay:
$(document).on('touchend', function (e) {
setTimeout(function(){
//do stuff here...
}, 0);
});

Safari on iOS 7 and HTML5: problems, changes and new APIs: http://www.mobilexweb.com/blog/safari-ios7-html5-problems-apis-review

iOS 7.1 seems to fix this issue; touchend events fire properly (even without the zero timeout)

Related

PinchZoom.js not working on iOS devices after 13.4 update by Apple

So I have run into a problem again with this plugin- PinchZoom.js which started happening after the 13.4 update by Apple for iOS devices.
The problem is that the double tap feature has suddenly stopped working completely on iOS devices now.
For a concrete test, you can refer to the plugin demo page: http://manuelstofer.github.io/pinchzoom/demo/pinchzoom.html
On iOS devices, you won't be able to double tap to zoom in the image whereas this was working fine in previous versions of iOS.
I have even dived down in the source code of the plugin but I am not sure what is causing the double tap TO NOT work in iOS devices after the update.
If anyone has any idea/workaround for this, it would be very helpful.
Thanks
On all browsers there used to be a delay of 300-350ms on touchstart events. Apparently, on iOS there still is. You can test this by logging tap events and time in the touchstart event listener.
And for your issue, you could either solve it by modifying pinchzoom.js to use touchend which has no delay instead of touchstart, or by preventing default behaviour on the touchstart.
I chose the latter and added event.preventDefault() to the touchstart event listener. You can do that too, until the developer provides an official solution.
el.addEventListener('touchstart', function (event) {
event.preventDefault(); //add this
if (target.enabled) {
firstMove = true;
fingers = event.touches.length;
detectDoubleTap(event);
}
});

offlineAudioContext.oncomplete never fires after running startRendering() on iOS

The oncomplete event of the webkitOfflineAudioContext never fires after running the context's startRendering() method. Even with a fix for iOS's requirement of a touch event to initiate sound.
Example jsfiddle here: https://jsfiddle.net/9kpdjk2y/16/
Note that running this fiddle in Chrome, Firefox etc will result in a success message being appended below the button. On iOS this event is never fired and so the renderedBuffer can never be accessed.
This is driving me crazy, am I overlooking something?
Tested on iPhone 6, iPhone 6s on iOS 9. Not tested on iOS 10 yet.
Most likely the iOS version of WebAudio does not support the oncomplete event. This is a relatively new addition to WebAudio.

Why is touchstart event after click?

Here's something odd, that I felt sure was working in earlier mobile browsers: In Chrome on Android, and Safari on iOS, it seems the touchstart event is fired after the click event, not before. When did this change?
A simple example:
jQuery(function($) {
var touched = false;
$('#clicky').on('touchstart', function(evt){
touched = true;
evt.preventDefault();
})
.click(function(){
if (!touched) {
alert("somehow touch didn't fire")
}
});
})
Run this fiddle, and you'll see the alert can pop up on Android and iOS, when it should actually never show!
http://jsfiddle.net/quxnxu7d/2/
I ran it through Chrome on Android and it worked as you expected for me. I added an alert to the touchstart handler and it fired to be sure that it was firing first and it did.
Take a look at the touch events mdn article. The article specifically mentions:
calling preventDefault() on a touchstart or the first touchmove event of a series prevents the corresponding mouse events from firing
Click is a mouse event so it "should" work as you expect (and it was working for me). I'd verify that the events are indeed running out of order (use console.log() instead of alert()) on your target browsers. If they are, which is perfectly possible with less than perfect browsers/specs, try using a different mouse event like mouseup. My guess is that you'll be able to find an event that works consistently.
Good luck!
Have you tried using mousedown instead of click? That way you should get different events for touch and click without any double firing. You will also likely need to use keydown to keep this site accessible.
There is a 300ms delay between a physical tap and the firing of a click event on some mobile browsers (e.g. iOS Safari)
I ran into the same issue and FastClick jQuery plugin fixed it for me
Have a look FastClick

Javascript Drag and drop in windows phone 7.5

I'm trying to get drag and drop functionality to work in a windows 7.5 phone.
Initially i tried using the jquery ui draggable which worked in all browsers except windows 7.5.
Later on exploring further, i found out that there are no touchstart, touchend and touchmove events in windows.
So i tried getting it to work using mousedown, mousemove events which shockingly were firing. But they donot fire in a proper sequence. (mousemove fires before mousedown).
Nor did the dragstart and dragend events work.
I need to get this to work. Do you have any suggestions ?
/*Eg1:does not work*/
$("#draggable").draggable();
/*Eg2:This event does not fire*/
$("#draggable").bind("touchstart touchmove touchend", function(){
alert("touch events supported");})
/*Eg3: In this case, mousemove fires before mousedown.*/
$("#draggable").bind("mousedown", function(){
alert("mousedown");});
$("#draggable").bind("mousemove", function(){
alert("mousemove");});
I only have experience working with Javascript in Windows Phone 8 which uses IE 10 (as opposed to IE 9 in WP7.5 and WP7.8) but you could give my approach a try.
In WP8 (IE10) Microsoft supports the pointer events MSPointerUp MSPointerMove MSPointerDown instead of touchstart, touchmove and touchend events. Try using these to see if they work.
In the example I had created, however, I did not even need to use those proprietary events as IE 10 happily used the standard mouse events (mouseup mousemove mousedown) and worked well to an extent. I did not have any problem with the order of events (like you stated in the question). The main problem that arose for me while dragging was that the mousemove event stopped being triggered (by the browser) and the browser instead started panning the page leaving my dragged elements in limbo state (no mousemove or mouseup triggered). Using event.preventDefault() did not help either as it did not prevent the page from panning. To overcome this problem I went through Microsoft's documentation about their touch events and came across this CSS line.
-ms-touch-action: none;
I applied this on my elements to be dragged and my problem was solved. You can read all about the above proprietary CSS property here. Be careful not to apply this property to the entire body of the page (I had done that earlier) as it prevents the default browser behaviour of page panning and zooming. As I said apply it only on the elements to be dragged and it works.
Yet again this is my experience for WP 8. I do not know if it works for previous versions of Windows Phone.

iOS 6 js events function not called if has setTimeout in it

I noticed this strange behaviour with the latest iOS (iOS 6). If calling a function for any touch event which has a setTimeout inside, the part inside the setTimeout is never triggered.
This happens only when there is a "system animation" such as scroll and zoom-in/out.
For example:
http://jsfiddle.net/p4SdL/2/
(I used jquery just for testing but the same happens with pure js)
Open that page with safari on any iOS 6 device and zoom in or out. The alert will never be called.
If tested on any iOS 5 device this will work just fine! It seems that during these animations the setTimeout or setInterval are reset by the OS. Is this the intended behaviour or a bug?
Thanks
Note: It looks like UIWebView does not support requestAnimationFrames. Thanks to Guillaume Gendre for pointing it out!
We ran into a similar issue with a web app we're working on.
For us, it was touchmove that caused issues. We implemented a workaround (found here: https://gist.github.com/3755461) that seemed to work pretty well until another issue forced us to abandon it. (I tried adding the workaround to your fiddle and was able to get the timer to fire once or twice, but it required a weird gesture+scroll event that was damn near impossible to consistently reproduce.)
Anyway, one of the new features in iOS 6 for developers are requestAnimationFrames. My workaround is basically a wrapper for timers, allowing the developer to pass a boolean, which will call either the native function or the workaround function.
For example:
setTimeout(function(){alert("HI")}, 1000); // using native
setTimeout(function(){alert("HI")}, 1000, true); // using workaround
Here are additional ways to use the workaround:
setInterval(function(){console.log("Interval")}, 1000, true);
var timer = setTimeout(function(){ /* ... */ }, 60000, true);
clearTimeout(timer);
var interval = setInterval(someFunc, 10000, true);
if(someCondition) clearInterval(interval);
Here are two fiddles with the workaround examples. Try pinch/zooming on the black squares:
http://jsfiddle.net/xKh5m/embedded/result (Uses native setTimeout function)
http://jsfiddle.net/ujxE3/embedded/result
We've been using this workaround for a few months in a production environment, and have not run into any major issues.
Here's a public gist of the workaround: https://gist.github.com/4180482
Here's more information about requestAnimationFrames:
MDN documentation
Paul Irish on requestAnimationFrame
Good luck!

Categories