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

Мобильный Safari: метод javascript focus() на входном поле работает только с кликом?

Я не могу найти решение этой проблемы.

У меня есть простое поле ввода, подобное этому.

<div class="search">
   <input type="text" value="y u no work"/>
</div>​

И я пытаюсь focus() внутри функции. Таким образом, внутри случайной функции (неважно, какая функция она есть) У меня есть эта строка...

$('.search').find('input').focus();

Это прекрасно работает на любом рабочем столе.

Однако он не работает на моем iPhone. Поле не фокусируется, и клавиатура не отображается на моем iPhone.

В целях тестирования и чтобы показать вам, ребята, я сделал быстрый пример:

$('#some-test-element').click(function() {
  $('.search').find('input').focus(); // works well on my iPhone - Keyboard slides in
});

setTimeout(function() {
  //alert('test'); //works
  $('.search').find('input').focus(); // doesn't work on my iPhone - works on Desktop
}, 5000);​

Любая идея, почему focus() не будет работать с функцией тайм-аута на моем iPhone.

Чтобы увидеть живой пример, проверьте эту скрипту на своем iPhone. http://jsfiddle.net/Hc4sT/

Update:

Я создал тот же случай, что и в моем текущем проекте.

У меня есть select-box, который должен - когда "изменить" - установить фокус на поле ввода и вставить kexboard на iphone или другие мобильные устройства. Я узнал, что focus() установлен правильно, но клавиатура не отображается. Мне нужна клавиатура для отображения.

Я загрузил тестовые файлы прямо здесь http://cl.ly/1d210x1W3Y3W... Если вы проверите это на iphone, вы увидите, что клавиатура не слайд- в.

4b9b3361

Ответ 1

Собственно, ребята, есть способ. Я изо всех сил пытался понять это для http://forstartersapp.com (попробуйте на iPhone или iPad).

В принципе, Safari на устройствах с сенсорным экраном скупо, когда дело доходит до текстовых полей focus(). Даже некоторые настольные браузеры лучше, если вы делаете click().focus(). Но разработчики Safari на устройствах с сенсорным экраном поняли, что это раздражает пользователей, когда клавиатура продолжает подниматься, поэтому они сделали фокус только при следующих условиях:

1) Пользователь нажал где-то и focus() был вызван во время выполнения события click. Если вы выполняете вызов AJAX, вы должны сделать это синхронно, например, с устаревшей (но все еще доступной) опцией $.ajax({async:false}) в jQuery.

2) Кроме того - и это заставляло меня заняться какое-то время - focus() по-прежнему не работает, если в то время сосредоточено какое-то другое текстовое поле. У меня была кнопка "Перейти", в которой был AJAX, поэтому я попытался размыть текстовое поле в событии touchstart кнопки Go, но это просто заставило клавиатуру исчезнуть и переместило видовое окно, прежде чем у меня появилась возможность завершить клик на кнопку Go. Наконец, я попытался размыть текстовое поле в событии touchend кнопки Go, и это сработало как шарм!

Когда вы ставите # 1 и # 2 вместе, вы получаете магический результат, который будет устанавливать ваши формы входа отдельно от всех испорченных форм входа в систему, помещая фокус в свои поля пароля и заставляя их чувствовать себя более родными. Наслаждайтесь!:)

Ответ 2

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

редактировать:

Здесь скрипка с тем же кодом. Очевидно, вы не можете запускать прикрепленные фрагменты на мобильных телефонах (или я делаю что-то не так).

var $triggerCheckbox = $("#trigger-checkbox");
var $targetInput = $("#target-input");

// Create fake & invisible input
var $fakeInput = $("<input type='text' />")
  .css({
    position: "absolute",
    width: $targetInput.outerWidth(), // zoom properly (iOS)
    height: 0, // hide cursor (font-size: 0 will zoom to quarks level) (iOS)
    opacity: 0, // make input transparent :]
  });

var delay = 2000; // That crazy long, but good as an example

$triggerCheckbox.on("change", function(event) {
  // Disable input when unchecking trigger checkbox (presentational purpose)
  if (!event.target.checked) {
    return $targetInput
      .attr("disabled", true)
      .attr("placeholder", "I'm disabled");
  }

  // Prepend to target input container and focus fake input
  $fakeInput.prependTo("#container").focus();

  // Update placeholder (presentational purpose)
  $targetInput.attr("placeholder", "Wait for it...");

  // setTimeout, fetch or any async action will work
  setTimeout(function() {

    // Shift focus to target input
    $targetInput
      .attr("disabled", false)
      .attr("placeholder", "I'm alive!")
      .focus();

    // Remove fake input - no need to keep it in DOM
    $fakeInput.remove();
  }, delay);
});
label {
  display: block;
  margin-top: 20px;
}

