craft ajax applications using jsf with css and javascript

23
Craft Ajax applications using JSF with CSS and JavaScript, Part 2: Dynamic JSF forms Explore CSS support in standard JSF components Skill Level: Advanced Andrei Cioroianu Senior Java Developer and Consultant Devsphere 12 Feb 2008 In the first article of this two-part series, author and Java™ developer Andrei Cioroianu showed how to use the style attributes of JavaServer Faces (JSF) components and how to set up default values for those attributes. In this second installment of the series, learn how to exercise the JavaScript-related attributes of standard JSF components. Learn several Web techniques based on the Document Object Model (DOM) APIs, JavaScript™, and Cascading Style Sheets (CSS). See how to hide and display optional JSF components without refreshing a Web page, how to implement client-side validation that is executed in the Web browser, and how to develop a custom component that displays help messages for the input elements of a Web form. Handling events and updating the user interface Many JSF HTML components have JavaScript-related attributes that let you specify code fragments, which are executed in the Web browser when a certain UI event happens. For example, there are seven types of mouse events supported by standard JSF components: onmouseover onmouseout Dynamic JSF forms © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 1 of 23

Post on 21-Oct-2014

2.011 views

Category:

Documents


6 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Craft Ajax applications using JSF with CSS and JavaScript

Craft Ajax applications using JSF with CSS andJavaScript, Part 2: Dynamic JSF formsExplore CSS support in standard JSF components

Skill Level: Advanced

Andrei CioroianuSenior Java Developer and ConsultantDevsphere

12 Feb 2008

In the first article of this two-part series, author and Java™ developer AndreiCioroianu showed how to use the style attributes of JavaServer Faces (JSF)components and how to set up default values for those attributes. In this secondinstallment of the series, learn how to exercise the JavaScript-related attributes ofstandard JSF components. Learn several Web techniques based on the DocumentObject Model (DOM) APIs, JavaScript™, and Cascading Style Sheets (CSS). Seehow to hide and display optional JSF components without refreshing a Web page,how to implement client-side validation that is executed in the Web browser, and howto develop a custom component that displays help messages for the input elementsof a Web form.

Handling events and updating the user interface

Many JSF HTML components have JavaScript-related attributes that let you specifycode fragments, which are executed in the Web browser when a certain UI eventhappens. For example, there are seven types of mouse events supported bystandard JSF components:

• onmouseover

• onmouseout

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 1 of 23

Page 2: Craft Ajax applications using JSF with CSS and JavaScript

• onmousemove

• onmousedown

• onmouseup

• onclick

• ondblclick

When a UI component gains or loses the keyboard focus, it generates events thatcan be captured through the onfocus and onblur attributes. The onkeydown,onkeyup, and onkeypress events are fired when a key is pressed or released. Inaddition, the <h:form> component accepts the onsubmit and onreset attributes,and the input components have the onchange and onselect attributes, which canbe used to call a JavaScript function when the form element's state changes.

You can also use JavaScript-related attributes of the HTML elements that aredirectly included in a JSF page instead of being rendered by JSF components. Forexample, the <body> tag has the onload and onunload attributes. The onloadevent is fired when the loading of a page is completed in the Web browser. Theonunload event occurs when the user leaves the page.

A typical JavaScript event handler uses DOM APIs in the Web browser to update theproperties of the HTML elements rendered by JSF components. You can easilylocate the objects representing the HTML elements using the DOM Core API. Forexample, you can use document.getElementById(...) to find an elementwhose ID is known.

The DOM HTML API extends the DOM Core API, adding methods and propertiesspecific to HTML documents. Use document.forms.myFormId to get the objectrepresenting a form in the Web browser, and then obtain an array of objectsrepresenting the form's elements with myForm.elements. A very useful property isclassName, which allows you to change the class attribute of an HTML element.

The DOM HTML specification (see Resources) describes all standard properties andmethods of the objects representing elements of a page on the client side. MostWeb browsers, including IE, Firefox, Netscape, Safari, and Opera, support additionalproperties, such as innerHTML, which let you change the contents of an HTMLelement.

The examples in this section show how to use the JavaScript-related attributes ofJSF HTML components and how to update the user interface using the DOM HTMLAPI.

Placing scripts within JSF pages

JavaScript code can be inserted in a JSF page as in any regular Web page, using

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 2 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 3: Craft Ajax applications using JSF with CSS and JavaScript

