IOS 7 Safari: OS блокируется в течение 4 секунд, когда щелчок/фокусировка на вводе HTML

ОБНОВЛЕНИЕ: проблема, похоже, связана с наличием множества элементов на странице. Насколько случайным является это?

Итак, вот проблема. На iOS 7 Safari при нажатии на текстовый ввод на моем сайте открывается клавиатура, а затем замораживает ОС примерно на 2-5 секунд, а затем прокручивается на вход. После этого произойдет один раз, это никогда не повторится, пока вы не обновите страницу. Я смотрел повсюду, и да, iOS 7 Safari супер глючит, но давайте посмотрим, сможем ли мы это понять.

Примечание. Это не происходит ни в каком другом мобильном браузере или в любом предыдущем iOS Safari. Это происходит как на iOS 7 iphone, так и на ios 7 ipad.

Я перечислил все, что мой друг и я пробовал до сих пор:

  • Удалена возможность добавления обработчиков событий в jQuery. (Примечание: все наши обработчики событий назначаются через jQuery, за исключением выгрузки и onpageshow).
  • Удалено автозаполнение jQuery script с входов.
  • Удалены все JavaScript из входов.
  • Удалены все сторонние библиотеки, которые добавляются на страницу, отклоняя домены на Mac.
  • Переключился на предыдущие версии jQuery. Последнее, что мы могли бы использовать до того, как ничего не получилось, было 1.7.0.
  • Переключился на предыдущие версии пользовательского интерфейса jQuery.
  • Изменена обработка входных событий, чтобы делегировать и жить, а не на ('click')
  • Удалены все классы CSS.
  • Удалены все CSS со страницы. Примечание. Время отклика для ОС снизилось до 1-2 секунд, но все же произошло.

Есть ли у кого-нибудь идеи?

Спасибо, куча!

Ответ 1

(Есть несколько эффективных решений, см. в конце списка)

В моей компании мы также страдаем от этого. Мы подали иск с Apple, но слышали маму.

Вот некоторые интересные jsfiddles, которые помогут проиллюстрировать некоторые из проблем, он определенно вращается вокруг количества скрытых полей, и текстовые поля не кажутся затронутыми.

От усилий по отладке, я предполагаю, что есть некоторые функции, пытаясь определить, является ли вход кредитной карточкой или номером телефона или каким-то особым видом, который, по-видимому, вызывает поведение блокировки. Это всего лишь одна гипотеза, хотя..

Резюме:

На странице с формой, содержащей именованные элементы ввода внутри контейнеров, которые помечены как "display: none", первое нажатие на вход в этой форме имеет очень заметную задержку (20 секунд-2 мин) между клавиатурой, идущей вверх и вход фокусируется. Это не позволяет пользователям использовать наше веб-приложение из-за огромного времени, затраченного на перезагрузку ui, ожидая ответа клавиатуры. Мы отлаживали его в различных сценариях, чтобы попытаться понять, что происходит, и, похоже, это связано с изменением того, как iOS7 анализирует DOM по сравнению с тем, как это произошло на iOS6, и ни одна из этих проблем не имеет.

Из отладки в Safari Inspector с подключенным iPad мы обнаружили, что iOS7 предоставляет гораздо больше информации о (программных) действиях, до такой степени, что мы обнаружили, что _CollectFormMetaData является родителем проблемы. Поиск метаданных приводит к массивному оттоку, который увеличивается более чем линейно, а также количеству скрытых контейнеров, содержащих входы. Мы обнаружили, что _isVisible и _isRenderedFormElement вызываются намного больше, чем они должны быть разумно. Кроме того, если это помогает, мы обнаружили, что некоторые функции обнаружения, относящиеся к кредитным картам, и адресные книги были крупными потребителями времени.

Вот некоторые иллюстрации jsFiddles для иллюстрации. Пожалуйста, просмотрите их в Safari на iPad под управлением iOS6, а затем на iPad под управлением iOS7:

http://jsfiddle.net/gUDvL/20/ - отлично работает на

http://jsfiddle.net/gUDvL/21/ - Просто заметная задержка на iOS 7

