В iOS8 с использованием .focus() отобразит виртуальную клавиатуру и прокрутку страницы после касания

До iOS8 использование метода Javascript .focus() на входном элементе не будет иметь эффекта (виртуальная клавиатура не будет отображаться). После последней версии iOS 8 запуск метода .focus(), казалось, не повлиял на загрузку страницы, но как только пользователь коснулся в любом месте экрана, виртуальная клавиатура мгновенно появится и прокрутит страницу до элемента в фокусе. (Это также проблема, когда я использую атрибут HTML "автофокус" )

Это изменение вызвало проблемы с пользователями iOS8 на моем сайте. Когда пользователь пытается щелкнуть кнопку на моей странице, внезапное появление прокрутки и клавиатуры заставляет их непреднамеренно нажать кнопку, которая была ниже на экране.

Я предполагаю, что это ошибка в iOS8 и не была преднамеренной функцией, мой вопрос - это то, что является наиболее эффективным решением для устранения этой проблемы?

Нужно ли проверять navigator.userAgent, чтобы узнать, является ли устройство iOS8, каждый раз, когда я использую метод .focus()?

Ответ 1

Похоже, вы определенно попали в ошибку iOS 8. В iOS7 Safari (по-видимому) игнорирует или удерживает несфокусированные элементы, у которых фокус установлен до загрузки страницы. Это включает как <input autofocus>, так и input.focus(), которые происходят до некоторой точки, возможно загрузка страницы (я тестировал только с встроенным script).

В iOS 8 Safari теперь, по-видимому, помнит, что элемент был сфокусирован, но фактически не фокусировал его до события touch down. Затем он слепо посылает событие щелчка на тот элемент, который получил прикосновение.

Оба браузера ведут себя одинаково для input.focus(), возникающих после загрузки страницы. Они оба приближаются к элементу и вызывают клавиатуру.

Тесты:

Хорошей новостью является то, что вам нужно только беспокоиться о новом поведении на элементах, которые вы хотите префокусировать. Другая хорошая новость заключается в том, что, хотя вам придется использовать обходной путь для пользователя, вы можете использовать его для всех версий iOS, поскольку они уже ведут себя так, как будто вы не автофокусировались:

if (!/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
    element.focus();
}

Это, по-видимому, подход http://www.google.com использует на основе базового тестирования пользовательского агента:

  • Mac Book Pro: автофокусировка перед загрузкой страницы.
  • iPhone: нет автофокуса
  • iPad: нет автофокуса
  • Kit Kat (Android): фокус после загрузки страницы, возможно, дополнительное обнаружение для наличия программной клавиатуры.

Если вы этого не сделали, вы должны пойти и подать радар с Apple на https://bugreport.apple.com.

Ответ 2

Если вы разрабатываете проект Cordova, вы можете исправить его, добавив эту строку

<preference name="KeyboardDisplayRequiresUserAction" value="false" />

в ваш config.xml файл. Протестировано в IOS 8.3 и IOS 8.4

Ответ 3

Кажется, что в iOS 8 было изменение API при обработке по умолчанию для команды javascript focus(). Если ваше приложение представляет собой гибридное приложение, в котором у вас есть прямой контроль над фасадом веб-представления Apple, ниже находится непосредственно из документов яблок.

Логическое значение, указывающее, может ли веб-контент программным путем отобразите клавиатуру.

[myWebView setKeyboardDisplayRequiresUserAction: YES];

Если для этого свойства установлено значение YES, пользователь должен явно нажать элементы в веб-представлении для отображения клавиатуры (или других соответствующих вид ввода) для этого элемента. Если установлено значение НЕТ, событие фокусировки на элемент вызывает отображение ввода и связан с этим элемент автоматически.

Значение по умолчанию для этого свойства: YES.

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

Кажется, что есть ошибка, так как этот метод не работает в настоящее время для меня. Текущее поведение, которое я получаю, соответствует, как будто по умолчанию оно равно NO.

Ответ 4

У меня есть решение:

  • Отключить все входы
  • Включить ввод, который вы хотите сфокусировать.
  • Установите фокус на этот вход
  • Включить все другие входы

Ответ 5

Здесь условная monkeypatch для jQuery.focus, поэтому вам не нужно добавлять тест userAgent везде.

JavaScript

if (/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
  (function($) {
    return $.fn.focus = function() {
      return arguments[0];
    };
  })(jQuery);
}

CoffeeScript

if /iPad|iPhone|iPod/g.test navigator.userAgent
  (($) ->
    $.fn.focus = ->
      arguments[0]
  )(jQuery)

Примечание. Я возвращаю arguments[0], поэтому мы не нарушаем цепочку методов, такую ​​как $(el).focus().doSomethingElse()

Ответ 6

Я зарегистрировал ошибку об этом в Apple Bug Reporter, и они закрыли ее как дубликат, что является признаком того, что они работают над исправлением этого. К сожалению, они не дали мне больше информации о дублирующем пункте или о самой проблеме. Я могу видеть только состояние дублирующегося элемента, которое открыто.