the <script> element of HTML (see Listing 1). You could use JavaScript code togenerate HTML content with document.write() in the Web browser, but this israrely needed. In most cases, you will place the <script> elements within thepage's header, which will contain the JavaScript functions called from the eventattributes, such as onclick, onsubmit, and onchange. You can also use the<noscript> element to warn users if JavaScript is disabled in their browsers.

Listing 1. Using the <script> tag

<html><head>

<script type="text/javascript">function myEventHandler(...) {

...}

</script></head><body>

<noscript>This page requires JavaScript.

</noscript>...

</body></html>

Apache MyFaces TobagoIf you prefer using JSF components instead of HTML tags, youcould use the <tc:script> component of MyFaces Tobago,which renders the <script> element for you.

Place your JavaScript code in .js files if you want to call the same functions inmultiple pages. External scripts must be imported in the Web pages, using the srcattribute of the <script> tag (see Listing 2). In this case, make sure the /faces/prefix isn't added to the script's URL, which can happen if you use a relative URIwithin the src attribute. The simplest way to avoid this issue is to use the .facessuffix. If you prefer the /faces/ prefix for requesting JSF pages, specify anabsolute URI for the JavaScript file, including the context path within the srcattribute of the <script> tag.

Listing 2. Importing external scripts

<script type="text/javascript"src="${pageContext.request.contextPath}/scripts/MyScript.js">

</script><script type="text/javascript"

src="<%=request.getContextPath()%>/AnotherScript.js"></script>

Hiding and displaying optional JSF components

In Part 1 of this series, you saw how to set the style classes of JSF components on

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 3 of 23

Page 4: Craft Ajax applications using JSF with CSS and JavaScript

the server side by using the styleClass attribute. You can also set or change styleclasses on the client side by using JavaScript and DOM. The following exampleshows how to collapse and expand a group of optional components using thedisplay CSS property. A simple search form (see Figure 1) contains a requiredtext field, two check boxes, and a drop-down list. When the user checks MoreOptions, the panel containing the Match Case and Language components isdisplayed. If the user unchecks More Options, the optional components arecollapsed.

Figure 1. SearchForm example

The SearchForm.jsp example (see Listing 3) uses standard JSF components tobuild the Web from. The optional components are placed within a <h:panelGrid>container which is rendered as an HTML table. The optional panel is made visible orhidden on the client side using a JavaScript function namedupdatePanelClass(). As its name indicates, this function changes the style classof the <table> element rendered by <h:panelGrid>. TheupdatePanelClass() function is invoked every time the user changes the statusof the check box labeled More Options because the updatePanelClass() call is

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 4 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 5: Craft Ajax applications using JSF with CSS and JavaScript

coded within the onclick attribute of the <h:selectBooleanCheckbox>component.

Listing 3. The SearchForm.jsp example

<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %><%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

<f:view><html><head>

<title>Search Form</title>...

</head><body onload="initForm()">

<h1>Search Form</h1><h:form id="searchForm">

<h:panelGrid columns="1" border="0" cellspacing="5"><h:panelGroup>

<h:outputLabel value="Text: " for="text"/><h:inputText id="text" value="#{searchBean.text}"

required="true" requiredMessage="Required" size="20"/><h:message for="text"/>

</h:panelGroup><h:panelGroup>

<h:selectBooleanCheckbox id="moreOptions"value="#{searchBean.moreOptions}"onclick="updatePanelClass()"/>

<h:outputLabel value="More Options" for="moreOptions"/></h:panelGroup><h:panelGrid id="optionsPanel"

columns="1" border="0" cellspacing="5"><h:panelGroup>

<h:selectBooleanCheckbox id="matchCase"value="#{searchBean.matchCase}"/>

<h:outputLabel value="Match Case" for="matchCase"/></h:panelGroup><h:panelGroup>

<h:outputLabel value="Language: " for="language"/><h:selectOneMenu id="language" value="#{searchBean.language}">

<f:selectItem itemValue="English" itemLabel="English"/><f:selectItem itemValue="Spanish" itemLabel="Spanish"/><f:selectItem itemValue="French" itemLabel="French"/>

</h:selectOneMenu></h:panelGroup>

</h:panelGrid><h:commandButton id="search" value="Search"

action="#{searchBean.searchAction}"/></h:panelGrid>

</h:form></body></html></f:view>