http://jsfiddle.net/gUDvL/22/ - Более заметная задержка на iOS 7

http://jsfiddle.net/gUDvL/29/ - ОЧЕНЬ заметная задержка на iOS 7

http://jsfiddle.net/gUDvL/30/ - То же, что и 29, но ни с чем не скрытое - без задержки на iOS 7

http://jsfiddle.net/gUDvL/38/ - То же, что и 29, но еще более усугубляется

http://jsfiddle.net/gUDvL/39/ - 99 скрытых входов, один видимый, один отдельно видимый

http://jsfiddle.net/gUDvL/40/ - 99 скрытых текстовых областей, один видимый, один отдельно видимый

http://jsfiddle.net/gUDvL/41/ - 99 скрытых входов, один видимый, один отдельно видимый, все с атрибутом autocomplete = "off"

http://jsfiddle.net/gUDvL/42/ - 99 скрытых входов, один видимый, один отдельно видимый. Скрывается положением абсолютным и левым, а не дисплеем.

http://jsfiddle.net/gUDvL/63/ - То же, что и gUDvL/43/, но с автозаполнением, автокоррекцией, автокапитализацией и орфографической проверкой

http://jsfiddle.net/gUDvL/65/ - То же, что и gUDvL/63/, но с очищенным отступом (кажется медленнее на iPad)

http://jsfiddle.net/gUDvL/66/ - То же, что и gUDvL/65/, но с отображением none через css снова вместо DOMReady jQuery

http://jsfiddle.net/gUDvL/67/ - То же, что и gUDvL/66/, но с техникой фокусировки/размывания TedGrav

http://jsfiddle.net/gUDvL/68/ - То же, что и gUDvL/66/, но с текстовым отступом css, а не с отображением: снова блок (заметное улучшение - уменьшение до 2 -3 сек для начальной фокусировки)

http://jsfiddle.net/gUDvL/69/ - То же, что и gUDvL/68/, но с повторным добавлением фокуса/размытия TedGrav

http://jsfiddle.net/gUDvL/71/ - То же, что и gUDvL/66/, но с js, добавляющим тег легенды перед каждым входом. (заметное улучшение - сокращение до 2-3 секунд для начальной фокусировки)

<input type="text" autocomplete="off" /> (links to jsfiddle.net must be accompanied by code..)

(Следует отметить, что при подключении iPad к Mac с отладчиком Safari резко подчеркивается задержка.)

Шаги по воспроизведению:

  • Загрузите любой из вышеперечисленных jsfiddles на iPad.
  • Нажмите кнопку ввода для фокусировки
  • Наблюдать за экраном, пока вы не наберете

Ожидаемые результаты:

Ожидайте, что сможете набирать, как только клавиатура появится.

Фактические результаты:

Наблюдайте за появлением клавиатуры и замораживанием экрана, не можете прокручивать или взаимодействовать с Safari в течение продолжительности. После продолжительности фокус задается, как и ожидалось. С этого момента больше не происходит зависаний при фокусировке на входах.

tl; описание техники

Итак, в целом есть пара предлагаемых исправлений из разных ответов:

  • Не скрывайте divs с отображением: none - используйте что-то вроде text-indent
  • Короткое замыкание Логика сканирования метаданных Apple - многие теги формы или теги легенд, похоже, делают трюк
  • Автофокус/размытие - не работало для меня, но два человека сообщили, что он сделал

Связанные темы в Apple:

https://discussions.apple.com/thread/5468360

Ответ 2

Кажется, что проблема связана с тем, как IOS обрабатывает сенсорное событие для входов и текстовых полей. Задержка увеличивается, когда DOM становится больше. Однако в фокусном событии нет проблем!

Чтобы обойти эту проблему, вы можете переопределить событие touchhend и установить фокус на вход/текстовую область.

document.addEventListener("touchend", function (e) {  
     if (e.target.nodeName.toString().toUpperCase() == 'INPUT' || e.target.nodeName.toString().toUpperCase() == 'TEXTAREA') {  
         e.preventDefault(); 
         e.target.focus(); 
     } 
});

