Safari Mobile: la méthode Javascript focus () sur inputfield ne fonctionne qu'avec click?
je n'arrive pas à trouver une solution à ce problème.
j'ai un champ d'entrée simple comme celui-ci.
<div class="search">
<input type="text" value="y u no work"/>
</div>
et j'essaie de focus()
à l'intérieur d'une fonction.
Donc à l'intérieur d'une fonction aléatoire (peu importe quelle fonction c'est) j'ai cette ligne ...
$('.search').find('input').focus();
cela fonctionne très bien sur chaque bureau que ce soit.
cependant il ne fonctionne pas sur mon iPhone. Le terrain ne devient pas concentré et le clavier n'est pas affiché sur mon iPhone.
pour tester et vous montrer le problème, j'ai fait un petit échantillon:
$('#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);
N'importe quelle idée pourquoi le focus()
ne fonctionnerait pas avec la fonction timeout sur mon iPhone.
pour voir l'exemple en direct, testez ce violon sur votre iPhone. http://jsfiddle.net/Hc4sT /
mise à jour:
j'ai créé exactement le même cas que celui auquel je fais face dans mon projet actuel.
j'ai une boîte de sélection qui devrait-quand" changé " - mettre l'accent sur le champ d'entrée et de glisser - dans le clavier sur l'iphone ou d'autres appareils mobiles. J'ai trouvé que le focus() est définie correctement, mais le clavier ne s'affiche pas. J'ai besoin du clavier.
j'ai téléchargé les fichiers de test juste ici http://cl.ly/1d210x1W3Y3W … Si vous tester sur l'iphone, vous pouvez voir que le clavier ne glisse pas.
7 réponses
en fait, les gars, il y a un moyen. J'ai eu du mal à comprendre ça pour http://forstartersapp.com (essayez sur un iPhone ou un iPad).
essentiellement, Safari sur les appareils à écran tactile est radin quand il s'agit de focus()
textboxes ing. Même certains navigateurs de bureau font mieux si vous faites click().focus()
. Mais les concepteurs de Safari sur les appareils à écran tactile ont réalisé que c'est ennuyeux pour les utilisateurs lorsque le clavier continue à venir, l'accent est mis uniquement sur les conditions suivantes:
1) L'utilisateur a cliqué quelque part et focus()
a été appelé lors de l'exécution de l'événement click. Si vous faites un appel AJAX, alors vous devez le faire de façon synchrone, comme avec l'option dépréciée (mais toujours disponible) $.ajax({async:false})
dans jQuery.
2) de plus -- et celui-ci m'a occupé pendant un certain temps -- focus()
semble toujours ne pas fonctionner si une autre boîte de texte est concentré sur le moment. J'avais un bouton " Go "qui faisait L'AJAX, donc j'ai essayé de brouiller la boîte de texte sur l'événement touchstart
du bouton Go, mais cela a juste fait disparaître le clavier et déplacé le viewport avant que j'ai eu la chance de compléter le clic sur le bouton Go. Enfin j'ai essayé de brouiller la boîte de texte sur le touchend
Événement du bouton Go, et cela a fonctionné comme un charme!
quand vous mettez les #1 et #2 ensemble, vous obtenez un résultat magique qui va définir vos formulaires de connexion en dehors de tous les formulaires de connexion Web merdiques, en plaçant le foyer dans vos champs de mot de passe, et les faire se sentir plus native. Profitez-en! :)
j'ai fait face à la même question récemment. J'ai trouvé une solution qui fonctionne apparemment pour tous les appareils. Vous ne pouvez pas faire de focus asynchrone programmatique mais vous pouvez changer focus à votre entrée cible quand une autre entrée est déjà focalisée. Donc, ce que vous devez faire est de créer, Cacher, ajouter à DOM & focus une entrée fake sur l'événement déclencheur et, lorsque l'action async se termine, il suffit d'appeler focus à nouveau sur l'entrée cible. Voici un exemple extrait - exécuter sur votre mobile.
edit:
voici un violon avec le même code . Apparemment, vous ne pouvez pas exécuter des snippets attachés sur les mobiles (ou je fais quelque chose de mal).
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's 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>
j'ai réussi à le faire fonctionner avec le code suivant:
event.preventDefault();
timeout(function () {
$inputToFocus.focus();
}, 500);
J'utilise AngularJS donc j'ai créé une directive qui a résolu mon problème:
Directive:
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);
});
}
};
}
]);
comment utiliser la directive:
<div>
<input type="search" id="search">
<i class="icon-clear" ng-click="clearSearchTerm()" focus-on-clear="search"></i>
</div>
on dirait que vous utilisez jQuery, donc je ne sais pas si la directive est utile.
j'ai un formulaire de recherche avec une icône qui efface le texte lorsque cliqué. Cependant, le problème (sur mobile & tablettes) était que le clavier s'effondrerait/se cacherait, car l'événement click
supprimé focus
a été supprimé du input
.
Goal : après avoir effacé le formulaire de recherche (en cliquant/en tapant sur X-icon) garder le clavier visible !
pour ce faire, appliquer stopPropagation()
sur l'événement comme ceci:
function clear ($event) {
$event.preventDefault();
$event.stopPropagation();
self.query = '';
$timeout(function () {
document.getElementById('sidebar-search').focus();
}, 1);
}
et la forme 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>
mise à JOUR
j'ai aussi essayé, mais en vain:
$(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)
}
});
});
je suis confus quant à la raison pour laquelle vous dites que cela ne fonctionne pas parce que votre JSFiddle fonctionne très bien, Mais voici ma suggestion de toute façon...
essayez cette ligne de code dans votre fonction SetTimeOut sur votre événement de clic:
document.myInput.focus();
corrélation entre myInput et l'attribut name de la balise input.
<input name="myInput">
et utilisez ce code pour brouiller le champ:
document.activeElement.blur();
Cette solution fonctionne bien, j'ai testé sur mon téléphone:
document.body.ontouchend = function() { document.querySelector('[name="name"]').focus(); };
profiter
veuillez essayer d'utiliser on-tap au lieu de ng-click event. J'ai eu ce problème. Je l'ai résolu en faisant mon clear-search-box bouton à l'intérieur de l'étiquette de formulaire de recherche et remplacé ng-click de clear-button par On-tap. Il fonctionne très bien maintenant.