L’utilisateur tape son mot-de-passe, et à la fin il doute de ce qu’il a entré sur l’avant dernier caractère. Du coup il retape tout. Et si on lui proposait de démasquer temporairement son mot de passe sur commande ?
Je vois souvent des sites connus proposer des formulaires d’identifications ou des formulaires d’inscription avec un champ « mot de passe » utilisant un type texte. L’effet est assez direct pour moi, on voit mon mot de passe, donc j’envoie un mail à l’équipe qui gère le site pour les prévenir de l’erreur.
« Bonjour Monsieur, ceci n’est pas une erreur et permet à l’internaute de voir ce qu’il a tapé dans le champ. »
Ah ouais carrément ! Ils ont réfléchi en plus, avant de faire cette erreur ?
Bref, sarcasmes mis à part, la personne qui regardera au dessus de votre épaule pendant que vous tapez deux fois votre mot de passe en clair, aura bien le temps de le lire une fois 😉
Concept
Windows 8 propose une gestion du champ mot-de-passe assez intéressante puisqu’il permet de masquer et démasquer le code à tout moment avec un bouton placé à droite du champ.
Voilà à quoi ressemble un tel champ :
C’est ce comportement que j’ai cherché à reproduire récemment.
Le code
HTML : la structure
Voici un petit morceau de code classique pour la structure HTML :
<div class="connect_box">
<h1>Connection<span>use your login and password</span></h1>
<form>
<p>
<label for="password">Your password</label>
<input type="password" value="" placeholder="Enter Password" id="password">
<button class="unmask" type="button" title="Mask/Unmask password to check content">Unmask</button>
</p>
</form>
</div>
Je ne pense pas que vous ayez besoin d’explications, mais si c’était le cas laissez-moi un petit commentaire en fin d’article.
Le bouton est présent uniquement pour intercepter l’action de masquage et démasquage, mais vous allez comprendre par vous-même. Je n’ai pas mis de bouton submit pour alléger le code 🙂
CSS : les styles
Un peu de mise en forme avec CSS, rien de sorcier également, nous verrons le design du bouton de démasquage plus tard :
div {
width: 400px;
margin: 0 auto;
text-align: center;
}
h1 {
font-size: 30px;
color: #969696;
text-shadow: 1px 1px 0px #fff;
font-weight: 100;
}
h1 span {
display:block;
font-size: 14px;
color: #bbb;
}
form p { position: relative; }
label {
position:absolute;
left:-9999px;
text-indent: -9999px;
}
input {
width: 250px;
padding: 10px 12px;
margin-bottom: 5px;
border: 1px solid #cccccc;
border-bottom-color: #fff;
border-right-color: #fff;
border-radius: 4px;
background: #e3e3e3;
color: #888;
}
Voici la partie concernant le petit bouton. J’ai souhaité faire quelque chose en full CSS sans image, mais à vous d’adapter la chose.
.password + .unmask {
position:absolute;
right: 68px; top: 7px;
width: 25px;
height: 25px;
text-indent: -9999px;
background: #aaa;
border-radius: 50%;
}
.password + .unmask:before {
content: "";
position:absolute;
top:4px; left:4px;
z-index:1;
width: 17px;
height: 17px;
background: #e3e3e3;
border-radius: 50%;
}
.password[type="text"] + .unmask:after {
content: "";
position:absolute;
top:6px; left:6px
z-index:2;
width: 13px;
height: 13px;
background: #aaa;
border-radius: 50%;
}
On donne une forme ronde à notre bouton, puis on lui change légèrement son aspect lorsque le champ password
devient un champ de type text
. Pour effectuer le passage de l’un à l’autre, on va utiliser JavaScript.
JavaScript : les actions
Là où ça fait vraiment mal, c’est la fonction JavaScript.
Je pensais utiliser simplement jQuery pour changer la valeur de l’attribut type et la faire passer de password à text.
C’est un peu la base de la technique, et sur le principe c’est hyper simple.
Sauf que ça ne se passe pas comme ça : l’accès à l’attribut type est « interdit ».
Il va falloir en quelque sorte récupérer l’élément, chacun de ses attributs et ses valeurs, puis recréer un nouvel élément composé des mêmes attributs (on en profitera pour changer la valeur du type 😉 ) pour l’insérer dans le DOM.
Je vais donc vous donner la partie facile du code, celle qui consiste à dire à l’élément « change de type quand on clique là-dessus ». Je vous donne la fonction plus complexe juste après.
$('.unmask').on('click', function(){
if($(this).prev('input').attr('type') == 'password')
changeType($(this).prev('input'), 'text');
else
changeType($(this).prev('input'), 'password');
return false;
});
Le code fait la chose suivante : au clic, si l’input
précédent le bouton est de type password
, alors il passe en type text
; s’il est de type text
, il repasse en password
.
La fonction changeType()
est définie ainsi :
/*
function from : https://gist.github.com/3559343
Thank you bminer!
*/
// x = élément du DOM, type = nouveau type à attribuer
function changeType(x, type) {
if(x.prop('type') == type)
return x; // ça serait facile.
try {
// Une sécurité d'IE empêche ceci
return x.prop('type', type);
}
catch(e) {
// On tente de recréer l'élément
// En créant d'abord une div
var html = $("<div>").append(x.clone()).html();
var regex = /type=(\")?([^\"\s]+)(\")?/;
// la regex trouve type=text ou type="text"
// si on ne trouve rien, on ajoute le type à la fin, sinon on le remplace
var tmp = $(html.match(regex) == null ?
html.replace(">", ' type="' + type + '">') :
html.replace(regex, 'type="' + type + '"') );
// on rajoute les vieilles données de l'élément
tmp.data('type', x.data('type') );
var events = x.data('events');
var cb = function(events) {
return function() {
//Bind all prior events
for(i in events) {
var y = events[i];
for(j in y) tmp.bind(i, y[j].handler);
}
}
}(events);
x.replaceWith(tmp);
setTimeout(cb, 10); // On attend un peu avant d'appeler la fonction
return tmp;
}
}
Limites
Mon exemple utilise CSS3. Pour une meilleure prise en charge de l’aspect du bouton, utilisez le principe de dégradation gracieuse en prévoyant une image pour les vieux navigateurs, par exemple.
IE7 et 8 ne reconnaissant pas la validité de la première partie du code JS (la partie « try »), le reste du code permet le changement de type, mais l’information entrée dans le champ de type password
est indépendante de l’information entrée dans le champ une fois passé en type text
.
Pour ceux qui veulent forker le code :
Le code sur CodePen.io
De quelle manière tu as pu voir que l’accès à l’attribut type était « interdit » ?
jQuery semblait empêcher un simple changement de type à mon dernier essai. La doc sur MSDN en parle également (mais c’est bien caché) :
http://msdn.microsoft.com/en-us/library/ie/ms534700%28v=vs.85%29.aspx
Je me souviens avoir eu un problème de ce genre sur un script plus complexe où j’avais dû coder une magnifique boucle pour recréer les éléments dans le DOM (jeux de checkboxes), enfin, c’est une autre histoire, mais IE n’aime pas trop qu’on modifie des choses à la volée dans les champs de formulaire on dirait.
Salut Geoffrey,
Un super article, je pense que c’est une best-practice de proposer d’afficher le mot de passe tappé dans les formulaires.
Je viens de remarquer que le framework metroui.css le propose aussi, as-tu jeté un coup d’œil dessus ? http://metroui.org.ua/forms.php
Passes de bonnes fêtes 🙂
Yo ! Je déterre un vieux truc, mais peut-on l’intégrer sur un forumactif et si oui, accepterais-tu de me dire comment ?
J’suis handi et taper c’est un peu la galère, et honnêtement j’en viens à taper mes mots de passe dans la barre d’adresse parfois pour être sûr de ne pas avoir laissé une lettre-bonus. Donc ça me serait super utile sur mon propre forum.
Quelle que soit la réponse, merci d’avance !
Hello !
Merci pour ton retour d’expérience sur ce type de script/outil.
Je sais forumactif très malléable au niveau du code, mais toucher à leurs formulaires et la galère. Pas d’autre choix que de faire du full-JS.
Peux-tu me donner le lien de ta page de connexion ? Je vais jeter un œil pour t’aider.
Très bonne journée.
Un gros merci Geoffrey
tes tutoriels sont toujours très bons et souvent lorsque j’ai besoin d’un coup de pouce je tombe comme par hasard sur un de tes tutos.
au plaisir de lire d’autres tutos.
Hello,
Merci pour ton message, c’est toujours agréable à lire 🙂
Bonne journée !
Bonsoir à tous. Ça c’est un excellent tutoriel et qui m’aidera bien pour mon projet. Je fouillais des choses sur Google et je suis tombé par hasard ici et c’est vraiment très intéressant. Je viendrais plus souvent par ici.
Bonne soirée à vous, bonne continuation et une fois de plus merci pour ce tutoriel
Salut !
Ce tutoriel ne marche pas pour moi !
J’ai bein mis le css entre deux balises style et le javascript entre les balises script…
Clément
Hello,
Le code est en ligne pour que je puisse regarder ça ?
Merci
Bonjour,
J’ai suivie votre tuto et je le trouve très bien fait! Merci!
J’aurai juste un petit problème, quand je l’applique, une erreur me dit (pour le fichier .js) que le »$ » de la première ligne du .js n’est pas définie.
Auriez-vous une idée de ce qui cloche?
Merci d’avance 😉
Bonjour,
Probablement parce que jQuery n’est pas chargé dans votre page ?
Je ne l’ai effectivement pas précisé, mais j’en fais mention au début de la partie sur JS.
Bon courage 🙂
Bonjour,
Je n’ai pas testé sur tous les navigateurs, mais cela fonctionne déjà sur Chrome, et d’après ton code :
$(‘.unmask’).on(‘mousedown’, function(e){
e.preventDefault()
$(this).prev(‘input’).attr(‘type’, ‘text’)
}).on(‘mouseup’, function(e){
e.preventDefault()
$(this).prev(‘input’).attr(‘type’, ‘password’)
})
J’ai changé le fonctionnement pour que ce ne soit qu’au clic maintenu/relâché que le mot de passe apparaît.
Hello Damien,
En effet les navigateurs ont un peu évolué, et aujourd’hui il est possible de faire beaucoup plus simple sans compter la limitation que l’on avait auparavant.
Merci pour le partage 😉
Bonjour,
Je sais que le sujet est très ancien, mais, ce matin j’ai codé un peu la même chose avant de trouver ton tuto. Par contre, je n’ai pas eu de problème pour changer l’attribut type. Les choses ont changé sûrement. Mais j’ai un nouveau problème :quand on met l’attribut en mode text, Firefox tente de faire l’autocompletion et monté le mot de passe précédemment saisi… Ce qui craint un max !
As-tu une idée ?
Petite différence avec ton tu to v dans mon cas v quand on clique, le mot de passe s’affiche, quand on reclique il repasse en mode masqué.
Merci pour ta réponse et bravo pour le boulot
Bonsoir,
Peut-être qu’avec l’attribut autocomplete= »false » sur le champ cela peut résoudre le problème 🙂