Reusable JavaScript

Here we demonstrate some reusable javascript that puts a "textbox hint" in a field.

We made it reusable by passing parameters such as the element id to it, and by putting the file in a central place (a folder called "js").

References: Tapestry JavaScript, @Import, JavaScriptSupport, Prototype 1.7 API.



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
<!-- We need a doctype to allow us to use special characters like &nbsp; 
     We use a "strict" DTD to make IE follow the alignment rules. -->
<html xmlns:t="">
    <link rel="stylesheet" type="text/css" href="${context:css/examples/js.css}"/>
    <h1>Reusable JavaScript</h1>

    <noscript class="js-required">

    Here we demonstrate some reusable javascript that puts a "textbox hint" in a field.<br/>
    <div class="eg">
        <form t:type="form" t:autofocus="false">
            <input t:type="TextField" t:id="firstName"/>
            <input t:type="TextField" t:id="lastName"/><br/>
    We made it reusable by passing parameters such as the element id to it, and by putting the file in a central place (a folder called "js").<br/><br/>
    <a href="">Tapestry JavaScript</a>, 
    <a href="">@Import</a>, 
    <a href="">JavaScriptSupport</a>,
    <a href="">Prototype 1.7 API</a>.<br/><br/> 
    <a t:type="pagelink" t:page="Index" href="#">Home</a><br/><br/>
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/pages/examples/javascript/ReusableJavaScript.tml"/>
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/pages/examples/javascript/"/>
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/css/examples/js.css"/>
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/js/textbox_hint.js"/>

package jumpstart.web.pages.examples.javascript;

import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.ioc.annotations.Inject;

// The @Import tells Tapestry to put a link to the file in the head of the page so that the browser will pull it in. 
@Import(library = "context:js/textbox_hint.js")
public class ReusableJavaScript {

    // Screen fields

    private String firstName;

    private String lastName;

    // Generally useful bits and pieces

    private JavaScriptSupport javaScriptSupport;

    // The code

    public void afterRender() {

        // Add some JavaScript to the page to instantiate a TextboxHint, twice. It will run when the DOM has been fully
        // loaded.

        javaScriptSupport.addScript(String.format("new TextboxHint('%s', '%s', '%s');", "firstName",
                "Enter First Name", "#808080"));
        javaScriptSupport.addScript(String.format("new TextboxHint('%s', '%s', '%s');", "lastName", "Enter Last Name",



body            { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; color: #333;
                    line-height: 17px; }
h1              { font-size: 26px; line-height: 20px; } /* For IE 7 */
form            { margin: 0; }

.eg             { margin: 20px 0; padding: 20px; color: #888; 
                    border: 1px solid #ddd; border-radius: 4px; -webkit-border-radius: 4px; -mox-border-radius: 4px; }

a               { text-decoration: none; color: #3D69B6; }
a:hover         { text-decoration: underline; }

/* For javascript examples. */
.js-required    { color: red; display: block; margin-bottom: 14px; }
.js-recommended { color: red; display: block; margin-bottom: 14px; }

.grid           { border-collapse: collapse; border-spacing: 0; border: 1px solid #dddddd; font-size: 13px; }
.grid tr.odd        { background-color: #f8f8f8; }
.grid tr:hover      { background-color: #eeeeee; }
.grid th        { padding: 3px 5px; text-align: left; width: 130px; border: 1px solid #dddddd; 
                    font-weight: normal; background-color: #eeeeee; 
                    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbfbfb', endColorstr='#e4e4e4'); /* for IE */
                    background: -webkit-gradient(linear, left top, left bottom, from(#fbfbfb), to(#e4e4e4)); /* for webkit browsers */
                    background: -moz-linear-gradient(top, #fbfbfb, #e4e4e4); /* for firefox 3.6+ */ }
.grid td        { padding: 3px 5px; text-align:left; }


// A TextboxHint observes a field, giving it a "textbox hint" when it is empty and does not have focus.
// Beware: it is flawed because it won't allow the user to submit text that is the same as the hint!
// Written in Protoype style because Tapestry includes the Protoype library (

TextboxHint = Class.create( {

    initialize : function(textboxId, hintText, hintColor) {
        this.textbox = $(textboxId);
        this.hintText = hintText;
        this.hintColor = hintColor;
        this.normalColor = this.textbox.getStyle('color');

        Event.observe(this.textbox, 'focus', this.doClearHint.bindAsEventListener(this));
        Event.observe(this.textbox, 'blur', this.doCheckHint.bindAsEventListener(this));
        Event.observe(this.textbox, 'change', this.doCheckHint.bindAsEventListener(this));
        Event.observe(this.textbox.form, 'submit', this.doClearHint.bindAsEventListener(this));
    doClearHint : function(e) {
        if (this.textbox.value == this.hintText) {
            this.textbox.value = "";
        this.textbox.setStyle({color: this.normalColor});

    doCheckHint : function(e) {
        // If field is empty, put the hintText in it and set its color to hintColor
        if (this.textbox.value.length == 0) {
            this.textbox.value = this.hintText;
            this.textbox.setStyle({color: this.hintColor});
        // Else if field contains hintText, set its color to hintColor
        else if (this.textbox.value == this.hintText) {
            this.textbox.setStyle({color: this.hintColor});
        // Else, set the field's color to its normal color
        else {
            this.textbox.setStyle({color: this.normalColor});

} )