The HTML produced by the SearchForm.jsp page is shown in Listing 4. Observehow the standard JSF components add the searchForm: prefix to the IDs of theHTML elements rendered by the components nested within the JSF form whose IDis searchForm.

Listing 4. HTML produced by the SearchForm.jsp

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 5 of 23

Page 6: Craft Ajax applications using JSF with CSS and JavaScript

<html><head>

<title>Search Form</title>...

</head><body onload="initForm()">

<h1>Search Form</h1>

<form id="searchForm" name="searchForm" method="post"action="/jsf12js/SearchForm.faces"enctype="application/x-www-form-urlencoded">

...<table border="0" cellspacing="5"><tbody><tr><td><label for="searchForm:text">Text: </label><input id="searchForm:text" type="text"

name="searchForm:text" size="20" /></td></tr><tr><td><input id="searchForm:moreOptions" type="checkbox"

name="searchForm:moreOptions" checked="checked"onclick="updatePanelClass()" />

<label for="searchForm:moreOptions">More Options</label></td></tr><tr><td><table id="searchForm:optionsPanel" border="0" cellspacing="5"><tbody><tr><td><input id="searchForm:matchCase" type="checkbox"

name="searchForm:matchCase" /><label for="searchForm:matchCase">Match Case</label></td></tr><tr><td><label for="searchForm:language">Language: </label><select id="searchForm:language" name="searchForm:language" size="1">

<option value="English">English</option><option value="Spanish">Spanish</option><option value="French">French</option>

</select></td></tr></tbody></table></td></tr><tr><td><input id="searchForm:search" type="submit"

name="searchForm:search" value="Search" /></td></tr></tbody></table>...</form></body></html>

Listing 5 shows the <style> element of the SearchForm.jsp page whose headercontains both style classes and JavaScript functions. The visible class just setsthe left margin of the optional panel and doesn't need any other settings because theHTML table is displayed by default. The hidden class sets the display CSSproperty to none, turning off the display of the table.

Listing 5. The style classes of SearchForm.jsp

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 6 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 7: Craft Ajax applications using JSF with CSS and JavaScript

<style type="text/css">.visible { margin-left: 40px; }.hidden { display: none; }

</style>

The updatePanelClass() function (see Listing 6) locates thesearchForm:moreOptions checkbox and the searchForm:optionsPaneltable with document.getElementById(). The panel object represents the<table id="searchForm:optionsPanel"> element rendered by<h:panelGrid id="optionsPanel">, and the checkbox object represents the<input id="searchForm:moreOptions"> element rendered by<h:selectBooleanCheckbox id="moreOptions">. TheupdatePanelClass() function gets the status of the checkbox object from thechecked DOM property and sets the style class of the panel table, using theclassName DOM property.

Listing 6. The updatePanelClass() function of SearchForm.jsp

function updatePanelClass() {var checkbox = document.getElementById("searchForm:moreOptions");var panel = document.getElementById("searchForm:optionsPanel");panel.className = checkbox.checked ? "visible" : "hidden";

}

The header of the SearchForm.jsp page also contains the initForm() function(shown in Listing 7) whose call is coded within the onload attribute of the <body>element. This function locates the text field of the form and calls focus(), so thatwhen the page is loaded in the browser, the user can start entering the text withouthaving to click the component first. Then, initForm() callsupdatePanelClass() to initialize the optional panel's class.

Listing 7. The initForm() function of SearchForm.jsp

function initForm() {var text = document.getElementById("searchForm:text");text.focus();updatePanelClass();

}

The values of the input components from the SearchForm.jsp example are boundto the properties of a simple bean, and the Search button triggers an action methodnamed searchAction(). The code of the SearchBean class is shown in Listing8.

Listing 8. The SearchBean class

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 7 of 23

Page 8: Craft Ajax applications using JSF with CSS and JavaScript

package jsfcssjs;

public class SearchBean implements java.io.Serializable {private String text;private boolean moreOptions;private boolean matchCase;private String language;

public SearchBean() {}

public String getText() {return text;

}

public void setText(String text) {this.text = text;

}

...

public String searchAction() {System.out.print("Text: " + text);if (moreOptions) {

if (matchCase)System.out.print(", Match Case");

System.out.print(", Language: " + language);}System.out.println();return null;

}

}

Implementing client-side validation

