Подтвердить что ты не робот

Текстовое поле автофокуса Mobile Safari

В Mobile Safari я не могу сфокусироваться на текстовом поле после установки периода задержки. Проблема связана с некоторыми примерами кода. Если при нажатии кнопки вы запускаете .focus(), все работает так, как ожидалось. Если вы ведете фокус на обратном вызове, например, функцию setTimeout, тогда он не работает ТОЛЬКО в мобильном сафари. Во всех других браузерах есть задержка, затем происходит фокус.

Смутно, событие "focusin" запускается даже в мобильном сафари. Это (и ~ подобные ~ комментарии в SO) заставляют меня думать, что это ошибка мобильного сафари. Любые указания будут приняты.

Я тестировал в эмуляторе и на iPhone 3GS/4 iOS4.

Пример HTML:

<!DOCTYPE html> 
  <html lang='en'> 
    <head> 
      <title>Autofocus tests</title> 
      <meta content='width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0' name='viewport'> 
      <meta content='yes' name='apple-mobile-web-app-capable'> 
    </head> 
    <body>
      <h1> 
        Show keyboard without user focus and select text:
      </h1> 
      <p> 
        <button id='focus-test-button'> 
          Should focus on input when you click me after .5 second
        </button> 
        <input id='focus-test-input' type='number' value='20'> 
      </p> 
      <script type="text/javascript"> 
        //<![CDATA[
        var button = document.getElementById('focus-test-button');
        var input  = document.getElementById('focus-test-input');

        input.addEventListener('focusin', function(event) {
          console.log('focus');
          console.log(event);
        });

        button.addEventListener('click', function() {
          // *** If triggered immediately - functionality occurs as expected
          // input.focus();
          // *** If called by callback - triggers the focusin event, but does not bring up keyboard or cursor
          var t = setTimeout("input.focus();",500);
        });
        //]]>
      </script>
    </body>
  </html>

~ Подобные вопросы ~ SO:

4b9b3361

Ответ 1

Я думаю, что это особенность мобильного Safari, а не ошибка. В нашей работе над FastClick мои коллеги и я обнаружили, что iOS позволит только активировать фокус на других элементах, изнутри функции, если первая функция в стеке вызовов была вызвана не-программным событием. В вашем случае вызов setTimeout запускает новый стек вызовов, и механизм безопасности срабатывает, чтобы предотвратить установку фокуса на входе.

Помните, что при настройке iOS фокус на элементе ввода вызывает клавиатуру - поэтому все те веб-страницы, которые задают фокус на элементе ввода на загрузке страницы, например Google, будут крайне раздражать для использования на iOS. Я думаю, Apple решила, что им нужно что-то сделать, чтобы этого не случилось. Поэтому я не согласен с @DA: это особенность, а не ошибка.

Там нет известного способа обхода, поэтому вам придется отказаться от идеи использовать задержку.

Обновление Август 2012:

Как и в iOS 5, обработчики, инициируемые синтезированными событиями кликов, могут инициировать фокусировку на входных элементах. Попробуйте обновленный пример фокуса ввода FastClick.

Ответ 2

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

Ответ 3

Кажется, что focus() работает только, если вы добавили сайт на главный экран и открыли сайт с помощью этой ссылки.

Ответ 4

Добавление ответа Мэтта. По крайней мере, в Safari на iOS 5.1 эта проблема исправлена. Работает FastClick, т.е. Синтез события клика не приведет к сбою. Однако это не помогает людям, которые хотят, чтобы их один код focus() работал на всех версиях iOS, вздох.

Ответ 5

Я был способен сделать работу .focus(), присоединив ее к двум отдельным событиям на карте событий, но это своего рода хакерство.

После добавления FastClick.js, это то, что происходит в iOS:.focus() работает только тогда, когда его активирует функция, привязанная к событию. НО фокус также является событием в карте событий мобильного сафари, которое фактически вызывается при использовании jQuery.focus(). Таким образом, вы можете быть избыточным и приложить другой .focus() к событию фокуса объекта, чтобы убедиться, что он тянет. Это особенно хорошо работает при создании ввода в DOM. Мне нравится программировать для MeteorJS в последнее время, вот что выглядит в этом решении:

Template.templateName.events({
    "click button":function(){
        Session.set("makeButtonVisible",true);
        $("input.created").focus();
    },
    "focus input.created":function(){
        $("input.created").focus();
    }
});

Надеюсь, это полезно для кого-то там, взял меня, как два часа, чтобы понять это.

EDIT: Что ж, для MeteorJS, в частности, вы не можете использовать функцию Template.templateName.rendered либо потому, что .focus() должен быть вызван из события. НО по какой-то причине, когда вы добавляете ввод через jQuery, вы можете сосредоточиться на нем внутри события. Угадайте, что путь. Это то, что я закончил:

Template.templateName.events({
    "click button":function(){
        $("body").append("<input class='created' type='tel'>");
        $("input.created").focus();
    }
});

Ответ 6

Вы ответили сами. Вам нужно просто запустить, если вы используете JQuery. Изменить фокус() на триггере ( "фокус" ); в любой части вашего кода.

$( "# searchField" ) триггер ( "фокус" );.