input {
  box-sizing: border-box;
  font-size: inherit;
}

#container {
  position: relative;
}

#target-input {
  width: 250px;
  padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="container">
  <input type="text" id="target-input" placeholder="I'm disabled" />

  <label>
    <input type="checkbox" id="trigger-checkbox" />
    focus with setTimetout
   </label>
</div>

Ответ 3

Мне удалось заставить его работать со следующим кодом:

event.preventDefault();
timeout(function () {
    $inputToFocus.focus();
}, 500);

Я использую AngularJS, поэтому я создал директиву, которая решила мою проблему:

Директива

angular.module('directivesModule').directive('focusOnClear', [
    '$timeout',
    function (timeout) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                var id = attrs.focusOnClear;
                var $inputSearchElement = $(element).parent().find('#' + id);
                element.on('click', function (event) {
                    event.preventDefault();
                    timeout(function () {
                        $inputSearchElement.focus();
                    }, 500);
                });
            }
        };
    }
]);

Как использовать директиву:

<div>
    <input type="search" id="search">
    <i class="icon-clear" ng-click="clearSearchTerm()" focus-on-clear="search"></i>
</div>

Похоже, вы используете jQuery, поэтому я не знаю, является ли директива какой-либо помощью.

Ответ 4

У меня есть форма поиска со значком, который очищает текст при нажатии. Однако проблема (на мобильных устройствах и планшетах) заключалась в том, что клавиатура рухнула/спряталась, поскольку удаленное событие click удалено focus было удалено из input.

text search input with close icon

Цель: очистка формы поиска (нажатие/нажатие на значок x) сохранить видимость клавиатуры!

Чтобы выполнить это, примените stopPropagation() к событию так:

function clear ($event) {
    $event.preventDefault();
    $event.stopPropagation();
    self.query = '';
    $timeout(function () {
        document.getElementById('sidebar-search').focus();
    }, 1);
}

И HTML-форма:

<form ng-controller="SearchController as search"
    ng-submit="search.submit($event)">
        <input type="search" id="sidebar-search" 
            ng-model="search.query">
                <span class="glyphicon glyphicon-remove-circle"
                    ng-click="search.clear($event)">
                </span>
</form>

Ответ 5

UPDATE

Я также пробовал это, но безрезультатно:

$(document).ready(function() {
$('body :not(.wr-dropdown)').bind("click", function(e) {
    $('.test').focus();
})
$('.wr-dropdown').on('change', function(e) {
    if ($(".wr-dropdow option[value='/search']")) {
        setTimeout(function(e) {
            $('body :not(.wr-dropdown)').trigger("click");
        },3000)         
    } 
}); 

});

Я смущен, почему вы говорите, что это не работает, потому что ваш JSFiddle работает нормально, но вот мое предложение в любом случае...

Попробуйте эту строку кода в вашей функции SetTimeOut в событии click:

document.myInput.focus();

myInput коррелирует с атрибутом имени входного тега.

<input name="myInput">

И используйте этот код, чтобы размыть поле:

document.activeElement.blur();

Ответ 6

Это решение работает хорошо, я тестировал на своем телефоне:

document.body.ontouchend = function() { document.querySelector('[name="name"]').focus(); };

пользоваться

Ответ 7

Реализация WunderBart для нативной JavaScript-реализации.

Отключите автоматическое увеличение, используя размер шрифта.

function onClick() {

  // create invisible dummy input to receive the focus first
  const fakeInput = document.createElement('input')
  fakeInput.setAttribute('type', 'text')
  fakeInput.style.position = 'absolute'
  fakeInput.style.opacity = 0
  fakeInput.style.height = 0
  fakeInput.style.fontSize = '16px' // disable auto zoom

  // you may need to append to another element depending on the browser auto 
  // zoom/scroll behavior
  document.body.prepend(fakeInput)

  // focus so that subsequent async focus will work
  fakeInput.focus()

  setTimeout(() => {

    // now we can focus on the target input
    targetInput.focus()

    // cleanup
    fakeInput.remove()

  }, 1000)

}

Ответ 8

Пожалуйста, попробуйте использовать on-tap вместо события ng-click. У меня была эта проблема. Я разрешил это, установив кнопку явного поиска в ящике формы поиска и заменив ng-щелчок кнопки очистки нажатием кнопки. Теперь он отлично работает.