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.

50
demandé sur Chad 2012-08-31 00:00:39

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! :)

66
répondu Gregory Magarshak 2013-05-17 04:14:23

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>
3
répondu WunderBart 2017-08-16 08:07:36

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.

2
répondu martinmose 2014-04-15 11:12:16

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 .

text search input with close icon

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>
2
répondu DeBraid 2015-11-25 17:57:13

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();
1
répondu Alex 2012-08-31 15:59:57

Cette solution fonctionne bien, j'ai testé sur mon téléphone:

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

profiter

1
répondu istvan makary 2016-02-12 17:52:28

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.

-3
répondu nishan mk 2016-05-02 09:36:54