Мобильный 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, вы увидите, что клавиатура не слайд- в.
Ответы
Ответ 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-щелчок кнопки очистки нажатием кнопки. Теперь он отлично работает.