After reading Jakob Nielsen’s post, “Stop Password Masking”, I really wanted to develop a quick and easy jQuery plugin which provided the ability to toggle a field between a masked and unmasked versions.
Stop Password Masking (Jakob Nielsen’s Alertbox)
Argument Against Masking
Nielsen argues that masking passwords doesn’t actually increase security. Instead, it could actually end up “[costing] you business due to login failures”. While masking may not actually increase security, it does provide additional privacy when a user is in a public environment. Nobody wants to have their banking password, for example, read from over their shoulder while they’re working at a library.
To be able to provide a masked input for the privacy concerns, as well as allowing the user to turn off the masking, we can utilize JavaScript to change the input from type password to type text, and vice-versa.
IE Woes
As usual, IE throws a wrench in the whole deal and doesn’t allow changing the type via jQuery’s attr method, so I had to go another route.
First we define our variables, and assuming target is the current input element. $target is the jQuery object found with the target selector, attrs is a NamedNodeMap of the elements attributes, and $field is our future text or password input field.
Node.attributes at Mozilla Developer Center
var $target = $(target),
attrs = $target[0].attributes,
$field = $(document.createElement('input'));
Then I would determine which attributes are currently assigned to the existing input (doesn’t matter whether it’s currently a type text or password), and then assign each attribute to the new element.
By using attrs[i].specified we only copy over those elements which are currently in the list of elements. In IE < 8 it seems that all attributes, no matter if they’re currently specified in the tag or not, get returned by the attributes accessor, so we need to weed out any unspecified attributes.
We’ll save doing type and value for later as well:
for (var i = 0; i < attrs.length; i++) {
if (attrs[i].specified
&& attrs[i].nodeName != 'type'
&& attrs[i].nodeName != 'value') $field.attr(attrs[i].nodeName, attrs[i].nodeValue);
}
If the current input is of type password, we set the new one to be text, and vice-versa. Also, let’s make use of jQuery’s val function to set the value of the new input field.
$field.attr('type', $target.is(':password') ? 'text' : 'password')
.val($target.val());
Finally, I would replace the current element with the new one.
$target.replaceWith($field);
And all together now as a jQuery function:
(function($) {
$.fn.passwordtoggle = function(target) {
return this.each(function() {
$(this).click(function() {
var $target = $(target),
attrs = $target[0].attributes,
$field = $(document.createElement('input'));
// because IE doesn't allow you to change the "type" of an input element, have to do it this way
// use the HTML DOM's attributes object to provide insight into what attributes exist for this element
for (var i = 0; i < attrs.length; i++) {
if (attrs[i].specified && attrs[i].nodeName != 'type' && attrs[i].nodeName != 'value') $field.attr(attrs[i].nodeName, attrs[i].nodeValue);
}
$field.attr('type', $target.is(':password') ? 'text' : 'password').val($target.val());
$target.replaceWith($field);
return false;
});
});
};
})(jQuery);
Summary
Going by Jakob Nielsen’s advice and providing the opportunity to switch between a password and text field, plus some fun JavaScript work, we can build a jQuery function which handles all the heavy-lifting for us. This (somewhat) simple JavaScript function increases usability on websites and hopefully will help you retain lost business where users may end of leaving your site out of frustration.
Tags: attributes, forms, intermediate, Jakob Nielsen, JavaScript, jQuery, password, toggle
