views:

921

answers:

9

I would like to display "password" as text in the password area, and when focused the box should become empty and allow normal password (starred out) input from the user.

Currently I use the following method. Initially I display a text field showing password, when focused it is removed and replaced with a password field. Here is the jQuery:

$(document).ready(function() {
    $("#password").focus( function() {
        $("#pwd").html('<input type="password" id="password" name="password" value="" />');
        $("#password").focus();
    });
});

This works on Firefox and Chrome but fails in IE 8 (and presumably other IE's) as the focus call fails for some reason (maybe the DOM isn't ready?).

A demo is available on jsbin.

Any ideas?

A: 

Why not just change the attribute and wipe out the value?

$("#password").focus( function() {
    $(this).attr('type','password');
    $(this).attr('value','');        
});
seanmonstar
Thanks. I get an obscure "Exception thrown and not caught" error on IE8 when the type is attempted to be set. Maybe IE 8 doesn't support changing the type attribute?
Pool
You can't change the attribute dynamically, for security purposes.
Jack Marchetti
+2  A: 

After realizing my original solution wouldn't work, I spent a while trying to come up with a working solution just out of curiosity. I'd still recommend using the jQuery plugin eKek0 recommended, since it degrades better, though.

The following example is fairly flexible. Rather than hard-coding the replacement <input /> tags as strings, the replacement tags are derived from the original tags. This helps if the <input /> tag attributes are altered, since you won't lose any styling or other attributes given to the tags.

The following solution has been tested in Chrome, Firefox, IE8, and IE8 in IE7 compatibility mode.

$(document).ready(function() { 

    var focusEvent = function() { 
        if(this.type == 'text') {
            var html = $(this).clone().wrap('<span></span>').parent().html();
            html = html.replace(/type=("|')?text("|')?/, 'type="password"');
            var $newPwdBx = $(html);      

            $(this).replaceWith($newPwdBx);
            $newPwdBx.removeClass('readOnly');
            $newPwdBx.val('');
            $newPwdBx.focus();
            $newPwdBx.blur(blurEvent);
        }
    };

    var blurEvent = function() { 
        if(this.value == '') { 
            var html = $(this).clone().wrap('<span></span>').parent().html();
            html = html.replace(/type=("|')?password("|')?/, 'type="text"');
            var $newTxtBx = $(html);            

            $(this).replaceWith($newTxtBx);
            $newTxtBx.addClass('readOnly');
            $newTxtBx.val('password');
            $newTxtBx.focus(focusEvent);
        } 
    };

    $("#password").focus(focusEvent); 
});

This code replaces the <input /> with the appropriate type on blur and focus. It also adds/removes a class for styling the "password" placeholder text so it is more usable, since the placeholder "password" text is not the default black color, which could potentially be misleading to a user.

You can see it working here: http://jsbin.com/azugu

Dan Herbert
Thanks, I do get an error for IE8: "Could not get the type property. This command is not supported." and it does not change to a password field. Does it work OK for you?
Pool
@Nick I guess I should have tested my original answer better before. I've updated my answer to correct these issues. It's working fine now.
Dan Herbert
I've gone with the jquery plug-in but +1 for the effort and an interesting and alternative solution.
Pool
A: 

Try this, experimentally if you will:

$(document).ready(function() {
    $(".pass").focus(function() {
        $pwInput = $('<input type="password" class="pass" name="password" value="" />');
        $(this).remove();
        $("#someDiv').append($pwInput);
    }).focus();
});
karim79
A: 

Why don't you just put a div over the top?

var $pwd = $("#passwordBox"),
    pos = $pwd.position()
;
$pwd
    .after(  // add the div
        $('<div></div>')
            .html("Password")
            .css({
                position : "absolute",    // place it over this
                top : pos.top + "px",  // adjust as necessary
                left : pos.top + "px"
            })
    )
    .next() // select the new div
    .andSelf()
    .one('click focus', function() {
        $pwd.next().remove()    // remove the div
            .end().focus() // focus the input box
        ;
    })
;
nickf
Hehe, two highly untested solutions
karim79
A: 

This works in FF & IE:

$(document).ready(function() {
    $("#password").focus( function() {
        $(this)
          .after('<input type="password" id="password" name="password" value="" />')
          .remove();
        $("#password").focus();
    });
});
Emmett
+4  A: 

You could try the watermarker plugin. I don't know if it works in IE8.

eKek0
Thanks, this does exactly what I require and seems to work fine on all browsers I tested.
Pool
+1  A: 

I have done something similar to this. If you are set on using javascript, this is one way of doing it:

  • Have two input fields, a normal one and a password one
  • The password is hidden with css
  • When normal input gets focus
    • Hide the normal input
    • Show the password input
    • Give focus to the password input

This approach has some problems to consider. If someone has javascript disabled, or is using the NoScript extension for Firefox, they may not be able to submit the form. If someone starts typing before javascript is loaded, there may be unexpected results.

Another approach is to use css and have javascript as a backup (for IE6). Create an image that has text "Password". Have that image be the background image for the password field. You can use pseudo classes in the css to change the background of the password field for hover and . This way, if a person has javascript disabled, the form still works. It also works as soon as the css is loaded.

The CSS might look something like this:

.pass { 
    background-image: url(/path/to/img.png);
}
.pass:hover {
    background: white;
}

Using jquery the javascript might look something like this:

 $( ".pass" ).hover( function() {
     $( this ).css( "background", "white" );
  };
Buddy
+1  A: 

The most common way to achieve this is to set a background image to the password field with the text "password" and remove the background image when it gets the focus.

I.devries
A: 

There is also this txReplaceFormPassword plugin made by Simone Lippolis.

Pons