While stumbling through the twittersphere, I ran across an article from UX Movement about watermarking HTML inputs. Naturally, I thought that I would come up with my own jQuery watermark plugin.
I have the code hosted on bitbucket @ https://bitbucket.org/xstoney/watermarklove/src. It is a simple implementation of a watermark control. It allows for the developer to define their own styles for the watermarked text, the field selected watermark text and the style when the watermark has been removed.
Watermark

Input Selected

Input Filled In

There is also the option of marking the field as optional. This would allow for a form that, instead of marking fields that are required, displayed fields that were optional.

First Attempt
This is my first attempt at this plugin. There are several improvements that could be made.
- Fade transition between text modes
- Callback methods for adding/removing/switching out the watermark
- In Google Chrome the text is highlighted in the box but what I would prefer is for the insert point to be placed at the beginning of the text
- Possibly use HTML5 Data attributes to semantically declare the watermark-y-ness of an input
- Watermark a select element
The Code
There are a couple of ways to setup a jQuery plugin. I chose the method where you select the elements that need to be enhanced and call the plugin method for each of these selected elements.
Create the watermark like so:
$("#firstname").watermark({text: "First Name"});
Here is the plugin code.
// Copyright (c) 2011 James Roberts
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(function($){
$.fn.watermark = function(options){
var defaults = {
"style": {"color":"#EDAC80","font-style":"italic","font-weight":"bold"},
"activestyle": {"color":"#EDD8CA","font-style":"normal"},
"normalstyle": {"color":"000000", "font-style":"normal", "font-weight":"normal"},
"optional": false,
"text": ""
};
if(options) { $.extend(defaults, options); }
var wmText = options.text + (defaults.optional ? " (optional)" : "");
var util = {
focus: function(){
if(this.createTextRange){
var range = this.createTextRange();
range.move("character", 0);
range.select();
}
else if(this.selectionStart){
this.focus();
this.setSelectionRange(0, 0);
}
if($(this).val().replace(/^\s+|\s+$/g,"") === wmText){$(this).css(defaults.activestyle);}
},
blur: function(){
var $this = $(this);
if($this.val().replace(/^\s+|\s+$/g,"") === ""){
$this.val(wmText);
$this.css(defaults.style);
} else if($this.val() === wmText){$this.css(defaults.style);}
},
keypress: function(){
var $this = $(this);
if($this.val().replace(/^\s+|\s+$/g,"") === wmText){
$this.val("");
$this.css(defaults.normalstyle);
}
else if($this.val() === ""){$this.val(wmText);}
}
};
return this.each(function(){
var $elm = $(this);
if(options && options.text){
if($elm.val().replace(/^\s+|\s+$/g,"") === ""){
$elm.val(wmText);
$elm.css(defaults.style);
}
$elm.focus(util.focus)
.blur(util.blur)
.keypress(util.keypress);
}
});
};
})(jQuery);