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:
Au lieu de
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/
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.
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.
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)
}
})
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.
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)
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 :)
Deux solutions:
One: appliquer un rembourrage sur le corps ->
body {
padding-top:50px;
}
Deux: appliquer une marge au conteneur principal ->
#content {
margin-top:50px;
}