The JSF framework provides several validators that run on the server side. When aJSF validator finds an error, the form is returned to the user so he or she can correctit. To minimize the failed form submissions, you can use JavaScript code to verifythe user input on the client side, too. The following example shows how to test themaximum length of the data entered in a text-area component. The current length isalso shown as the user types the text. When the user clicks the Submit button, aJavaScript function is used to verify the input.

ClientValidation example

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 8 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 9: Craft Ajax applications using JSF with CSS and JavaScript

Using the maxlength attributeThe <h:inputText> component allows you to limit the length ofthe entered data with the maxlength attribute. Unlike thesingle-line input field, the multi-line <h:inputTextarea>component doesn't have a maxlength attribute because therendered <textarea> tag of HTML doesn't support it.

The JSF form of the ClientValidation.jsp example (see Listing 9) contains a<h:inputTextarea> component that uses the onkeyup attribute, so a JavaScriptfunction named validateText() is called every time the user presses a key. Thisfunction is also invoked once the page is loaded in the browser because the onloadattribute of the <body> tag contains the validateText() call. Even if the userinput is validated on the client side, the <h:inputTextarea> component uses therequired attribute and the <f:validateLength> validator to verify the enteredtext on the server-side, too—just in case JavaScript is disabled in the user'sbrowser. Server-side validation is also necessary to defend against malicious users.

Listing 9. The ClientValidation.jsp example

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 9 of 23

Page 10: Craft Ajax applications using JSF with CSS and JavaScript

<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %><%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

<f:view><html>...<body onload="validateText()">

<h1>Client-Side Validation</h1><h:form id="validForm" onsubmit="return validateForm()">

<h:panelGrid columns="1" border="0" cellspacing="5"><h:panelGroup>

<h:outputText value="Text (max #{textBean.maxLength} chars): "/><f:verbatim><span id="charCount"></span></f:verbatim>

</h:panelGroup><h:panelGroup>

<h:inputTextarea id="textArea" value="#{textBean.text}"required="true" rows="5" cols="30"onkeyup="validateText()">

<f:validateLength maximum="#{textBean.maxLength}"/></h:inputTextarea><h:message for="textArea"/>

</h:panelGroup><h:commandButton id="submit" value="Submit"

action="#{textBean.submitAction}"/></h:panelGrid>

</h:form></body></html></f:view>

The validateText() function (shown in Listing 10) locates the page's form withdocument.forms.validForm and gets the object representing the text area withform.elements["validForm:textArea"]. Then, the JavaScript code tests thelength of the entered text and returns an error message if the user input isn't valid. Inaddition, validateText() shows the current length by setting the innerHTMLproperty of the <span id="charCount"> element fromClientValidation.jsp. The style class is also updated, using the classNameDOM property of the span element.

Listing 10. The validateText() function of ClientValidation.jsp

<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %><%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

<f:view><html><head>

<title>Client-Side Validation</title><style type="text/css">

.valid { color: green; }

.error { color: red; }</style><script type="text/javascript">

function validateText() {var form = document.forms.validForm;var textArea = form.elements["validForm:textArea"];var length = textArea.value.length;var maxLength = <h:outputText value="#{textBean.maxLength}"/>;var error = null;if (length == 0)

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 10 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 11: Craft Ajax applications using JSF with CSS and JavaScript

error = "Text cannot be empty.";else if (length > maxLength)

error = "Text cannot have more than "+ maxLength + " characters."

var span = document.getElementById("charCount");span.innerHTML = length;span.className = (error == null) ? "valid" : "error";return error;

}...

</script></head>...</html></f:view>

The maxLength variable is initialized in the JavaScript code from Listing 10, usingthe property with the same name of a bean whose ID is textBean. The value of thisproperty is specified in the faces-config.xml file (see Listing 11).

Listing 11. Configuring TextBean in faces-config.xml

<faces-config xmlns="http://java.sun.com/xml/ns/javaee" ... version="1.2">

<managed-bean><managed-bean-name>textBean</managed-bean-name><managed-bean-class>jsfcssjs.TextBean</managed-bean-class><managed-bean-scope>request</managed-bean-scope><managed-property>

<property-name>maxLength</property-name><value>100</value>

</managed-property></managed-bean>...

</faces-config>

