diff --git a/_posts/2011-10-19-subtilites-du-login.markdown b/_posts/2011-10-19-subtilites-du-login.markdown new file mode 100644 index 0000000..3a589e8 --- /dev/null +++ b/_posts/2011-10-19-subtilites-du-login.markdown @@ -0,0 +1,151 @@ +--- +layout: post +title: Les subtilités des formulaires de login en JS +author: feugy +tags: [javascript, login, formulaire, chrome, firefox, jQuery] +published: false +--- + +Quoi de plus simple qu'un formulaire de login ? +En HTML, certes, mais lorsque qu'on parle d'application riche en javascript, c'est une autre histoire. + +Si vous ne comprenez pas pourquoi le navigateur ne retient pas vos logins, ne propose pas le mot de passe associé, ou ne réagit pas à la touche entrée, lisez la suite ! + +Cet article est le résultat de **l'étude empirique du comportement des navigateurs**. +Il est donc sujet à caution: tout dépends de votre navigateur et de sa version. +J'espère simplement vous aider à comprendre et éviter les principaux chausse-trappes, sans avoir recours à l'installation d'un plugin :) + + +## Mais ce n'est qu'un formulaire ! + +Hélas non... Les formulaires de login (un champs text + un champ password) sont détectés par le navigateur, qui va les traiter différemment des autres champs textuels. + +C'est là le premier problème : +>**Le formulaire doit être présent dans le DOM au chargement de la page.** + +Oui, vous avez compris : si vous construisez votre formulaire directement en JS, ou si vous utilisez un template que vous accrochez une fois la page chargée, votre formulaire sera ignoré par certains navigateurs. + +L'astuce que j'utilise consiste à: + +* inclure le formulaire de login dans ma page index.html +* le masquer avec un style CSS display:none. +* le déplacer par la suite en javascript là où il doit apparaitre dans le rendu + +**index.html** + +
+ +**login.js** + + $('.loginContainer', this.element).append($('#loginStock > *')); + + +## Dois-je mettre un champ de type submit ? + +S'il n'y a que les champs de type text et password, le navigateur ne retiendra pas le mot de passe. + +>**Le champ de type submit est indispensable.** + +Même s'il est masqué (le bouton n'est pas encore bien skinnable, même en CSS 3), il doit être présent. + +**index.html** + + + +**login.js** + + $('.loginContainer .submit').click(function(event){ + // Déclenche la soumission du formulaire. + $('#formLogin').submit(); + // Annule la propagation du Click sur le lien, pas de la soumission du formulaire ! + return false; + }).button({label:'log in !'}); + + +## Doit-on stopper la propagation de l'événement submit ? + +Le problème se pose si vous ne réalisez pas un "vrai" POST lorsque l'utilisateur déclenche la soumission du formulaire. +Dans la majorité des applications riches, l'authentification se fait via une API, et donc un appel Ajax. + +On se branche alors sur l'événement submit, et on annule sa propagation. + +Seulement, en stoppant l'événement de soumission, le navigateur ne retient pas le login et le mot de passe. + +>**Pour que le navigateur mémorise le couple login/mot de passe, l'événement submit doit se propager.** + +Cela implique: + +* que le formulaire pointe sur une véritable url, sinon, une vilaine 404 apparaitra dans votre console +* que le résultat de la soumission soit routée dans une iframe (désolé pour les puristes :)), sans quoi, toute la page se rechargera + +Donc généralement, mon service web propose une API POST qui ne fait rien et renvoie une page vide, et j'utilise une iframe masquée. + +**index.html** + + + + +**login.js** + + $('#formLogin').submit(function(event){ + // Ici mon appel ajax, et surtout, ne pas renvoyer false ni invoquer event.stopPropagation(). + }); + + +### Une petite astuce : lorsque l'authentification échoue. + +A partir du moment où l'événement submit est propagé, et qu'une réponse HTTP est reçue, le navigateur conservera bien le mot de passe et le login. + +Mais nous pouvons tirer parti de ce comportement, lorsque l'authentification échoue, par exemple si l'utilisateur est inconnu, ou le mot de passe erroné. + +Ainsi, mon appel Ajax est toujours **synchrone** (parfois ça sert !), et s'il échoue, alors dans ce cas, j'annule la propagation de l'événement submit pour ne pas conserver les mauvais identifiants. + + + +## La touche entrée ne soumet pas toujours mon formulaire... + +Hélas oui, c'est un comportement étrange de certains navigateurs : un formulaire sera automatiquement soumit si on appuie sur entrée dans un de ses champs, sauf si le bouton submit est invisible ! + +Donc il faut eviter le display:none ou le visibility:hidden sur le champ. +Personnellement, je lui affecte une taille de zéro. Vous pouvez aussi le positionner en absolu, en dehors de la zone visible, ou le mettre en dessous d'un autre élément avec le z-index + +**index.html** + + + + +## Conclusion + +Vous voyez ? quand je vous disais que ce n'était pas trivial... + +Mais maintenant, vous avez toutes les clefs pour faire des formulaires qui exploitent le cache de login/mot de passe des navigateurs. + +Espérons que dans un futur proche, les navigateurs harmonisent un peu plus leur fonctionnement, de manière à éviter tout ces tricks... + +Damien. \ No newline at end of file