meta info 
As you can tell by the title, I intend this to be a multi-part series on using moo.fx to create better forms.  In the first installment we are going to create a form that displays a hint to the user about the type of information that is expected in an input box.




What does it look like?



Why does this require its own article? 


Well it probably doesn't but I want these pieces to be modular and if I were to lump too many functions in one article it would be different to separate one piece from another.  I don't like how-to articles that tell you how to build a house when you really want to install a sink so let's keep each article on a more basic level.

Why would you need this?
  • To keep the form simple.
  • To emulate a paper form.
  • Because a web designer invisioned it that way.
  • To march to the beat of a different drummer.

The Code

function getLabelText(id) {
var result = '';

$S('label').action ({
initialize: function(){
if (this.htmlFor == id) {
result = this.firstChild.nodeValue;
}
}
});

return result;
}

function initializeFormElements() {
// Hook up the UI interactions for form elements
$S('input.TEditBox').action ({
initialize: function(){
if(this.value == '') {
this.value = getLabelText(this.id);
Element.addClassName(this, 'TEditBoxCaption');
} else {
Element.addClassName(this, 'TEditBoxLostFocus');
}
},
onblur: function() {
if(this.value == '') {
Element.addClassName(this, 'TEditBoxCaption');
this.value = getLabelText(this.id);
} else {
Element.addClassName(this, 'TEditBoxLostFocus');
}
},
onfocus: function() {
if(this.value == getLabelText(this.id)) {
this.value = '';
}
Element.removeClassName(this, 'TEditBoxCaption');
Element.removeClassName(this, 'TEditBoxLostFocus');
}
});
}


Sample HTML
<form action="/custom/cma" method="post" name="cma_form" id="cma_form" class="cma_form">

<label for="firstName">First Name</label><input type="text" name="firstName" id="firstName" value="" class="TEditBox" />
<label for="lastName">Last Name</label><input type="text" name="lastName" id="lastName" value="" class="TEditBox" />
<label for="email">email</label><input type="text" name="email" id="email" value="" class="TEditBox" />
<label for="address">Address</label><input type="text" name="address" id="address" value="" class="TEditBox" />
<label for="city">City</label><input type="text" name="city" id="city" value="" class="TEditBox" />
<label for="state">State</label><input type="text" name="state" id="state" value="" class="TEditBox" />
<label for="zipCode">Zip Code</label><input type="text" name="zipCode" id="zipCode" value="" class="TEditBox" />
<div class="clear"></div>
<input type="submit" />
</form>

Sample CSS
.TEditBox {
background-color: #ffffcc !important;
margin: 0px 0px 4px 0px;
text-align: left !important;
}


.TEditBoxLostFocus {
background-color: #f4f4f4 !important;
color: #444 !important;
}

.TEditBoxCaption {
background-color: #eaeaea !important;
color: #888 !important;
text-align: right !important;
}

How It Works

To make the form degrade in browsers that don't support JavaScript or don't have it enabled, we place HTML labels next to the input boxes.  Since we don't intend to see these labels, we set the font size to 0 and set the width to a very small value and make them invisible.  A more complete version would swap the CSS using JavaScript to set these values rather than CSS so it would degrade normally but that will be included in part 2 of this series.

Now that the labels exist and are invisible, we call the initialization function from the body load event.  This code locates all the TEditBox class inputs and hooks up the blur and focus events so the input areas can change their appearance automatically.  The nice part about this code is that it will not throw an error if no input boxes are present and it also doesn't need to be rewritten for each new form because it finds the controls that it will change automatically.

So back to part one, the labels were present to help when degrade with the browser but they also exist so the system knows what text to put into the inputs when the control loses focus.  It does this by walking the labels and finding the one that has the 'for' set to the 'id' of the input that we are connected to.

The last part is the class switching that happens when the controls lose focus and regain focus.  To make them stand apart, we have three state.  Focused with data, unfocused with data and unfocused without data.

 

End of side one

This concludes part one of the series.   Part two will refine the degradation and begin introducing Ajax'd validation using moo.ajax.  Stay tuned...

Related Posts
Forms with moo.fx part 2
Yet Another Ajax Contact Page
Ajax Tabs Reloaded: based on the Havoc Studios article
Simple Ajax Code-Kit (fixed)
What happened to...