The ClientValidation.jsp example contains a second JavaScript functionnamed validateForm() (see Listing 12). This function is invoked when theSubmit button is clicked. Observe the return keyword used within the onsubmitattribute of <h:form>, right before the validateForm() call. If the returned valueis false, meaning that the user input isn't valid, the Web browser doesn't submitthe form data to the server. This is the desired result because validateForm()signals the error to the user with alert(), and there is no point to submit the invalidinput.

Listing 12. The validateForm() function of ClientValidation.jsp

function validateForm() {var error = validateText();if (error)

alert(error);return error == null;

}

If the user input is valid, validateForm() returns true and the Web browser

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 11 of 23

Page 12: Craft Ajax applications using JSF with CSS and JavaScript

submits the form data to the server where the JSF framework invokes thesubmitAction() method of the TextBean class (see Listing 13).

Listing 13. The TextBean class

package jsfcssjs;

public class TextBean implements java.io.Serializable {private String text;private int maxLength;

...

public String submitAction() {System.out.println("Length: " + text.length());return null;

}

}

The maximum length validation implemented above for the <h:inputTextarea>component is coded within the ClientValidation.jsp example. This was thesimplest way to do it, but the code is not reusable without changes. Whenimplementing features that are not specific to a particular page, it is a good idea tomove the JavaScript code into external .js files so you can call their functions fromany page of the application. In addition, you can develop custom JSF components toset up JavaScript-based mechanisms, and you can even add custom attributes tothe existing components. The next section shows how to implement generic UIfeatures that enhance the standard JSF components.

Using custom attributes to enable new UI features

Part 1 of this series showed you how to build a custom component for setting thedefault styles of JSF components. In this section, you'll see how to use the sametechnique for setting JavaScript-related attributes. In addition, the samplespresented here use a custom attribute, which is added with the <f:attribute> tagto standard JSF components.

Developing the custom JSF component

Next, you'll see how to build a custom component that modifies the onfocus andonblur attributes of every nested component that contains <f:attributename="helpOnFocus" value="..."> (see Listing 14). The JavaScriptexpressions of the onfocus and onblur attributes are evaluated in the Webbrowser when a form element gains and loses the keyboard focus. The customcomponent, whose tag is named <js:helpOnFocus>, changes the onfocusattribute of each nested input component to show a help message within a <divid="helpOnFocus"> element when the rendered <input> element gains thefocus. The onblur attribute of the nested component is also changed to clear the

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 12 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 13: Craft Ajax applications using JSF with CSS and JavaScript

help message when the <input> element loses the keyboard focus.

Listing 14. Using the <js:helpOnFocus> component in a JSF page

<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %><%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %><%@ taglib prefix="js" uri="/js.tld" %>...<script type="text/javascript" src=".../HelpOnFocus.js"></script>...<js:helpOnFocus>

...<h:inputText ...>

<f:attribute name="helpOnFocus" value="... Help message ..."/></h:inputText>...

</js:helpOnFocus>...<div id="helpOnFocus"></div>...

The SetupComponent class, which was presented in Part 1, traverses the JSFcomponent tree, allowing you to change the attributes of the nested componentsright before their rendering. The HelpOnFocusComponent class (see Listing 15)extends SetupComponent and implements the setup() method, which is calledfor every nested component whose rendered property is true. ThegetAttribute() method retrieves the value of a single attribute from thecomponent's attribute map. The insertCall() method includes a function callwithin the given attribute, preserving any existing value. Nothing is done if theattribute already contains the function call, which happens when the applicationreturns the same form to the user after a post. In this case, the custom componenthas already added the onfocus and onblur attributes to the nested componentsduring the processing of a previous request. The attributes already contain theJavaScript calls because the JSF framework saves the state of all componentsbetween requests.

Listing 15. The HelpOnFocusComponent class

package jsfcssjs;

import javax.faces.component.UIComponent;import javax.faces.context.FacesContext;

import java.util.Map;