Однако это создаст новую проблему. Это позволит вам прокручивать страницу при касании ввода /textarea, но когда вы отпустите, сайт вернется в исходное положение.

Чтобы исправить это, вам просто нужно проверить, произошла ли какая-либо прокрутка, и окружить функции preventDefault и target.focus инструкциями if.

Чтобы установить исходное положение, вы можете использовать событие touchstart.

document.addEventListener("touchstart", function (e) {
    ... //store the scrollTop or offsetHeight position and compare it in touchend event.
}

EDIT Я и его коллега немного улучшили его, и это работает как шарм.

var scroll = 0; 
document.addEventListener("touchstart", function (e) { 
    scroll = document.body.scrollTop; 
 });   

document.addEventListener("touchend", function (e) { 
    if (scroll == document.body.scrollTop) { 
        var node = e.target.nodeName.toString().toUpperCase(); 
        if (node == 'INPUT' || node == 'TEXTAREA' || node == 'SELECT') { 
            e.preventDefault(); 
            e.target.focus(); 
            if(node != 'SELECT') {
                var textLength = e.target.value.length; 
                e.target.setSelectionRange(textLength, textLength);
            }
        } 
    } 
}); 

Ответ 3

У меня такая же проблема freezeing.

Я не уверен, что мы в той же ситуации.

вот моя демонстрация: http://tedzhou.github.io/demo/ios7sucks.html

На моей странице я использую элемент <p> с атрибутом onclick в качестве кнопки. Когда пользователь нажмет на кнопку, измените страницу на textarea. Затем щелчок по нему заморозит браузер.

Время замораживания, уходящее в соответствие с числами элементов dom. На моих страницах есть 10000 элементов, которые заставляют замораживаться на 10 + секунд.

Мы можем решить проблему, переключив элемент <p> на реальный <button> или уменьшив число элементов dom.

ps: извините за мой бедный английский. LOL

Ответ 4

Основная проблема для меня была со скрытыми полями. Заменили форму на 10-15 секунд.

Мне удалось обойтись, разместив скрытые поля формы на экране.


Чтобы скрыть:

position: absolute;
left: -9999px;

Чтобы показать:

position: relative;
left: 0;

Ответ 5

Борьба с этой проблемой также в полноэкранном режиме ios, который вставлял/удалял страницы, содержащие один элемент ввода. Был задержан до 30 секунд с единственным видимым элементом ввода текста на странице (и внутри всей DOM). Другие динамически вставленные страницы с одним или несколькими текстовыми входами в том же webapp не испытывали задержки ввода. Как уже упоминалось, после начальной задержки поле ввода будет вести себя нормально при последующих событиях фокусировки (даже если динамическая страница, содержащая элемент ввода, была удалена из DOM, затем динамически повторно отображена/вставлена ​​обратно в DOM).

В ожидании, основанном на вышеприведенном поведении, попробуйте следующее при загрузке страницы:

.

$( "# проблемно-вход" ) фокус(); $ ( "# Проблема-вход" ) размытие();.

В то время как вышеупомянутое выполняется немедленно без задержки, конечный результат не является последующим задержек, когда вход получает фокус через взаимодействие пользователя. Не могу объяснить причину этой работы, но, похоже, она работает последовательно для моего приложения, а другие предлагаемые исправления не удались.

Ответ 6

Встретил ту же проблему в довольно сложном приложении, имеющем много входов.

Отключенный отладчик для Safari iOS7 через USB и зарегистрированные события пользовательского интерфейса. Я вижу событие "touchhend", как только я нажимаю на textarea (или любой ввод), и через 10-20 секунд после этого я вижу "click", который отправляется.

Очевидно, что это ошибка в Safary, как на других устройствах, таких как Android или iOS6, нет проблем с тем же самым приложением.

Ответ 7

Это происходит не только в iOS, но и в сафари 7 для MAC OS (Maverics), я обнаружил, что проблема возникает, когда вы используете множество тегов div, чтобы содержать входы (или выбираемые) в форме:

<div> <select>...</select> </div>
<div> <select>...</select> </div>
...

Я изменил макет моих настроек, чтобы использовать ul/li и fieldsets вместо divs, и время замораживания резко сократилось.

<ul>
   <li><select>...</select></div>
   <li><select>...</select></div>
</ul>

Вот два примера в jsfiddle:

замораживание в течение 5 секунд

http://jsfiddle.net/k3j5v/5/

заморозить в течение 1 секунды

http://jsfiddle.net/k3j5v/6/

Я надеюсь, что это может помочь кому-то

Ответ 8

Для меня эта проблема вызвана тем, что пользовательские входы скрыты на странице с помощью display:none.

Обходной путь, который я использовал: вместо того, чтобы скрывать входы с помощью display:none, я использовал метод jQuery detach() на документе, готовый "скрыть" все пользовательские входы, которые не использовались. Затем append() входы, когда они были необходимы.

Таким образом, никакие входы не имели display:none, когда страница была впервые загружена, и поэтому при первоначальном взаимодействии с пользователем не было задержки.

Ответ 9

У нас была такая же или аналогичная проблема в моей компании. Всякий раз, когда мы показывали большое количество выпадающих списков, а затем пользователь щелкал на выпадающем списке, IOS 7 задерживала страницу на минуту или две. После размораживания все будет работать должным образом с этого момента.

Это повлияло на все типы ввода. Большое количество выпадающих объектов было фактически спрятано при первой загрузке - пользователь инициировал отображение выпадающих списков. До тех пор, пока не отобразится ниспадающее меню, все будет работать нормально. Как только они будут отображаться, следующий щелчок ввода, даже вход, который работал правильно, теперь заставит браузер замораживаться.

Как отмечали другие, кажется, что IOS 7 имеет проблему при анализе видимых входов в DOM после того, как пользователь сначала взаимодействует с входом. Когда число и/или сложность элементов/параметров/DOM выше, замораживание более выражено.

Поскольку он всегда зависел от первоначального взаимодействия с пользователем, мы решили инициировать скрытое действие пользователя, как только мы отобразили список выпадающих списков. Мы создали прозрачную кнопку (она не может быть скрыта - она ​​должна быть "отображена" ) и инициировала щелчок по ней, как только пользователь открыл раскрывающийся список. Мы думали, что это заставит IOS начать синтаксический анализ DOM быстрее, но обнаружил, что он фактически полностью устранил проблему.

Ответ 10

Я столкнулся с этой проблемой, так как заметил, что у многих людей по-прежнему возникают проблемы с этим, я думал, что положу свое решение.

В основном мое решение - это скрытие элементов на стороне сервера. Моя страница - ASP.NET, поэтому я завернул свои divs входы с помощью панелей и установил эти панели как Visible false. Таким образом, если я нажимаю на вход, сафари не могут видеть все остальные элементы управления, так как они скрыты на стороне сервера.

Конечно, если вы хотите сделать эту работу немного похожей на clientide jquery, вам понадобится автоматическая обратная передача и панель обновления где-нибудь. Это решение требует усилий, но все же лучше, чем на самом деле пытается исправить ошибку сафари.

Надеюсь, что это поможет.

Ответ 11

Мой ответ может быть немного от основной темы, но я пришел сюда после некоторого поиска, так как сценарий "чувствует" похоже.

Вопрос:

Моя проблема была похожа на блокировку в iOS, но не совсем, поскольку другие элементы на странице все еще были интерактивными. У меня был элемент <input type="search" />, который не фокусировался бы при нажатии на поле. Но это в конечном итоге уловило бы фокус после примерно 4-5 кранов на экране.

Дополнительная информация:

Мой проект - это гибридное приложение: WebView внутри приложения iOS. Сайт построен с Twitter Bootstrap.

Решение:

У меня также был атрибут autofocus, установленный в элементе. Я попытался удалить это, и он работал... не более последовательных кранов, чтобы получить поле для фокусировки.

Ответ 12

Вы пытались отключить "Пароль и автозаполнение" > "Кредитные карты" в настройках Safari? После этой операции он работает нормально. Это не окончательное решение, но, возможно, проблема в iOS.