markupboy

A Better Method for Clearing Default Form Input Values

Penned on .

A while back I wrote a quick post on how to clear default form values on click. Using jQuery, we leveraged the "defaultValue" variable associated with each input object and on focus simply checked whether the current value equalled the defaultValue. If it did, we cleared it, easy as that.

Unfortunately, that's not as semantic as it could be (even less so if we're not already using a label). On top of that when the form is submitted we have to check every form element we've handled this way and clear it out if it hasn't been set; if we don't, the default values will end up getting submitted.

Using an alternate method we can get around this altogether:

Start with a basic, completely semantic text-input with a label

<p class="input_group">
    <label for="find_a_location">Find a Location</label>
    <input type="text" name="find_a_location"
        value="" id="find_a_location"></input>
</p>

The input is as plain as it gets, with a name and an id. The label's nothing too special either, just make absolutely sure the 'for' attribute matches the inputs id. The last piece is that I've gone ahead and wrapped the two in another tag and classed it "input_group". This doesn't have to a paragraph tag (a span or li would work just as well), but know that whatever you use will end up having to act a block level element for the positioning of the label.

No CSS

Next, a dash of CSS to pretty things up a bit. Start by styling the input itself; not terribly necessary, but certainly makes everything more attractive:

input {
    width: 350px;
    border: 10px solid #e2e1d4;
    font-size: 14px;
    padding: 7px;
    outline: none;
    border-radius: 7px;
    -webkit-border-radius: 7px;
    -moz-border-radius: 7px;
}

input:focus {
    border: 10px solid #9c836e;
}

Adding the :focus pseudo-class helps to draw a users attention to the active field.

Next we need to set up the input_group so that we can position the label correctly:

p.input_group {
    width: 350px;
    margin: 1em auto;
    position: relative;
}

And finally, drop the label over the input, giving the appearance that it's actually inside the input:

label {
    font-size: 14px;
    font-family: verdana;
    position: absolute;
    top: 19px;
    left: 19px;
}

We can even give the label a focus class (that will be triggered by javascript later) to push the illusion even further:

label.focus {
    opacity: 0.2;
    -moz-opacity: 0.2;
    filter:alpha(opacity=20);
}

Full CSS

The last piece of the puzzle: the experience layer thanks to JavaScript.

Get started by looping through all the fields we want to set up:

$('p.input_group input').each(function() {

Set up some variables we'll need for later (mainly storing the label that points to this input):

    var id = $(this).attr('id'),
            $label = $('label[for='+id+']');

On page load, if there's already a value in the input, hide the label (this fixes an issue if the user hits the back button and the field is already filled):

    if($(this).val() != '') {
        $label.hide();
    }

When the input is focussed, add a 'focus' class to the label:

    $(this).focus(function() {
        $label.addClass('focus');
    });

When the input is blurred, remove that 'focus' class

    $(this).blur(function() {
        $label.removeClass('focus');
    });

When a key that adds to the input's value value (any letter, number or other ascii character) is pressed, hide the label because the user is actively typing in the field.

    $(this).bind('keydown', function(e) {
        if(e.keyCode >= 48 ) {
            $label.hide();
        }
    });

When any key is release, check the value; if it's blank, show the label again. This means when a user delete or backspaces through the field, cut's all the text or does anything to blank it out the label comes back

    $(this).bind('keyup', function() {
        if($(this).val() == '') {
            $label.show();
        }
    });

And close out the loop

});

No CSS

That's all there is to it. One thing to note, this isn't meant to be a replacement for the original method, merely an alternative. There are situations where one will definitely be more viable than the other. Just use whatever works best.

Check out the demo here