Comment définir le focus sur le premier élément d'entrée dans un formulaire HTML indépendant de l'ID?

84

Existe-t-il un moyen simple de définir le focus (curseur de saisie) d'une page Web sur le premier élément d'entrée (zone de texte, liste déroulante, ...) lors du chargement de la page sans avoir à connaître l'id de l'élément?

Je voudrais l'implémenter comme un script commun pour toutes mes pages / formulaires de mon application Web.

splattne
la source
7
REMARQUE si le formulaire est placé vers le bas dans la page d'une manière que l'utilisateur doit faire défiler la page vers le bas pour voir le formulaire, en définissant le focus fera automatiquement défiler la page vers le bas comme le ferait une ancre. Ce n'est pas très bon car l'utilisateur accédant à une telle page la verrait immédiatement défiler jusqu'à la position du formulaire. J'ai testé sur Safari et FF (IE7 n'effectue pas le défilement de page).
Marco Demaio
@Marco_Demaio Mon application Web est structurée de manière à ce que chaque page ait ses zones de saisie en haut de la fenêtre.
splattne
3
et si l'utilisateur redimensionnait la hauteur de la fenêtre du navigateur à quelque chose de plus petit que 768px. La page défile jusqu'à l'endroit où vous définissez le focus. Quoi qu'il en soit, je voulais seulement vous avertir au cas où vous ne saviez pas ce problème mineur, je ne savais pas non plus avant de faire quelques tests.
Marco Demaio

Réponses:

96

Vous pouvez également essayer la méthode basée sur jQuery:

$(document).ready(function() {
    $('form:first *:input[type!=hidden]:first').focus();
});
Marko Dumic
la source
Ça marche! Je commence à intégrer jQuery dans mon application Web. Donc, je pense que je vais m'en tenir à cette approche! Merci beaucoup, Marko!
splattne
3
Que se passe-t-il si le premier formulaire de la page est masqué dans ce cas? Ou si le premier élément du formulaire est masqué via CSS? Cela échouerait sûrement. Je suis pédant bien sûr mais c'est comme ça que je roule.
James Hughes
Dans mon cas (en utilisant ASP.NET), je n'ai qu'un seul formulaire qui n'est jamais caché. Donc cela fonctionne pour moi.
splattne
@Jame Hughes, vous pouvez l'écrire en tant que fonction et l'appeler quand vous en avez besoin, et vous pouvez faire des exceptions. Pour moi, cette solution a vraiment aidé.
Luci
cela ne fonctionne pas pour moi pour une raison quelconque. ne devrais-je pas voir un curseur.
Chris
136

Bien que cela ne réponde pas à la question (nécessitant un script commun), je pensais qu'il pourrait être utile pour d'autres de savoir que HTML5 introduit l'attribut 'autofocus':

<form>
  <input type="text" name="username" autofocus>
  <input type="password" name="password">
  <input type="submit" value="Login">
</form>

Plongez dans HTML5 pour plus d'informations.

Jacob Stanley
la source
2
l'autofocus est le nom d'attribut. Qu'en est-il de sa valeur? Quelque chose comme l'autofocus = vrai pas nécessaire? Que signifie ne pas définir de valeur?
Geek
4
En HTML5, certains attributs n'ont pas besoin d'avoir une valeur, «vérifié» est un autre attribut où c'est le cas. Je crois que lorsque la valeur est laissée de côté, il est sous-entendu que c'est le même que le nom (par exemple, autofocus = "autofocus" et vérifié = "vérifié").
Jacob Stanley
Mon application Spring est interrompue lorsque j'essaie d'utiliser autofocussans valeur spring:form. autofocus="autofocus"fonctionne bien, cependant. Merci, @Jacob.
Sergei Tachenov
2
@Geek L'attribut autofocus, comme beaucoup d'autres, est un type d'attribut booléen. C'est pourquoi il n'est utilisé que de manière déclarative, pas en lui attribuant une valeur. Voir plus de détails dans les spécifications w3c: w3.org/TR/html5/infrastructure.html#boolean-attribute
n1kkou
34
document.forms[0].elements[0].focus();

Cela peut être affiné en utilisant une boucle par exemple. ne pas concentrer certains types de champs, les champs désactivés, etc. Mieux peut - être ajouter une classe = « mise au point automatique » au champ que vous avez réellement ne veulent concentré et boucle sur les formes [i] .elements [j] la recherche de ce className.

Quoi qu'il en soit: ce n'est normalement pas une bonne idée de faire cela sur chaque page. Lorsque vous vous concentrez sur une entrée, l'utilisateur perd la capacité d'ex. faites défiler la page à partir du clavier. Si cela est inattendu, cela peut être ennuyeux, alors la mise au point automatique ne se fait que lorsque vous êtes certain que l'utilisation du champ de formulaire sera ce que l'utilisateur souhaite faire. c'est à dire. si vous êtes Google.

bobince
la source
3
Doit être la bonne réponse, car la question n'a pas de balise jquery.
Kalle H. Väravas
@ KalleH.Väravas non, il devrait être rejeté car il émet des hypothèses qui ne sont pas en cause, par exemple. il y a au moins un formulaire. Généralement, cela ne fonctionne pas.
9ilsdx 9rvj 0lo
18

L'expression jQuery la plus complète que j'ai trouvée fonctionne est (à l'aide de ici )

$(document).ready(function() {
    $('input:visible:enabled:first').focus();
});
ngeek
la source
1
J'utilisais ceci, j'ai remarqué qu'il fonctionne extrêmement lentement sur IE quand un grand nombre> 1000 de cases à cocher dans une table. Je ne sais pas quoi faire à ce sujet, vous devrez peut-être renoncer à vous concentrer sur le premier champ d'entrée.
Sam Watkins
5

Vous devez également ignorer toutes les entrées masquées.

for (var i = 0; document.forms[0].elements[i].type == 'hidden'; i++);
document.forms[0].elements[i].focus();
Marko Dumic
la source
Je me trompe peut-être, mais cette boucle n'a pas de comportement défini si forms [0] n'a pas d'entrées cachées.
xtofl
Exactement. Il est utilisé pour ignorer toutes les principales entrées cachées. Et il est écrit en supposant qu'il y a des champs non cachés dans le formulaire. J'aurais pu le faire aussi avec jQuery (je posterai une autre réponse) mais vous n'avez pas mentionné que vous vouliez impliquer jQuery.
Marko Dumic
1
@MarkoDumic Pourquoi gaspiller de la mémoire si vous pouvez utiliser une whileinstruction?
Lucio
3

Mettre ce code à la fin de votre bodybalise focalisera automatiquement le premier élément activé visible et non masqué sur l'écran. Il traitera la plupart des cas que je peux proposer à court préavis.

<script>
    (function(){
        var forms = document.forms || [];
        for(var i = 0; i < forms.length; i++){
            for(var j = 0; j < forms[i].length; j++){
                if(!forms[i][j].readonly != undefined && forms[i][j].type != "hidden" && forms[i][j].disabled != true && forms[i][j].style.display != 'none'){
                    forms[i][j].focus();
                    return;
                }
            }
        }
    })();
</script>
James Hughes
la source
1
Une chose à considérer ici est qu'il peut correspondre à des éléments qui ne sont pas eux-mêmes cachés, mais un ancêtre l'est. Cela nécessiterait de remonter le DOM et de tester la visibilité de chaque ancêtre, ce qui, à mon avis, est excessif pour ce genre de situation.
James Hughes
Qu'en est-il de <input type = "text" readonly = "readonly"> Je pense que vous devriez ajouter un tel cas à votre code. Normalement, les gens ne veulent pas se concentrer sur un champ de texte de saisie en lecture seule. En tout cas beau code et +1 merci!
Marco Demaio
Non testé mais je l'ai mis à jour avec! Forms [i] [j] .readonly! = Undefined
James Hughes
3

J'utilise ceci:

$("form:first *:input,select,textarea").filter(":not([readonly='readonly']):not([disabled='disabled']):not([type='hidden'])").first().focus();
Robert Brooker
la source
2

Cela obtient la première de toute entrée commune visible, y compris les zones de texte et les zones de sélection. Cela garantit également qu'ils ne sont pas masqués, désactivés ou en lecture seule. il permet également un div cible, que j'utilise dans mon logiciel (c'est-à-dire, première entrée à l'intérieur de ce formulaire).

$("input:visible:enabled:not([readonly]),textarea:visible:enabled:not([readonly]),select:visible:enabled:not([readonly])", 
    target).first().focus();
Dave K
la source
1

Pour ceux qui utilisent JSF2.2 + et ne peuvent pas passer l'autofocus en tant qu'attribut sans valeur, utilisez ceci:

 p:autofocus="true"

Et ajoutez-le à l'espace de noms p (aussi souvent utilisé pt. Tout ce que vous voulez).

<html ... xmlns:p="http://java.sun.com/jsf/passthrough">
fédérateur
la source
0

Avec AngularJS:

angular.element('#Element')[0].focus();
EpokK
la source
0

Cela inclut les zones de texte et exclut les boutons radio

$(document).ready(function() {
    var first_input = $('input[type=text]:visible:enabled:first, textarea:visible:enabled:first')[0];
    if(first_input != undefined){ first_input.focus(); }
});
HectorPerez
la source
0

Vous devriez pouvoir utiliser clientHeight au lieu de vérifier l'attribut d'affichage, car un parent pourrait masquer cet élément:

function setFocus() {
    var forms = document.forms || [];
        for (var i = 0; i < forms.length; i++) {
            for (var j = 0; j < forms[i].length; j++) {
            var widget = forms[i][j];
                if ((widget && widget.domNode && widget.domNode.clientHeight > 0) && typeof widget.focus === "function")
                 && (typeof widget.disabled === "undefined" || widget.disabled === false)
                 && (typeof widget.readOnly === "undefined" || widget.readOnly === false)) {
                        widget.focus();
                        break;
                }
            }
        }
    }   
}
le coolmacdude
la source
0

Sans bibliothèques tierces, utilisez quelque chose comme

  const inputElements = parentElement.getElementsByTagName('input')
  if (inputChilds.length > 0) {
    inputChilds.item(0).focus();
  }

Assurez-vous de prendre en compte toutes les balises d'élément de formulaire, excluez les balises masquées / désactivées comme dans les autres réponses, etc.

cghislai
la source
0

sans jquery, par exemple avec javascript classique:

document.querySelector('form input:not([type=hidden])').focus()

fonctionne sur Safari mais pas sur Chrome 75 (avril 2019)

localhostdotdev
la source