web-dev-qa-db-fra.com

Entrée HTML5 requise, faites défiler jusqu'à l'entrée avec la barre de navigation fixe lors de l'envoi

Lorsque j'essaie de soumettre un formulaire avec des champs obligatoires manquants, mon navigateur (Chrome) affiche un message signalant qu'un champ est manquant. S'il est en dehors de mon écran, il défile jusqu'à l'écran.

Mon problème est que j'ai un en-tête fixe de 50 px dans ma page Web et, par conséquent, le champ de saisie est masqué et le message semble sortir de nulle part:

Input field hidden

Au lieu de

Input field shown

Y a-t-il un moyen de contourner ceci? 

J'ai essayé à la fois d'appliquer la marge 50px à <html> et à <body>

À votre santé


MODIFIER

Voici un violon du problème: http://jsfiddle.net/LL5S6/1/

41

Le seul moyen que j’ai trouvé est d’ajouter un «remplacement» au gestionnaire non valide . Pour implémenter cela pour chaque entrée de votre formulaire, vous pouvez faire quelque chose comme ceci.

var elements = document.querySelectorAll('input,select,textarea');
var invalidListener = function(){ this.scrollIntoView(false); };

for(var i = elements.length; i--;)
    elements[i].addEventListener('invalid', invalidListener);

Cela nécessite HTML5 et cela est testé sur IE11, Chrome et Firefox.
Crédits à @HenryW pour avoir découvert que scrollIntoView fonctionne comme prévu.

Notez que le paramètre false pour scrollIntoView aligne l'entrée avec le bas. Par conséquent, si vous avez un formulaire de grande taille, il peut être aligné avec le bas de la page.

jsfiddle

22
A1rPun

J'ai eu exactement le même problème et je l'ai résolu en utilisant jquery avec ce morceau de code:

var delay = 0;
var offset = 150;

document.addEventListener('invalid', function(e){
   $(e.target).addClass("invalid");
   $('html, body').animate({scrollTop: $($(".invalid")[0]).offset().top - offset }, delay);
}, true);
document.addEventListener('change', function(e){
   $(e.target).removeClass("invalid")
}, true);

Le décalage doit correspondre à la hauteur de votre en-tête et au délai, au temps qu'il vous faut pour parcourir l'élément.

37
T.J. Moats

Lorsqu'il y a plusieurs entrées non valides dans le formulaire, vous voulez seulement faire défiler jusqu'au premier d'entre elles:

var form = $('#your-form')
var navbar = $('#your-fixed-navbar')

// listen for `invalid` events on all form inputs
form.find(':input').on('invalid', function (event) {
    var input = $(this)

    // the first invalid element in the form
    var first = form.find(':invalid').first()

    // only handle if this is the first invalid input
    if (input[0] === first[0]) {
        // height of the nav bar plus some padding
        var navbarHeight = navbar.height() + 50

        // the position to scroll to (accounting for the navbar)
        var elementOffset = input.offset().top - navbarHeight

        // the current scroll position (accounting for the navbar)
        var pageOffset = window.pageYOffset - navbarHeight

        // don't scroll if the element is already in view
        if (elementOffset > pageOffset && elementOffset < pageOffset + window.innerHeight) {
            return true
        }

        // note: avoid using animate, as it prevents the validation message displaying correctly
        $('html,body').scrollTop(elementOffset)
    }
})

JSFiddle

9
Alf Eaton

ok, j'ai fait un test avec un extrait de code que j'ai trouvé ici sur SO

Puisqu'il s'agit d'un code de quelqu'un d'autre, je le modifie simplement pour faire défiler l'élément qui manquait d'une exigence d'entrée .. Je ne veux pas de crédit pour cela, et ce n'est peut-être même pas ce que vous avez ou quelqu'un d'autre pourrait l'utiliser comme référence.

Le but était d'obtenir l'identifiant de l'élément de saisie oublié/incorrect:

            var myelement = input.id;
            var el = document.getElementById(myelement);
            el.scrollIntoView(false);

S'il vous plaît gardez à l'esprit que ce violon ne fonctionne que pour votre violon posté ci-dessus, il ne gère pas plusieurs champs de saisie oubliés ou erronés. Je voulais seulement montrer une alternative.

-----> jSFiddle

4
HenryW

Vous pouvez utiliser l'attribut d'événement oninvalid de HTML5 et écrire dans la balise de votre script une fonction pour le rediriger.

Voici l'exemple:

<input type="text" required oninvalid="scroll_to_validator(this)">

<script>
    function scroll_to_validator(input)
        {
        input.focus(); 
        }
</script>

Et en cliquant sur votre bouton d'envoi, il fera défiler le champ invalide.

Pour le bouton radio, ajoutez seulement une radio du même nom
Voici l'exemple (jsfiddle)

1
Abhilash Sharma

J'ai essayé d'utiliser la manière de T.J. Des douves, mais cela n’a pas fonctionné au besoin, car je revenais souvent sur le terrain, ce qui était incorrect au départ.

Alors je l'ai fait:

var navhei = $('header').height();
var navheix = navhei + 30;
document.addEventListener('invalid', function(e){
$(e.target).addClass("invalid");
   $('html, body').animate({scrollTop: $($(".invalid")[0]).offset().top - navheix }, 0);
 
setTimeout(function() {
$('.invalid').removeClass('invalid');
},0300);
}, true);
body {
    margin: 0;
    margin-top: 50px;
    text-align: center;
}

header {
    position: fixed;
    width: 100%;
    height: 50px;
    background-color: #CCCCCC;
    text-align:center;
    top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<header>This is the header</header>
<div>
<form action="">
<br>
    <input id="text" type="text" required="required" /><br><br>
    <input id="text" type="text" required="required" /><br><br><br><br>
    <input id="text" type="text" required="required" /><br><br>
    <input id="text" type="text" required="required" /><br><br><br><br>
    <input id="text" type="text" required="required" /><br><br><br><br><br><br>
    <input id="text" type="text" required="required" /><br><br>
        <p>Click send (at the bottom of the page), without filling the input field.</p><br><br><br><br><br><br>
        <input id="text" type="text" required="required" /><br><br>
    <input type="submit" id="btnSubmit" />
    </form>
</div>

J'espère que ce sera utile pour les gens :)

0
kibus90

Deux solutions:

  • One: appliquer un rembourrage sur le corps ->

    body {
     padding-top:50px;
    }
    
  • Deux: appliquer une marge au conteneur principal ->

     #content {
       margin-top:50px;
     }
    
0
DaniP