web-dev-qa-db-fra.com

Désactiver le défilement lors de la modification d'éléments de formulaire de focus application web ipad

J'ai une application web. J'essaie de désactiver/empêcher le défilement qui se produit lorsque vous vous concentrez sur différentes entrées de formulaire (c'est-à-dire le défilement qui se produit lorsque vous avancez dans les éléments d'entrée d'un formulaire).

J'ai déjà désactivé le défilement avec ceci: 

 <script type="text/javascript">
     $(document).ready(function() {
         document.ontouchmove = function(e){
              e.preventDefault();
              }
     });
 </script>

Pour ajouter un peu plus d’informations - j’ai quelques "diapositives" qui composent ma page. Chacune correspond à 768x1024 et elles sont "empilées" sur la page (c'est-à-dire que la page est 768x3072 [1024 * 3 = 3072]) et lorsque vous cliquez sur un lien, j'utilise le plugin scrollTo jquery pour faire défiler jusqu'à la "diapositive" suivante et .focus() sur un élément d'entrée.

Est-ce que quelqu'un sait comment faire ça?

26
Andrew Samuelsen

J'ai trouvé que dans UIWebView, document.body est également parfois déplacé. Donc j'utilise:

    input.onfocus = function () {
        window.scrollTo(0, 0);
        document.body.scrollTop = 0;
    }
16
Paul Greyson

Oups, le window.scrollTo suggéré est un peu moche et rend les choses imprévisibles. 

Essayez cette meilleure solution:

jQuery('body').bind('focusin focus', function(e){
  e.preventDefault();
})

Ou simplement, accrochez votre entrée:

jQuery('input.your-input-class').bind('focusin focus', function(e){
  e.preventDefault();
})

Pourquoi? Les navigateurs peuvent faire défiler l'élément de formulaire ciblé dans la vue par défaut lors de l'activation de l'événement 'focusin' (Firefox a un bogue, donc accrochez-vous au point). Alors, dites-leur simplement de ne pas le faire explicitement.

BTW, si l'événement focus est déclenché par element.focus() dans votre code, alors même la solution précédente ne serait pas fonctionnelle. 

Donc, une solution à cela serait de remplacer le déclencheur focus par select, c.-à-d.

element.select()

autre que element.focus()

Si vous n'aimez pas l'approche element.select() puisqu'elle select le texte à l'intérieur de l'élément d'entrée, essayez de créer un Range object du texte de l'élément d'entrée et réduisez-le si vous le souhaitez, désolé de ne pas avoir le temps de l'essayer pour le moment.

11
Paul Lan

Pour empêcher le navigateur de faire défiler l'élément que vous avez déplacé, j'utilise jQuerys one listener. Juste avant de déplacer le focus sur l'élément, nous ajoutons le programme d'écoute à l'événement scroll et le compteur scroll. L'écouteur d'événements est ensuite supprimé par jQuery.

var oldScroll = $(window).scrollTop();

$( window ).one('scroll', function() {
    $(window).scrollTop( oldScroll ); //disable scroll just once
});

$('.js-your-element').focus();

Cette méthode me semble simple, efficace et fonctionne très bien dans tous les tests que j'ai effectués.

J'espère que ça aide quelqu'un.

4
Dominik

Si vous ne voulez pas que l'entrée soit modifiable, la réponse de kpozin fonctionne bien. Mais dès que vous supprimez l'attribut readonly, onfocus ou onclick, le champ de saisie est réactivé.

Ce qui aide vraiment et n'a pas d'incidence sur la mise au point ou la capacité de saisir du texte, c'est d'ajouter onFocus="window.scrollTo(0, 0);" aux éléments en entrée.

Bien sûr, vous devez vous assurer que l'entrée correspondante n'est pas couverte par le clavier à l'écran!

Voir aussi cet article: Empêcher un élément <input> de faire défiler l'écran sur un iPhone?

3
Mischa Magyar

Mise à jour à ce sujet - J'ai vu la solution window.scroll(0,0) dans plusieurs endroits, mais cela semblait empirer les choses. J'ai plusieurs entrées de texte en ligne sur ma page. Ainsi, lors du déplacement de focus entre elles, le défilement automatique vers le haut et le bas dans Safari a rendu la page presque inutilisable, en particulier en orientation paysage.

Après avoir combattu iOS 8 pendant une semaine, j'ai constaté que cela empêchait le défilement. Cela fonctionne lorsque vous modifiez le focus d'un élément à un autre, car vous devez associer l'événement onblur à quelque chose:

var moveFocus = function (blurId, focusId) {
    var blurInput = document.getElementById(blurId);
    var focusInput = document.getElementById(focusId);
    if (blurInput && focusInput) {
        blurInput.onblur = function () {
            if (focusInput.setSelectionRange && focusInput.setSelectionRange()) {
                var len = focusInput.value.length;
                focusInput.setSelectionRange(len, len);
            }
            focusInput.focus();
        };
        focusInput.focus();
    };
};
2
panchoLopez

Si vous développez une application Web mobile avec Cordova, il existe un plugin pour cela:

Le plugin qui a résolu le problème pour moi était le Telerik Keyboard Plugin . Il utilise le UIWebView de base. Installer le plugin

cordova plugin add ionic-plugin-keyboard

Et appelez cette commande après le chargement de votre application:

cordova.plugins.Keyboard.disableScroll(true);

Si vous utilisez WKWebView, vous pouvez utiliser par exemple ce plugin

0
David Nathan

Cela a fonctionné pour moi (en utilisant jQuery). Il permet le défilement, puis vous ramène à la bonne position lorsque vous quittez l’entrée.

    var saveScrollLeft;
    $("input, textarea")
        .focus(function () {
            clearTimeout(blurTimeoutId);
            saveScrollLeft = $("body").scrollLeft();
            })
        .blur(function () {
            // The user might be moving from one input to another, so we don't want to quickly scroll on blur.  Wait a second and see if they are off all inputs.
            blurTimeoutId = setTimeout(function () {
                $(window).scrollLeft(saveScrollLeft);
                }, 1000);
        });
0
mhenry1384

Aucune des solutions fournies ne fonctionnait pour moi… .. Étant donné que le formulaire qui capte le focus (et le défilement de l'affichage initial de la page jusqu'au formulaire) se trouve en dessous du pli, j'ai simplement ajouté un fondu au fond.

J'ajoute donc un nom de classe appelé fade-in, qui correspond à css en display:none

en utilisant jQuery, je fais simplement jQuery(".fade-in").fadeIn(); après le document prêt, et le problème a disparu.

Ceci n'est évidemment pas limité à l'utilisation de jQuery. Vanilla js peut être utilisé pour le fondu.

0
proxiblue

Essayez cette réponse par BLSully. Attribuez un attribut readonly="readonly" à tous vos éléments d'entrée. Cela empêchera Mobile Safari d'y accéder. Supprimez l'attribut sélectionné et rajoutez-le à nouveau pour rendre flou chaque élément.

0
kpozin

Pour "faire le point" sans défilement, vous pouvez utiliser select. select par défaut sélectionnera tout le texte à l'intérieur d'une entrée. Pour imiter le comportement focus et avoir le curseur à la fin de l'entrée, vous pouvez utiliser:

var myInput = document.getElementById('my-input');
var length = myInput.value.length;  // Or determine the value of length any other way
myInput.select();
myInput.setSelectionRange(length, length);
0
tic