Archive for December 12th, 2011

I hate password masking—hiding what I'm typing to prevent someone from looking over my shoulder at my passwords. I know when I'm in public and when I'm alone in the house, and it should be my choice to actually see what I'm typing, since it has to have some nonsense combination of characters. Even Jakob Nielsen agrees with me.

The logical thing to do is to have a checkbox that would show the characters, and the easiest way to do that is to change the type of the input element from password to text.

For most browsers, this is nontrivial but doable. You have to detach the element first in order to change its type. But in Internet Explorer, there's no way to change it. One solution is to create a new input element with type text and copy all the other attributes into it, but that seems like overkill. All we need is a way for the user to see what he is typing, so a tooltip-like overlay would work.

This is what I came up with (note that it requires jQuery UI position:

<input type="password" id="password"/>
<label><input type="checkbox" id="check"/> Show characters as I type</label>
try{
  $('<input type="password">').detach().attr('type', 'text');
  $.fn.showPassword = function(shouldShow){
    var type =  shouldShow ? 'text' : 'password';
    return this.each(function(){
      /* from http://stackoverflow.com/questions/540851/jquery-change-element-type-from-hidden-to-input */
      marker = $('<span />').insertBefore(this);
      $(this).detach().attr('type', type).insertAfter(marker);
      marker.remove(); 
    });
  };
}catch(e){
  $.fn.showPassword = function(shouldShow){
    return this.each(function(){
      if (shouldShow){
        var span = $(this).siblings('.showPassword');
        if (span.length > 0){
          span.show();
        }else{
          span = $('<span>').addClass('showPassword').css({
            opacity: 0.9,
            background: 'white',
            position: 'absolute',
            fontFamily: 'sans-serif',
            paddingLeft: '2px'
          }).position({
            at: 'left bottom',
            of: this,
            my: 'left top'
          }).text(this.value).insertBefore(this);
          $(this).keyup(function(){ span.text(this.value); });
        }
      }else{
        $(this).siblings('.showPassword').hide();
      }
    });
  };
}
$('#check').change(function(){
  $('#password').showPassword($(this).is(':checked'));
});

Try this in Internet Explorer as well as a standards browser. The details are different, but the functionality is the same.