public class HelpOnFocusComponent extends SetupComponent {

protected void setup(FacesContext ctx, UIComponent comp) {Map<String, Object> attrMap = comp.getAttributes();String helpOnFocus = getAttribute(attrMap, "helpOnFocus");if (helpOnFocus != null) {

String helpParam[] = new String[] {EncodeUtils.encodeString(helpOnFocus).toString() };

insertCall(attrMap, "onfocus", "showHelpOnFocus", helpParam);

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 13 of 23

Page 14: Craft Ajax applications using JSF with CSS and JavaScript

insertCall(attrMap, "onblur", "clearHelpOnBlur", null);}

}

protected String getAttribute(Map<String, Object> attrMap, String attrName) {Object attrValue = attrMap.get(attrName);if (attrValue != null)

return attrValue.toString();else

return null;}

protected void insertCall(Map<String, Object> attrMap, String attrName,String functionName, String functionParams[]) {

String attrValue = getAttribute(attrMap, attrName);if (attrValue != null && attrValue.indexOf(functionName) != -1)

return;StringBuilder buf = EncodeUtils.encodeCall(

functionName, functionParams);if (attrValue != null && attrValue.length() > 0) {

buf.append(';');buf.append(attrValue);

}attrMap.put(attrName, buf.toString());

}

public String getFamily() {return "HelpOnFocus";

}

}

The HelpOnFocus.js file (shown in Listing 16) contains theshowHelpOnFocus() and clearHelpOnBlur() functions, whose invocations arecoded within the onfocus and onblur attributes. The setInnerHTML() functioninserts the given content within the HTML element with the given id.

Listing 16. The HelpOnFocus.js file

function setInnerHTML(id, content) {document.getElementById(id).innerHTML = content;

}

function showHelpOnFocus(msg) {setInnerHTML("helpOnFocus", msg);

}

function clearHelpOnBlur() {setInnerHTML("helpOnFocus", "");

}

Like any custom JSF component, HelpOnFocusComponent must be configured infaces-config.xml (see Listing 17).

Listing 17. Configuring HelpOnFocusComponent in faces-config.xml

<faces-config xmlns="http://java.sun.com/xml/ns/javaee" ... version="1.2">...<component>

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 14 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 15: Craft Ajax applications using JSF with CSS and JavaScript

<component-type>HelpOnFocusComponent</component-type><component-class>jsfcssjs.HelpOnFocusComponent</component-class><component-extension>

<component-family>HelpOnFocus</component-family></component-extension>

</component>

</faces-config>

Listing 18 shows the HelpOnFocusTag class, which implements the tag handler forthe custom component. The UIComponentELTag base class is part of the JSF 1.2API. If you want to use the custom component in a JSF 1.1-based application, thesuperclass of the tag handler must be UIComponentTag.

Listing 18. The HelpOnFocusTag class

package jsfcssjs;

import javax.faces.webapp.UIComponentELTag;

public class HelpOnFocusTag extends UIComponentELTag {

public String getComponentType() {return "HelpOnFocusComponent";

}

public String getRendererType() {return null;

}

}

The name and attributes of the custom tag are specified in the js.tld file (shown inListing 19). The HelpOnFocusTag handler doesn't have any setter methods for itsattributes because it inherits them from UIComponentELTag.

Listing 19. The js.tld file

<?xml version="1.0" encoding="UTF-8" ?><taglib xmlns="http://java.sun.com/xml/ns/javaee" ... version="2.1">

<tlib-version>1.0</tlib-version><short-name>js</short-name><uri>/js.tld</uri><tag>

<name>helpOnFocus</name><tag-class>jsfcssjs.HelpOnFocusTag</tag-class><body-content>JSP</body-content><attribute>

<name>id</name><required>false</required><rtexprvalue>true</rtexprvalue>

</attribute><attribute>

<name>binding</name><required>false</required><deferred-value>

<type>jsfcssjs.HelpOnFocusComponent</type></deferred-value>

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 15 of 23

Page 16: Craft Ajax applications using JSF with CSS and JavaScript

</attribute><attribute>

<name>rendered</name><required>false</required><deferred-value>

<type>boolean</type></deferred-value>

</attribute></tag>

</taglib>

JavaScript encoding utilities

The HelpOnFocusComponent class presented above uses the helper methodsprovided by the EncodeUtils class. The encodeString() method (see Listing20) escapes the backspace, TAB, CR, LF, and non-ASCII characters so the returnedvalue can be used as a string literal in the JavaScript code. In addition, the ", &, <,and > characters are replaced with &quot;, &amp;, &lt;, and &gt; so theencoded string can be included within the HTML page. Two quote characters areused as delimiters. For example, if you pass abc \ " & < > [TAB] [LF] [CR]123 to encodeString(), the returned value will be "abc \\ &quot; &amp;&lt; &gt; \t \n \r 123".

Listing 20. The encodeString() method of the EncodeUtils class

package jsfcssjs;

