UPDATE: The issue seems to stem from having many select elements on a page. How random is that?
So here's the issue. On iOS 7 Safari, when tapping the a text input on my site, the keyboard opens then freezes the OS for about 2-5 seconds then finally scrolls to the input. After this happens once, it never happens again until you refresh the page. I've looked all over the place, and yes, iOS 7 Safari is super buggy, but lets try and see if we can figure this out.
Note: This does not happen in any other mobile browser or any previous iOS Safari. It happens both on the ios 7 iphone and ios 7 ipad.
I will list everything my friend and I have tried so far:
- Removed the ability to add event handlers in jQuery. (Note: all our event handlers are assigned through jQuery except for unload and onpageshow).
- Removed the jQuery autocomplete script from the inputs.
- Removed all JavaScript from the inputs.
- Removed all third-party libraries being added on the page by rejecting the domains on the Mac.
- Switched back to previous jQuery versions. The last one we could actually use before nothing worked was 1.7.0.
- Switched back to previous jQuery UI versions.
- Changed input event handling to delegate and live, instead of on('click')
- Removed all CSS classes.
- Removed all CSS from the page. Note: The response time for the OS this went down to 1-2 seconds but still happened.
Does anyone have any ideas?
Thanks a bunch!
My answer might be slightly off the main topic, but I did arrive here after some searching as the scenario "feels" similar.
Issue:
My issue felt like a lockup in iOS, but not quite, since other elements on the page were still interactive. I had an
<input type="search" />
element, that would not focus when I clicked into the field. But it would eventually catch focus after about 4-5 taps on the screen.Additional Info:
My project is a hybrid app: WebView inside of an iOS app. The site is built with Twitter Bootstrap.
Solution:
I happened to also have the
autofocus
attribute set on the element. I tried removing that and it worked... no more consecutive taps to get the field to focus.(There are some somewhat-effective solutions, see near the end of the list)
At my company we are also suffering from this. We filed an issue with Apple but have heard mum.
Here are some interesting jsfiddles to help illustrate some of the issues, it definitely seems to revolve around the number of hidden fields, and textareas do not seem to be affected.
From debugging efforts, my guess is that there is some functionality trying to detect if an input is a credit card or phone number or some special kind which seems to cause the locking behavior. This is just one hypothesis though..
Summary:
On a page with a form containing named input elements inside containers that are marked "display: none", the first press on an input in that form has a very noticeable delay (20sec-2min) between the keyboard coming up and the input being focused. This prevents users from using our web app due to the enormous time spent with the ui frozen waiting for the keyboard to respond. We have debugged it in various scenarios to try and discern what is going on, and it appears to be from a change in how iOS7 parses the DOM versus how it did on iOS6, which has none of these issues.
From debugging within Safari's Inspector with the iPad connected, we found that iOS7 provides much more information about the (program)'s activities, to the point that we found that _CollectFormMetaData is the parent of the problem. Searching for meta data causes massive churn that increases more than linearly along with the number of hidden containers containing inputs. We found that _isVisible and _isRenderedFormElement are called far more than they reasonably should be. Additionally, if it helps, we found some detection functions relating to credit cards and address books were large time consumers.
Here are some jsFiddles for illustration. Please view them in Safari on an iPad running iOS6 and then on an iPad running iOS7:
http://jsfiddle.net/gUDvL/20/ - Runs fine on both
http://jsfiddle.net/gUDvL/21/ - Just noticeable delay on iOS 7
http://jsfiddle.net/gUDvL/22/ - More noticeable delay on iOS 7
http://jsfiddle.net/gUDvL/29/ - VERY noticeable delay on iOS 7
http://jsfiddle.net/gUDvL/30/ - Same as 29 but with none hidden - no delay on iOS 7
http://jsfiddle.net/gUDvL/38/ - Same as 29 but further exacerbated
http://jsfiddle.net/gUDvL/39/ - 99 hidden inputs, one visible, one separately visible
http://jsfiddle.net/gUDvL/40/ - 99 hidden textareas, one visible, one separately visible
http://jsfiddle.net/gUDvL/41/ - 99 hidden inputs, one visible, one separately visible, all with the autocomplete="off" attribute
http://jsfiddle.net/gUDvL/42/ - 99 hidden inputs, one visible, one separately visible. Hidden by position absolute and left instead of display.
http://jsfiddle.net/gUDvL/63/ - Same as gUDvL/43/ but with autocomplete, autocorrect, autocapitalize, and spellcheck off
http://jsfiddle.net/gUDvL/65/ - Same as gUDvL/63/ but with cleaned up indentation (seems slower on iPad)
http://jsfiddle.net/gUDvL/66/ - Same as gUDvL/65/ but with display none via css again instead of DOMReady jQuery
http://jsfiddle.net/gUDvL/67/ - Same as gUDvL/66/ but with TedGrav's focus/blur technique
http://jsfiddle.net/gUDvL/68/ - Same as gUDvL/66/ but with css driven text-indent instead of display:block again (noticeable improvement - reduction to 2-3 secs for initial focus)
http://jsfiddle.net/gUDvL/69/ - Same as gUDvL/68/ but with TedGrav's focus/blur re-added
http://jsfiddle.net/gUDvL/71/ - Same as gUDvL/66/ but with js adding a legend tag before each input. (noticeable improvement - reduction to 2-3 secs for initial focus)
(We should note that having the iPad connected to a Mac with Safari's debugger engaged dramatically emphasizes the delays.)
Steps to Reproduce:
Expected Results:
Expect to be able to type as soon as the keyboard pops up
Actual Results:
Watch the keyboard pop up and the screen freeze, unable to scroll or interact with Safari for a duration. After the duration, focus is given as expected. From then on no further freezes are experienced when focusing on inputs.
tl;dr technique summary
So overall there are a couple proposed fixes from various answers:
Related threads at Apple:
https://discussions.apple.com/thread/5468360
There seems to be a problem with how IOS handles the touch-event for inputs and textareas. The delay gets larger when the DOM gets larger. There is however not a problem with the focus event!
To work around this problem you can override the touchend event and set focus to the input/textarea.
This will however create a new problem. It will let you scroll the page while touching the input/textarea, but when you let go, the site will scroll back to the original position.
To fix this, you just need to check if any scrolling has occured, and surround the preventDefault and target.focus with an if statement.
To set the original position, you can use the touchstart event.
EDIT Me and a colleague have improved it a little bit, and it works like a charm.
I have the same
freezeing
problem.I am not sure we're in the same situation.
here is my demo:http://tedzhou.github.io/demo/ios7sucks.html
In my page, i use a
<p>
element withonclick
attribute as a button. When user click on the button, page change to atextarea
. Then a click on it will freezes the browser.The time freezing spent relevent to the numbers of the dom elements. In my pages, there are 10000 elements, which make it freeze by 10+ seconds.
We can solve the problem by switching the
<p>
element to the real<button>
, or reducing the nums of dom elements.ps: sorry for my poor english. LOL
The main issue for me was with hidden fields. Made the form hang for 10-15 seconds.
I managed to get around by positioning the hidden form fields off the screen.
To hide:
To show:
It happens not only in iOS but in safari 7 for MAC OS (Maverics) too, I have found that the problem happens when you use a lot of div tags to contain inputs (or selects) within a form:
I changed the layout of my selects to use ul/li and fieldsets instead of divs and the freezze time was reduced drastically.
Here are two examples in jsfiddle:
freezze for 5 seconds
http://jsfiddle.net/k3j5v/5/
freeze for 1 second
http://jsfiddle.net/k3j5v/6/
I hope it might help someone