jQuery Password Mask - DIY
July 17, 2009
I was reading Jakob Nielsen's post Stop Password Masking, which is an interesting read. I like the idea of letting the user decide if they want to be able to see their password or have it masked. There are several jQuery plugins out there which do the job, some of are really clever and mask the password as you type (like mobile phones do).
Then the developer in me kicked in and I decided I should try to write the code myself. I thought I'd post it here to show how the power of jQuery lets you do something like this quite easily.
<html>
<head>
<script type="text/javascript"
src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js">
</script>
<script type="text/javascript">
$(function(){
$('<a href="#" class="passwordmask">show password</a>')
.insertAfter($('input[type=password]'))
.click(function(){
$password = $(this).prev();
$clone = $password.clone();
if ($password.attr('type')=='password')
{
$clone.attr('type','text');
$(this).text('hide password');
}
else
{
$clone.attr('type','password');
$(this).text('show password');
}
$clone.insertAfter($password);
$password.remove();
return false;
});
});
</script>
</head>
<body>
<form>
<input type="text" id="username" name="username" value="username" /><br />
<input type="password" id="password" name="password" value="my-password" /><br />
<input type="submit" id="submit" name="submit" value="login" />
</form>
</body>
</html>
I'm not saying that my code is better than the plugins, I'm sure that this could be refined and improved but it does the job. I just think it's worth learning how to do things in jQuery even if I decide to to use a plugin in my production code.
If you want to know about jQuery then there is a section on the jQuery site for tutorials, I also recommend checking out 40+ Excellent jQuery Tutorials. There is also a sample chapter from the Learning jQuery 1.3 book on the which you can download for free.
Update!
Julian Halliwell pointed out to me that the web developer's favourite browser, Internet Explorer, won't let you change the type attribute. I wanted to add a few features to my code so here is a new version which:
- Works in Internet Explorer
- Hides the password when you submit the form
- Toggles all password fields in the same form
- Only shows one toggle link per form
Anyway, here is the updated version.
<html>
<head>
<script type="text/javascript"
src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js">
</script>
<script type="text/javascript">
$(function(){
// assign a class to all password boxes to make it easy to select
$('input[type=password]').addClass('passwordfield');
// create a link after the first password field in the form
// and assign a click event to it
$('<a href="#" class="passwordmask">show password</a>')
.insertAfter($('form').find('input[type=password]:eq(0)'))
.click(function(){
// create a reference to the clicked link
$clicked = $(this);
// find the form this link is in
$parentform = $clicked.parents('form')
.find('input.passwordfield')
.each(function(i,el){
// create a reference to the password field
$password = $(el);
// IE doesn't support changing the type attribute
// so create a new element (hat tip to Julian Halliwell)
if ($password.attr('type')=='password')
{
$clone = $('<input type="text" />');
$clicked.text('hide password');
}
else
{
$clone = $('<input type="password" />');
$clicked.text('show password');
}
// copy all attributes to clone
var attrs = $password[0].attributes;
// IE throws errors if you try to set type, value or dataFormatAs attributes
if (attrs[i].nodeName!='type'&&attrs[i].nodeName!='value'&&attrs[i].nodeName!='dataFormatAs'){
$clone.attr(attrs[i].nodeName, $password.attr(attrs[i].nodeName));
}
// set required attributes
$clone.attr('class',$password.attr('class'));
$clone.attr('name',$password.attr('name'));
$clone.attr('id',$password.attr('id'));
// set the value
$clone.val($password.val());
// insert clone after the current password box
$clone.insertAfter($password);
// remove the current password box
$password.remove();
})
.end()
.submit(function(){
$theform = $(this);
if($theform.find('input[type=password]').size()==0){
// paswords visible!
$theform.find('.passwordmask').click();
}
return true;
});
return false;
});
});
</script>
</head>
<body>
<form id="form-one">
<label for="username">Username:</label><br />
<input type="text" id="username" name="username" value="username" /><br />
<label for="password">Password</label><br />
<input type="password" id="password" name="password" value="my-password" /><br />
<label for="password">Confirm Password</label><br />
<input type="password" id="passwordconfirm" name="passwordconfirm" value="my-password" /><br />
<input type="submit" id="submit" name="submit" value="login" />
</form>
<form id="form-two">
<label for="username_2">Username:</label><br />
<input type="text" id="username_2" name="username_2" value="username" /><br />
<label for="password_2">Password</label><br />
<input type="password" id="password_2" name="password_2" value="my-password" /><br />
<label for="password_2">Confirm Password</label><br />
<input type="password" id="passwordconfirm_2" name="passwordconfirm_2" value="my-password" /><br />
<input type="submit" id="submit_2" name="submit_2" value="login" />
</form>
</body>
</html>
- Posted in:
- jQuery
10 comments
Leave a comment
If you found this post useful, interesting or just plain wrong, let me know - I like feedback :)





There is a problem with your implementation though: it won't work in IE because the type of an existing input element can't be changed.
The plugin you linked to gets round this by creating a new text input and synching the values with the password input. I found the code a little opaque so like you I decided to write my own:
simplicityweb.co.uk/code/showpassword/
/>
Cheers
Julian.
Comment by Julian Halliwell – July 18, 2009
Comment by John Whish – July 19, 2009
Added a new line :
// copy the class
$clone.attr('class',$password.attr('class'));
becomes :
// copy the class
$clone.attr('class',$password.attr('class'));
$clone.attr('id',$password.attr('id'));
.. and now works great!
Thanks!
Comment by Red Carrot Web Design – October 20, 2009
After using this code my submit button no longer works.
Thanks anyway...
Comment by Red Carrot Web Design – October 20, 2009
Comment by John Whish – October 20, 2009
The submit button works once again, but I have a new problem.
If I have a value in the field, and toggle, the field submitted is empty.
If I don't toggle, the field is not empty.
I really want this to work. I've tried a few plugins, but your code seems to come closest to working.
Comment by Red Carrot Web Design – October 20, 2009
// copy the class $clone.attr('class',$password.attr('class'));
$clone.attr('id',$password.attr('id'));
$clone.attr('name',$password.attr('name'));
Form fields are passed back by name not id
Comment by John Whish – October 20, 2009
The 'id' thing was a seperate issue - my 'id' was required for the form styling, so when I clicked 'show password' my input box would shrink!
With your fix, the 'name' attribute is always present, and so the form submits just fine.
Here is the full fix :
// copy the class
$clone.attr('class',$password.attr('class'));
changes to ...
// copy the class
$clone.attr('class',$password.attr('class'));
// copy the id
$clone.attr('id',$password.attr('id'));
// copy the name
$clone.attr('name',$password.attr('name'));
Thank you for your help!
Comment by Red Carrot Web Design – October 21, 2009
Your script has no effect in FF3.5.5 !?
@John:
Thanks for this post - really!
I'll have to think about it for a while...
Comment by jQuery Agentur – November 17, 2009
Comment by Colin – February 02, 2010