public class EncodeUtils {

public static StringBuilder encodeString(String str) {if (str == null)

return null;StringBuilder buf = new StringBuilder();buf.append('"');int n = str.length();for (int i = 0; i < n; i++) {

char ch = str.charAt(i);switch (ch) {

case '\\': buf.append("\\\\"); break;case '\'': buf.append("\\\'"); break;case '"': buf.append("&quot;"); break;case '&': buf.append("&amp;"); break;case '<': buf.append("&lt;"); break;case '>': buf.append("&gt;"); break;case '\t': buf.append("\\t"); break;case '\r': buf.append("\\r"); break;case '\n': buf.append("\\n"); break;default: {

if (' ' <= ch && ch <= '~')buf.append(ch);

else {buf.append("\\u");for (int j = 3; j >= 0; j--) {

int h = (((int) ch) >> (j*4)) & 0x0f;buf.append((char) (h<10 ? '0'+h : 'a'+h-10));

}}

}}

}

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 16 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 17: Craft Ajax applications using JSF with CSS and JavaScript

buf.append('"');return buf;

}...

}

The encodeCall() method (see Listing 21) builds a function call using the givenparameters.

Listing 21. The encodeCall() method of the EncodeUtils class

public class EncodeUtils {...public static StringBuilder encodeCall(

String functionName, String functionParams[]) {StringBuilder buf = new StringBuilder();buf.append(functionName);buf.append('(');if (functionParams != null)

for (int i = 0; i < functionParams.length; i++) {if (i > 0)

buf.append(',');buf.append(functionParams[i]);

}buf.append(')');return buf;

}

}

For a better understanding of the encoding methods, consider the example fromListing 22, which contains an input component that already has an onfocusattribute. A helpOnFocus attribute is also added to this component with<f:attribute> and the whole form is wrapped by a <js:helpOnFocus>component.

Listing 22. String encoding example

<% request.setAttribute("msg", "abc \\ \" & < > \t \n \r 123"); %>...<js:helpOnFocus>

<h:form><h:inputText ... onfocus="alert('focus')">

<f:attribute name="helpOnFocus" value="#{msg}"/></h:inputText>

</h:form></js:helpOnFocus>...<div id="helpOnFocus"></div>...

When the page is executed, the <js:helpOnFocus> component traverses thenested component tree and sets the onfocus and onblur attributes to display andclear the help message. Listing 23 shows the HTML that is rendered by the JSF

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 17 of 23

Page 18: Craft Ajax applications using JSF with CSS and JavaScript

components. The onfocus attribute contains the showHelpOnFocus() call alongwith the alert('focus') expression from the example shown in Listing 22. The &characters and the " delimiters of the encoded string are escaped one more time bythe <h:inputText> component, which encodes the values of its own attributes.

Listing 23. Encoded string

<form ...>...<input ... onblur="clearHelpOnBlur()"

onfocus="showHelpOnFocus(&quot;abc \\ &amp;quot; &amp;amp;&amp;lt; &amp;gt; \t \n \r 123&quot;);alert('focus')" />...</form>...<div id="helpOnFocus"></div>...

When the Web browser parses and decodes the piece of HTML from Listing 23, thevalue retrieved from the onfocus attribute is showHelpOnFocus("abc \\&quot; &amp; &lt; &gt; \t \n \r 123");alert('focus'). The browserpasses this code to its JavaScript engine, which calls the showHelpOnFocus()function that inserts abc \ &quot; &amp; &lt; &gt; [TAB] [NL] [CR]123 within the <div id="helpOnFocus"> element of the Web page, and thebrowser shows abc \ " & < > 123.

The developerWorks Ajax resource centerCheck out the Ajax resource center, your one-stop shop for freetools, code, and information on developing Ajax applications. Theactive Ajax community forum, hosted by Ajax expert JackHerrington, will connect you with peers who might just have theanswers you're looking for right now.

Using the custom component in a JSF page

The HelpOnFocus.jsp page (see Listing 24) is another example that uses the<js:helpOnFocus> component. The JSF form contains three input components: atext field, a checkbox, and a drop-down list. All these components use the<f:attribute> tag to specify help messages.

Listing 24. The HelpOnFocus.jsp example

<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %><%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %><%@ taglib prefix="js" uri="/js.tld" %>

<f:view>...<script type="text/javascript"

src="<%=request.getContextPath()%>/HelpOnFocus.js"></script>...

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 18 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 19: Craft Ajax applications using JSF with CSS and JavaScript

<js:helpOnFocus>...<h:inputText id="text" ...>

<f:attribute name="helpOnFocus"value="Enter the text you want to search for."/>

</h:inputText>...<h:selectBooleanCheckbox id="matchCase" ...>

<f:attribute name="helpOnFocus"value="Distinguish between lowercase and uppercase

characters."/></h:selectBooleanCheckbox>...<h:selectOneMenu id="language" ...>

...<f:attribute name="helpOnFocus"

value="Select the language of the searched text."/></h:selectOneMenu>...<f:verbatim>

<div id="helpOnFocus"></div>

</f:verbatim>...

</js:helpOnFocus>...

</f:view>

Listing 25 shows the HTML produced by the HelpOnFocus.jsp page.

Listing 25. HTML generated by HelpOnFocus.jsp

...<script type="text/javascript"

src="/jsf12js/HelpOnFocus.js"></script>...<input id="searchForm:text" type="text" ... onblur="clearHelpOnBlur()"

onfocus="showHelpOnFocus(&quot;Enter the text you want to search for.&quot;)"/>...<input id="searchForm:matchCase" type="checkbox" ... onblur="clearHelpOnBlur()"

onfocus="showHelpOnFocus(&quot;Distinguish between lowercase and uppercase\r\n characters.&quot;)" />

...<select id="searchForm:language" ... onblur="clearHelpOnBlur()"

onfocus="showHelpOnFocus(&quot;Select the language of the searched text.&quot;)">...

</select>...<div id="helpOnFocus"></div>...

Conclusion

Share this...

Diggthis

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 19 of 23

Page 20: Craft Ajax applications using JSF with CSS and JavaScript

story

Posttodel.icio.us

Slashdotit!

This article showed you how to develop JavaScript event handlers that update theHTML rendered by JSF components. It introduced several Web techniques,including:

• Setting the className property to change the value of the classattribute

• Using the innerHTML property to insert some content within a HTMLelement

• Hiding and displaying JSF components with CSS

• Implementing client-side validation with JavaScript

It also showed you how to use custom attributes in conjunction with a wrappercomponent for adding new features to existing JSF components.

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 20 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 21: Craft Ajax applications using JSF with CSS and JavaScript

Downloads

Description Name Size Download method

Sample application for this article jsfcssjs_p2.zip 30KB HTTP

Information about download methods

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 21 of 23

Page 22: Craft Ajax applications using JSF with CSS and JavaScript

Resources

Learn

• "Craft Ajax applications using JSF with CSS and JavaScript, Part 1" introducesthe CSS support provided by standard JSF components. It also explains howJSF component trees are built and how you can add features such as defaultstyles.

• Auto-save JSF forms with Ajax is a three-part series that presents additionalJavaScript and JSF techniques.

• The developerWorks Web development zone is packed with tools andinformation for Web 2.0 development.

• The developerWorks Ajax resource center contains a growing library of Ajaxcontent as well as useful resources to get you started developing Ajaxapplications today.

• The JSF 1.2 Specification fully describes the JavaServer Faces technology.

• Visit developer.mozilla.org if you are looking for JavaScript tools anddocumentation.

• You can find more CSS-related resources on the Cascading Style Sheets homepage.

Get products and technologies

• Get the DOM Core and DOM HTML specifications from www.w3C.org

• Get the JSF RI source code and binaries from javaserverfaces.dev.java.net

• Apache MyFaces Project is another popular JSF implementation.

Discuss

• Participate in the discussion forum for this content.

About the author

Andrei CioroianuAndrei Cioroianu is the founder of Devsphere, a provider of Java EE developmentand Ajax/JSF consulting services. He's been using Java and Web technologies since1997 and has 10 years of professional experience in solving complex technicalproblems and managing the full life cycle of commercial products, customapplications, and open source frameworks. You can reach Andrei through the contactform at devsphere.com.

developerWorks® ibm.com/developerWorks

Dynamic JSF formsPage 22 of 23 © Copyright IBM Corporation 1994, 2007. All rights reserved.

Page 23: Craft Ajax applications using JSF with CSS and JavaScript

Trademarks

Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in theUnited States, other countries, or both.

ibm.com/developerWorks developerWorks®

Dynamic JSF forms© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 23 of 23