1. Introduction

Rcfaces or Rich Client Faces is a JavaServerFaces library that provides a set of components for building modern Web applications. Rcfaces uses AJAX technologies and an object-oriented JavaScript API to simplify the building of highly interactive user interfaces.

This open source (GNU LGPL License) library has been developed by Vedana since the summer 2004.

Rcfaces is currently used by a French public organisation for a major project :

over 3000 users

Average page loading time under 1.5 seconds

The distinctive advantages of Rcfaces are :

Ability to create desktop-like applications that run inside the browser.

Simplify the use of potentially complex technologies like AJAX and JavaScript.

"On the fly" client-side field validation.

Rich set of components

Ability to customize the look and feel of components through skins, behaviors and capabilities.

These Projects can be imported into eclipse as WTP projects. Right click/import/WEB>WAR File.

src: The RCfaces source libraries

For integration build:

You must download one of the core JAR file (e.g. rcfaces-core-jsf1_2-I2554.jar ) and the corresponding html jar (e.g. rcfaces-html-jsf1_2-I2554.jar). Both jars are required.

You will also find the source code for each implementation (e.g. rcfaces-core-src-jsf1_2-I2554.jar and rcfaces-html-src-JSF1_2-I2554.jar), and documentation for java source code, Javascript and TLD (rcfaces-javadoc-JSF1_2-I2554.jar., rcfaces-jsdoc-JSF1_2-I2554.jar and rcfaces-tlddoc-JSF1_2-I2554.jar).

The rcfaces-imageIO-*.jar is used by Rcfaces to generate on the fly multiple versions of an image (hover, disabled, scaled, ...).

3.2 Your first Rcfaces application

The goal of this tutorial is to create a simple form and add results in a grid. This will give you a quick overview of Rcfaces.

This project was built with Eclipse Galileo and Apache Tomcat 6. The Eclipse workspace is available for download here.

These two declarations are the minimum requirement for the web.xml file. Rcfaces supports many other parameters to improve its performance. For further configuration, read part 6: Rcfaces configuration.Final version of web.xml :

3.5 Create a managed bean

We want to add data from a form into a data grid, so we need to build a JSF managed bean to get fields value and put them in the table's data model. The best-practice solution would be to create two managed beans; however, for this simple demo, one will suffice.

Create a java object named GridBean in the org.rcfaces.rcfacesformsample.managed package :

package org.rcfaces.rcfacesformsample.managed;

import java.text.DateFormat;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import org.rcfaces.core.event.SelectionEvent;

publicclass GridBean {

privatestaticfinal DateFormat dateFormat = new SimpleDateFormat(

"dd/MM/yyyy");

private List<Row> rows; // Data model of dataGrid

private Row newRow; // Use by the form field

public GridBean() {

rows = new ArrayList<Row>();

rows.add(new Row("Didier", "La Rochelle", "1/1/1882"));

rows.add(new Row("Fred", "La Rochelle", "02/02/1901"));

rows.add(new Row("Olivier", "La Rochelle", "11/4/1975"));

rows.add(new Row("Christine", "La Rochelle", "4/12/1980"));

rows.add(new Row("Jean-Marc", "La Rochelle", "4/12/1980"));

rows.add(new Row("JB", "La Rochelle", "1/8/2000"));

}

// called by the actionListner of submit button

publicvoid addRow(SelectionEvent event) {

rows.add(new Row(newRow.getName(), newRow.getCity(), newRow

.getBirthDate()));

newRow = null;

}

public List<Row> getRows() {

returnrows;

}

publicvoid setRows(List<Row> rows) {

this.rows = rows;

}

public Row getNewRow() {

if (newRow == null) {

newRow = new Row();

}

returnnewRow;

}

publicvoid setNewRow(Row newRow) {

this.newRow = newRow;

}

publicclass Row {

private String name;

private String city;

private Date birthDate;

public Row() {

}

public Row(String name, String city, String birthDate) {

this.name = name;

this.city = city;

try {

this.birthDate = dateFormat.parse(birthDate);

} catch (ParseException ex) {

thrownew IllegalArgumentException(ex);

}

}

public Row(String name, String city, Date birthDate) {

this.name = name;

this.city = city;

this.birthDate = birthDate;

}

public String getName() {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

public String getCity() {

returncity;

}

publicvoid setCity(String city) {

this.city = city;

}

public Date getBirthDate() {

returnbirthDate;

}

publicvoid setBirthDate(Date birthDate) {

this.birthDate = birthDate;

}

}

}

Each JSF managed bean must be registered in the faces-config.xml file :

3.6 Create a JSP

In web.xml file, we mapped the Faces Servlet with the url pattern like "*.jsf", therefore the welcome file index.jsp must do a forward to a *.jsf page to enter the JSF context :

<?xmlversion="1.0"encoding="UTF-8"?>

<jsp:rootversion="2.0"xmlns="http://www.w3.org/1999/xhtml"

xmlns:jsp="http://java.sun.com/JSP/Page">

<jsp:forwardpage="form.jsf"/>

</jsp:root>

form.jsp source code :

<?xmlversion="1.0"encoding="UTF-8"?>

<jsp:rootversion="2.0"xmlns="http://www.w3.org/1999/xhtml"

xmlns:jsp="http://java.sun.com/JSP/Page"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:v="http://rcfaces.org/core"xmlns:vh="http://rcfaces.org/html">

<jsp:directive.pagecontentType="text/html"pageEncoding="UTF-8"/>

<jsp:outputomit-xml-declaration="true"doctype-root-element="html"

doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"

doctype-system="http://www.w3.org/TR/html4/loose.dtd"/>

<f:view>

<html>

<head>

<vh:init/> <!-- !important tag -->

</head>

<vh:javaScriptCollector>

<body>

<h:form>

<v:fieldSettext="Form">

<!-- container -->

<divstyle="margin-top: 10px;">

What is your name :

<v:messagefor="field1"showDetail="false"showSummary="true"

showIfMessage="true"/>

<v:textEntryid="field1" columnNumber="30"

value="#{gridBean.newRow.name}" required="true"/>

</div>

<divstyle="margin-top: 10px;">

Where do you come from :

<v:messagefor="field2"showDetail="false" showSummary="true"

showIfMessage="true"/>

<v:textEntryid="field2" columnNumber="30"

value="#{gridBean.newRow.city}" required="true"

emptyMessage="your city"/>

</div>

<divstyle="margin: 10px 0;">

When were you born :

<v:messagefor="fieldDate"showDetail="false"showSummary="true"

showIfMessage="true"/>

<v:dateEntryid="fieldDate"value="#{gridBean.newRow.birthDate}"

required="true"/>

<v:dateChooserid="date"for="fieldDate"/>

</div>

<v:submitButtontext="submit"actionListener="#{gridBean.addRow}" />

</v:fieldSet>

<divstyle="margin-top: 10px;">

<v:dataGridid="tableId"

width="450"value="#{gridBean.rows}" var="row"rows="3">

<v:dataColumntext="Name"sortListener="alpha"value="#{row.name}" />

<v:dataColumntext="city"sortListener="alpha"value="#{row.city}" />

<v:dataColumntext="BirthDate"value="#{row.birthDate}"

alignment="center"/>

</v:dataGrid>

<v:pagerfor="tableId"></v:pager>

</div>

</h:form>

</body>

</vh:javaScriptCollector>

</html>

</f:view>

</jsp:root>

In the header element of this page, there is a tag <vh: init />. This tag is compulsory for Rcfaces so don't forget it. If your application uses template like Tiles or Facelet, this tag can be placed in the header of the main page.

Please note that this sample is done without additional css styles. All components will have the default Rcfaces look and feel. To customize the look and feel, see part 11. Customize Components

Run the RcfacesFormSample web project as server application and point your browser to this URL : http://localhost:8080/RcfacesFormSample/

You should see :

4. Rcfaces architecture overview

4.1 JSF enhancements

The aim of Rcfaces is to offer a rich set of components that makes it easier to build rich and professional Web applications.

To build those components, Rcfaces extends the base JSF specifications to offer additional features :

4.2 Object-oriented and aspect-oriented JavaScript framework

The strength of Rcfaces is its object-oriented JavaScript framework which makes use of aspect-oriented programming concepts (AOP).

This framework creates a strong relationship between the HTML components and their JavaScript associated classes.

A Rcfaces component automatically loads all the required classes through the class inheritance and the aspects it implements. The use of AOP also reduces the size of generated JavaScript source code on the client side. For example, most components use functions such as getValue(), isDisabled(), isRequired(), isEditable(), setStyleClass() and more. These functions are declared as aspects of the components.

The JavaScript framework offers a symetrical API for components : client side API and server side API. Each component has the same methods and properties in JavaScript (client side) and in Java (server side). Whenever a JSF page is submitted, all the modified properties are synchronized automatically with the server side.

To enable fast rendering of the JSF pages, Rcfaces is able to load all the JavaScript framework within a special hidden frame so that the browser does not need to reload the framework on each page refresh.

4.3 AJAX Engine

The AJAX engine is integrated in the Rcfaces JavaScript API. Ajax is used by complex components and allows to minimize page refreshes for :

DataGrid pagination

DataGrid sorting

Datagrid popups

Combo search results

Tree rendering

show boxes, expand bars and tabbed panes

show error messages

load image

progressbar animation

popups

5. Components List and Feature

For a complete description and demo of each component go to rcfaces.org. You will find javadoc, javascript-doc and TLD-doc.

Each component have some capabilities and inherit some javaScript classes.

Setting the parameter "GROUP_ALL_FILE" to "false" will result in having all the files loaded but not gathered in a unique file (default value is true).

The goal (GROUP_ALL_FILE=true) is to improve loading of resources by concatenating the javasript and CSS ressources into single files. The load time of this unique resource will be shorter than the combined loading time of the individual component ressources.

6.1.2 Rcfaces Application version

The size of HTTP exchanges tends to increase with modern Web applications.

To minimize the network traffic, Rcfaces can add expiration dates to the static resources (JavaScript, css, images, ...) used by JSF components.

With expiration dates, the browser or the proxy server will put the Rcfaces resources in a cache and will not make additional requests for those resources.

The main problem with this mechanism resides in the deployment of a new version of an application. If the cached resources have been modified, there is normally no way to tell the proxy or the browsers to clear their cache immediatly !

The role of the Application Version Servlet (AVS) is to get around this problem. To do so the AVS manages HTTP header for each Rcfaces resource (Last Modified, Expires date, a special calculation of Etag and the content-MD5 attributes). It will also change the URL of the resources whenever a new version of an application is deployed. The change of URL will force the browser and the proxy server to get a new version of all the resources used by an application.

Note: If the size of resource is greater than 512ko, the AVS will automatically use gzip compression over HTTP.

6.1.3 Rcfaces Application dynamics Contents

Rcfaces provides a servlet to manage Css file. The first role of this servlet is to merge all the CSS files needed by an application in a single file. This limits the number of files loaded by the web browser.

The generation of this single CSS file can be a time-consuming task. To maximize the application performance, the Application Content Servlet caches the generated CSS file in memory.

Another functionality of the Application Content Dynamics Servlet is to dynamically modify images.

The servlet allows to :

Change colors depending on the image state.

Change contrast and brightness for differents type of image files.

Resize images.

Convert an image to another format (JPEG, GIF, PNG and ICO).

Sample page that uses the dynamic image features of the servlet :

<v:imageimageURL="images/back64.gif"/>

<v:imageimageURL="hover::images/back64.gif"/>

<v:imageimageURL="disabled::images/back64.gif"/>

<v:imageimageURL="selected::images/back64.gif"/>

<v:imageimageURL="gray::images/back64.gif"/>

<v:imageimageURL="contrast(0.6)::images/back64.gif"/>

<v:imageimageURL="brithness(-0.6)::images/back64.gif"/>

<v:imageimageURL="scale(0.5)::images/back64.gif"/>

<!--size in px -->

<v:imageimageURL="resize(50)::images/back64.gif"/>

<v:imageimageURL="setSize(80,150)::images/back64.gif" />

<v:imageCheckButton

imageURL="images/home.gif"

hoverImageURL="hover::"

disabledImageURL="disabled::"

selectedImageURL="selected::"

/>

<v:imageCheckButtondisabled="true"

imageURL="images/home.gif"

disabledImageURL="disabled::"

/>

<!--GIF to JPEG -->

<v:imageimageURL="jpeg(quality=1)::images/babelfish.gif"/>

<!--JPEG to JPEG -->

<v:imageimageURL="jpeg(quality=0.7)::images/babelfish.jpg"/>

<!--JPEG to GIF -->

<v:imageimageURL="gif::images/babelfish.jpg"/>

<!--JPEG to PNG -->

<v:imageimageURL="png::images/babelfish.jpg"/>

<!--GIF to PNG -->

<v:imageimageURL="png::images/babelfish.gif"/>

Results :

original hover disabled selected gray

contrast brithness scale resize setsize

6.1.4 Rcfaces Client bundle

Internationalization is an important feature for a web based application. JSF standard tag <f:loadBundle> allows to perform basic internationalization. However, it isn't available for JavaScript programming.

Rcfaces client bundle servlet's goal is to make the resources bundle available for JavaScript Programming.

6.2 Development Parameters

This part describes all the parameters which can be used during the development stage.

6.2.1 Activate The JavaScript console

The Javascript console is displayed inside the browser window at development time. It displays client-side messages that shows the application progress and protential errors.

To display the JavaScript console, follow these instructions :

In the web.xml, add the following lines (context parameters) :

<...web-app>

...

<context-param>

<param-name>org.rcfaces.renderkit.html.client.DEBUG_MODE</param-name>

<param-value>true</param-value>

</context-param>

<context-param>

<param-name>org.rcfaces.renderkit.html.client.ENABLE_LOG</param-name>

<param-value>true</param-value>

</context-param>

<context-param>

<param-name>org.rcfaces.core.client.DEFAULT_LOG_LEVEL</param-name>

<param-value>debug</param-value>

</context-param>

....

</web-app>

In jsp file :

<vh:javaScriptrequiredClasses="f_consoleAppender"/>

The console is displayed in the browser window (top right corner) :

6.2.2 Disable cache

These option allows to disable caching of generated resources on the server and the client. It is useful when debugging custom javascripts and stylesheets. We strongly advice to disable caching on the client sider at development time.

Name

Default

Description

org.rcfaces.renderkit.html.NO_CACHE

False

Disable cache for Stylesheet and Javascript servlet

org.rcfaces.renderkit.html.JSP_DISABLE_CACHE

False

set tag META HTTP-EQUIV cache-control and pragma to no cache.This directive indicates cached information should not be used and instead requests should be forwarded to the origin server. And Set EXPIRES to 0 that may thus be used to force a modification check at each visit.

org.rcfaces.renderkit.html.javascript.REPOSITORY_DEV_MODE

False

Regenerate javascript repositories for each request.

org.rcfaces.core.NO_CACHE

False

Change HTTP META Tag like JSP_DISABLE_CACHE but int servlet response.

org.rcfaces.core.contentStorage.DISABLE_CACHE

False

Disable cache of the content storage servlet.

6.3 Runtime Parameters

These parameters allow to optimize the behavior of the application when you deploy them :

Name

Default

Description

org.rcfaces.core.LITERAL_LOCAL

None

List of default supported language

org.rcfaces.core.GZIP_SUPPORT

True

Allow Rcfaces to ZIP resources when they are biger than 512ko

org.rcfaces.core.EXPIRES

Week

Default life time of resources in browser cache.

org.rcfaces.core.VERSIONED_EXPIRES

Year

For versioned resources. i.e.:37w and resources expire after 37 week.

org.rcfaces.core.APPLICATION_VERSION

None

This parameter can either take the value Hascode: URI of values are made with their hascode, or the value Now: made a random value with ce current time in millisecond, or specified value i.e.: "v1.0.3".

org.rcfaces.core.ETAG_SUPPORT

True

Manage or not the HTTP header value Etag: this attribute is used to determine change in content at a given URL

org.rcfaces.core.HASH_SUPPORT

True

Add the Content-MD5 entity-header field to pass through proxies and gateways

org.rcfaces.renderkit.html.CONFIGURATION_VERSION

None

Select a specific version i.e: 1.0.3

org.rcfaces.renderkit.html.CONFIGURATION_VERSION_SUPPORT

Can be set to False to forbid css version repoisitories

org.rcfaces.core.RESOURCE_PROXY_DEFAULT_URL

None

In load balacing configuration this parameter allows to specify the default address where the application is deployed to load resources trough this application server in priority. Otherwise, a user could load file each time that they will request an other server.

org.rcfaces.core.RESOURCE_PROXY_RULES_PATH

None

Some rules to get ressources

org.rcfaces.core.ENABLE_FILTERED_RESOURCE_PROXY

False

Accept ressource proxy

org.rcfaces.core.ENABLE_FRAMEWORK_RESOURCE_PROXI

False

Accept ressource proxy

org.rcfaces.core.LISTENER_MANAGER_STRATEGY

default

Allow to manage life of listener during the application wokflow. Decide when listener are added and cleaned. There are four Strategy: DEFAULT append listener at each navigation without control,CLEAN_ALL is used with facelet to remove all listener when a component is reused.CLEAN_BY_CLASS delete all listener class by class before add a new. ADD_IF_NEW add listener if it doesn't always exist.

6.4 Module Parameters

Web applications are all different, that's why CSS and javaScript of components can be changed (see part 11: Customize Components). Rcfaces allows to gather its own CSS or JavaScript files in bigger files (modules) to optimize loading of resources.

6.4.1 Create a CSS repository

In the same package where you created the new CSS files (a good practice is to separate css for each component), create a XML file named repository.xml. All of our CSS files will be gathered in different modules

repository.xml example :

<?xmlversion="1.0"encoding="UTF-8"?>

<repositoryid="CssApp"

baseDirectory="com/myproject/jsf/rcfaces/css">

<moduleid="myCssModule">

<filename="rcfaces.css"/>

<filename="button.css"/>

<filename="ie_cadreRegroupement.css"/>

<filename="combo.css"/>

<filename="grid.css"/>

<filename=grid_ie.css"userAgent="ie"/>

<filename="ie_hyperlink.css"/>

<filename="menuHorizontal.css"/>

<filename="menuVertical.css"/>

</module>

</repository>

Note: the baseDirectory attribute of the <repository> node is the package where this file is saved.

6.4.2 Create a JavaScript repository

In the javascript file package container, create another file named repository.xml which looks like this :

<?xmlversion="1.0"encoding="UTF-8"?>

<repositoryid="js"

baseDirectory="com/myproject/jsf/rcfaces/js"

convertSymbols="true">

<moduleid="MyJsModule">

<filename="menuHorizontal.js">

<classname="ie_menuHorizontal">

<required-classname="f_component"/>

<required-classname="fa_disabled"/>

<required-classname="fa_readOnly"/>

<required-classname="fa_selectionManager"/>

<required-classname="fa_items"/>

<required-classname="fa_itemClientDatas"/>

</class>

</file>

<filename="menuVertical.js">

<classname="pe_menuVertical">

<required-classname="f_tree"/>

<required-classname="fa_items"/>

<required-classname="fa_itemClientDatas"/>

</class>

</file

[…]

<filename="messages.js">

<classname="ie_messages">

<required-classname="f_messageContext"/>

<required-classname="f_messageObject"/>

<required-classname="f_messages"/>

</class>

</file>

</module>

</repository>

Note : JavaScript classes are instances of f_class or fa_aspect object created by the API.

6.4.3 Register a Repository in Rcfaces context and Use it

The next step is to register these repositories in the Rcfaces context. In the base directory src, make a META-INF folder containing a XML file named rcfaces-config.xml with the following content:

<?xmlversion="1.0"encoding="UTF-8"?>

<rcfaces-config>

<repositories>

<repository>

<type>javascript</type>

< location>com/myproject/jsf/rcfaces/js/repository.xml</location>

</repository>

<repository>

<type>css</type>

<location>com/myproject/jsf/rcfaces/css/repository.xml</location>

</repository>

</repositories>

</rcfaces-config>

Finally, in a JSP file:

<header>

<vh:init />

<vh:cssStylerequiredModules="MyCssModule"/>

<vh:javaScriptrequiredModules="MyJsModule"/>

</header>

After that, stylesheets and JavaScript are integrated in Rcfaces context for having a better resource management.

Note : These tags must be inside the html <head> tag.

6.5 JavaScript optimization

The page loading time must be as small as possible, and this time depends on the size of JavaScript source code the browser loads and how the functions are called.

6.5.1 JavaScriptCollector Tag

This tag allows to gather all the <SCRIPT> HTML tags in only one. Some browser (i.e: Internet Explorer) could have a loss of performance when they have too many <SCRIPT> tag on the same page. The best way to use the <vh:javaScriptCollector> tag is :

<?xmlversion="1.0"encoding="UTF-8"?>

<jsp:root

version="2.0"

xmlns="http://www.w3.org/1999/xhtml"

xmlns:jsp="http://java.sun.com/JSP/Page"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:v="http://rcfaces.org/core"

xmlns:vh="http://rcfaces.org/html"

xmlns:layout="http://jakarta.apache.org/struts/tags-tiles">

<jsp:directive.page

contentType="text/html"

pageEncoding="UTF-8"/>

<layout:importAttributescope="request"/>

<f:view>

<jsp:output

omit-xml-declaration="true"

doctype-root-element="html"

doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"

doctype-system="http://www.w3.org/TR/html4/loose.dtd"/>

<htmllang="fr">

<jsp:directive.includefile="_header.jspf"/>

<vh:javaScriptCollector>

<body>

<h:formid="ecranGlobal">

<jsp:directive.includefile="_body.jspf"/>

<!-- Menu Horizontal -->

<divclass="zoning_menuHorizontal">

<f:subviewid="menuHorizontal">

<jsp:includepage="${menuHorizontal}" flush="false"/>

</f:subview>

</div>

[...]

</h:form>

</body>

</vh:javaScriptCollector>

</html>

</f:view>

</jsp:root>

6.5.2 Compiled Versions of the Rcfaces runtime

There are two special versions of rc-faces-html.jar with different compilation parameters to improve size and loading time of the JavaScript runtime :

Version

Size

Loading Time

HTML

1

1

Free

HTMLC

0.22

0.6

Free

HTMLC3

0.26

0.33

Premium

These jar file will be put in the WEB-INF/lib folder of your application. They replace the rc-faces-html.jar file. We advise not to use them at development time as they make the debugging of the client-side scripts much harder. Use them at application-deployment time.

7 Basic use of the RCFaces Javascript API

The RCFaces Javascript framework is the base of its advanced graphical user interface.

In order to create an application with RCFaces, it is important to understand the events thrown by the listeners when you select a data, expand a tree, drag an element or press a key.

When you develop an event handler, you must use the RCFaces API and the f_event object to access the page components and change their state. Use only the public APIs (mainly f_*) to avoid problems with the optimized javascript library.

7.1 How to use the object f_event in a RCFaces event.

When RCFaces throws an event, an instance of the object f_event is instanciated. This Object is created with the native javascript event object provided by the browser enriched with other informations specific to RCFaces likes: the component, the type of event, the selected item, a value and others... This event object usually provides the entry point to work with the API in a custom javascript method.

7.1.1 Find Component with the event object

Example : opening a ViewDialog when clicking on a button

<v:viewDialog

id="idPopup"

width="450"

text="Title popup"

height="180"

visible="false"

viewURL="$context/popup/bodyPopup.jsf"

hiddenMode="client"/>

<v:buttontext="Open popup"

selectionListener="return showViewDialog(event, 'idPopup');"/>

The selection listener of this button calls the "showViewDialog" function with the javascript event object and the view dialog component id.

The "showViewDialog" function is defined in the jsp or within an external javascript file included in the page :

function showViewDialog(event, idViewDialog) {

var button = event.f_getComponent();

var viewDialog = event.f_findComponent(idViewDialog);

viewDialog.f_open(function(returnValue) {

button.f_setDisabled(returnValue);

});

returnfalse;

}

The RCFaces event allows to find the viewDialog component (f_findComponent) and call its public f_open method. It will also change the button disabled state based on the return value of the viewDialog (here : bodyPopup.jsp). The return value is given as the second parameter of the CloseShell function.

The event object contains the selected item as its item (f_getItem method).

The event's item may have specifics attribute, for example a tree item can be opened or not.

The f_tree class provides an item state via a specific function "f_isOpened" which takes an item as parameter.

7.1.3 The f_event public methods

Name

Description

f_getType()

Returns the type of event

f_getJsEvent()

Returns the Javascript event if any

f_getItem()

Returns the item associated to the event

f_getComponent()

Returns the component associated to the event

f_getValue()

Returns the value of the item associated to the event

f_findComponent()

Search for and return the {@link f_component} with an id that matches the specified search expression (if any).

f_findSiblingComponent()

Search for and return the sibling {@link f_component} with an id that matches the specified search expression (if any).

7.2 The most important function in f_core class

f_core is a class which has several public static functions. These functions can be used at any time in your scripts. It is possible to find a component anywhere in a page without having an event object. The following table shows several public static functions of the class f_core:

Name

Description

Assert(expr, message)

Throws a message if the expression is true

Debug (name, message, exception, win)

add log

FindComponent(id, doc)

Find a child in the main page by its identifier. (The naming separator IS ':')

GetElmentByClientId(id, doc,

Find a child by its identifier. (The naming separator might not be ':')

GetCookieValue (cookieName, doc)

Returns String value associated to the cookie

GetDocumentSize(values, doc)

Returns the size of the document

GetViewSize(values, doc)

Returns the size of the View

GetViewPosition (doc)

Returns the position of the Window

SetFocus(component, asyncMode)

give focus to a component

ShowVersion()

return RC-Faces version

ValidateForm(component)

valide form of the component in parameter

To call these static public functions, use this syntax: f_core.GetElementByclientID.

When you develop your own components and associated classes, you are entitled to use hidden functions like : CreateElement, GetAttribute or GetJsEvent. Theses functions may not be used in standard page scripts (they will not be available at runtime).

7.3 Create a new RCFaces Javascript Class

Each component is linked to a javascript class. During a development some components can be created or other already existing can evolve therefore it is important to know how to create a RCFaces javascript class.

The RCFaces javascript API relies on an original architecture which allows to create classes that can inherit from another class and also use "aspects" thanks to the Prototype framework.

Each class can have a static part and a member part with class attributes and methods.

In this example, the class f_scheduler extends f_component and has two aspects: fa_items and fa_selectionManager.

Static and member variables are declared in the two __statics and __members variables. The call of "new f_class()" initialize the f_scheduler class declaration : inheritance, aspects, static and member parts.

When a JSF component is rendered in a page, the javascript framework will create an instance of this new class. This object is associated with the HTML component.

The new javascript object can be used inside event handlers. You must only use the public component methods and properties and not try to access directly the HTML component. The framework use the @method annotation to know which methods are public. The JSDoc documentation tool will also use the @... annotations when building the component's documentation.

8. The service component and AJAX request

The service component is a non-visual component, it allows to call server-side code from javascript thanks to the AJAX service. A POJO method, which is register as a managed bean can be invoked in synchronous or asynchronous mode without JSF page navigation.

8.1 Component declaration

The service component can be declared at any time in the JSP and several service tags can be declared in the same page.

The following example performs an AJAX based "Hello world" :

JSP :

<v:service

id="myAjaxService"

serviceEventListener="#{myBean.getResults}" />

<v:buttontext="Call Service"

selectionListener="return callService(event, 'myAjaxService',

'resultService','world');"/>

<v:textid="resultService"/>

The id attribute of the service tag allows to find the service component with the javaScript RCFaces API. The "serviceEventListener" attribute allows to bind the service with a method of a managed bean.

The managed bean is called by the function f_synCall which return the result of the java method declared in the serviceEventListener attribute.

You should be aware that using this mode with Firefox will block the user interface.

8.2.2 Asynchronous mode

The asynchronous mode is the preferred mode and is more natural in AJAX. The service component still calls the serviceEventListener, but instead of returning the result directly, a callback function will be called :

callService: function(p_Event, idService, idResult, otherParam) {

var servComp = p_Event.f_findComponent(idService);

if (servComp) {

servComp.f_asyncCall(myCallBack ,//myCallBack is a function

{param1:idResult, param2:otherParam});

}

}

The function f_asyncCall take a callback function as its first parameter. It will be the function called by the ajax engine. The second parameter is a map that is used to send parameters to the server side code, these parameters are also provided to the callback function.

8.3 Get asynchronous response in callback

The last step with asynchronous mode is to get the response within the callback. The callback function must have three parameters : a status to know if the work is done or in progress, a map of parameter (The map put in f_asyncCall) and the result object.

The example function source code:

myCallback: function(status, params, result) {

if(status!=f_service.LOADED_STATE) {

return;

}

var resComp = f_core.GetElementByClientId(params['param1']);

if (resComp) {

resComp.f_setText(result);

}

}

Type of response setted in the param result can be a primitive type or any type of object.

9. Client Validators

Client validators are used in web forms to check and validate user entry in specific fields which either must respect some rules or have a format or must be converted before sending data to the server. It is mostly used to check fields like Email , credit card, password, phone number, etc...

9.1 How it works

A Client Validator is an attribute of the TextEntry component. The validator is a piece of JavaScript code that is called when a component lose its focus or when it changes its value. The validator is also called when a form is submitted on the server side during the generate response steps of JSF cycle.

A validator consists of fiyrdifferent parts :

Filter: validate each character with a regular expression.

Translator: Format each character i.e: upper case, see if separator is accepted or replace it.

Checker: Check validity of data. For exemple checking syntax of an Email.

Formatter: Apply specifc pattern of the field i.e : format a date according to the current locale.

For these four parts are implemented as a javascript function called on the client side and a java class on the server side when the form is submitted by the browser. The browser side generate the formatted field value in the "Render" phase of the JSF lifecycle. A validator can't have several filter, translator, chercker, or Formatter.

Presently several Client Validator are available, it is possible to change their behaviors and their parameters. Moreover it is easy to create new validators using some part of existing validators or new validator parts.

We advise you to look at the rcfaces-config.xml file contained in rcfaces-html.jar to see all existing client validators. Extract of rcfaces-config.xml :

When the user type within the text field, only alpha characters are authorized. They are automatically changed to upper case as the user is typing. When the field loses focus, the Caesar cipher is called.

10. Drag & Drop

Since the 1.2 version, RCFaces allows to perform Drag & Drop operations with the Tree and the DataGrid components. Only those two components are available for D&D as of today, but it should be expanded to other components in the future.

10.1 How to set a component draggable or droppable

Set the draggable attribute to true on a component and droppable on another component. Add one or many mime type with dragTypes and DropTypes attributes.

By default the dnd effect value is : "default" but RCFaces allows to define other accepted dragEffects and/or dropEffects with values: none, default, any, copy, move or link. During a default drag behaves as a file manager drag : Drag + CTRL to copy, Drag + MAJ to move and Drag + ALT to create a link. The default dragTypes is "x-RCFaces/xxx" where xxx can be a tree node or grid row. The default dropTypes is "*/*", It is possbile to drop any type of element.

Items contained inside the Tree and the DataGrid components inherit these dnd properties.

It is always possible to specify a different behavior for each item. drag/dropEffects and drag/dropTypes attributes are available on all the different types of items component.

For example, we can build a tree whose some branches accept to "copy" some apples and other branches accept to "move" some pears.

By default to drop an element you must be over another item. But RCFaces allows to drop new element on the component body with the Boolean attribute bodyDroppable.

The developer decides how and where a dragged item will be handled in relation to the item which has thrown the drop event (function called by the dropCompleteListener on DROP_COMPLETE event).

10.2 Use dndEvent and Understand each dnd stage

10.2.1 D&D Listener and event

Three Listeners and a common event object may be used by the developer to control the behavior of RCFaces Drag & Drop :

The dragListener handle events thrown when an element is caught with a mousedow event and the mouse begin to move. Conversely the dropListener is called when an dragged element is passing over another element and a "mouseup" event is handle. These two listeners are not mandatory, but they allow to pass additional information to change icon, cursor, add some text in order to customize your own D&D to provide feedback to the final user.

The third listener and the most important is the dropCompleteListerner. Most of the time its goal will be to make an AJAX request to update the components on server side and reload them graphically via a javascript function. Developers can bind a managed bean method to this listener and make a JSF navigation like in other actions.

The common point between these three listerners is the f_dndEvent object. This object allows to get the source and the target item together with component container, effects, types, get the stage of dnd and an instance of the javaScript Drag&drop engine. To get the engine instance, use the Static js function f_dndEvent.As(event) :

function myDrag(event) {

var targetTree=event.f_getComponent();

var dndEvent=f_dndEvent.As(event);

switch(dndEvent.f_getStage()) {

case f_dndEvent.DRAG_START_STAGE:

var infos=new Object();

infos[f_iconDnDInfo.DND_SOURCE_IMAGE]="images/iconDnD.jpg";

infos[f_iconDnDInfo.DND_SOURCE_IMAGE_WIDTH]=48;

infos[f_iconDnDInfo.DND_SOURCE_IMAGE_HEIGHT]=48;

dndEvent.f_getDragAndDropEngine()

.f_setSourceAdditionnalInformations(infos);

}

}

or :

function myDropComplete(event) {

var dndEvent=f_dndEvent.As(event);

alert("OK ! from="+dndEvent.f_getSourceItemValue()+

"to="+dndEvent.f_getTargetItemValue());

return true ;

}

For more information about what is possible, refer to the javascript doc of the following classes :

10.2.2 D&D Stage

There are twelve stages possible in D&D. It is important to know them in order to understand why a dnd failed and when the dnd is finish.

Drag and Drop activity diagram :

In this diagram all yellow diamonds (type decision or merge) translate to RCFaces event type ""DRAG" containing the current stage.

These stages can be intercept in drag/drop/dropCompleteListener.

The blue diamonds represent the basic user input to do drag and drop : a mouse click down to drag an element, then slides over the other items and drop the element.

The red diamonds is the lastest event thrown by the API to call a JSF navigation.

11. Customize Components

Rcfaces allows to add different complex components in a web application. These components must integrate properly with skins and behaviors of the application, that's why each component have many CSS classes which can be overriden. Besides that skin customisation, Rcfaces also allows to override Java renderer and javascript file for every component.

11.1 Override css

Using style-sheets is the quick and easy way to customize a component. All the Rcfaces components have a StyleClass attribute that can be used to change their CSS class.

i.e : change TextEntry compoent CSS class. In a jsp file :

<v:textEntryid="demoText"required="true" styleClass="test_class"/>

In a CSS file (referrenced by the JSP files) :

.test_class .f_textEntry{

border:1pxsolid#ABA6A1;

color:#333333;

font-family:Verdana;

font-size:11px;

font-weight:bold;

}

.test_class .f_textEntry_error {

background-color:#FFCCCC;

}

Here ".f_textEntry" is the CSS class defined by component renderer. Moreover, in this example the "required" attribute can change the component's state to error, so there is CSS class for this state : ".f_textEntry_error".

The CSS classes of every component have a suffix for all possible states i.e : "_selected", "_disabled", "_readOnly" ...

Every component part alos have a suffix such as "_title" to specify title label or "_topLeft", "_middle", "_topRight" to specify images of a rounded component or "_tab" in the case of a tabbed pane.

Components are continually evolving so it is possible that CSS subclasses change from version N to version N+1.

11.2 Create a lookId

Sometimes it is possible to create components based on the same interface but with a very different look and feel. When changing the stylesheets is not enough, you can create a "lookid" for this component. A lookid consists of a specific java class that performs the rendering phase of the JSF lifecycle, the class must perform the encoding and decoding of the component for the user device. The rendering phase emits HTML code based on the component attributes.

By writing a new renderer, you can freely specify :

The generated HTML tags that make the component on the client side

The CSS classes used by a component (f_*)

The JavaScript code used by a component.

A Rcfaces component has two types of rendering, one that is called on the server side and one that is called on the client side (javascript code). API consistency must be enforced at all time.

11.2.1 Create a Rcfaces Java renderer

There are at least four methods to override from AbstracCssRenderer:

getMainStyleClassName(): return the css class name.

getJavaScriptClassName(): return the js class name. If no css class name is defined this class name become the default css class name.

This example is just an overview, before you start to do your own component renderer, it is advisable to understand carefully how the component works and read its source code.

If you the HTML structure, the javaScript class associated to a component must be overriden and registered in a JavaScript module (see Module Parameter).

Note: Some Components which contain Select Item work with a Decorator like Combo, Tree or calendar ... for this type of component, HTML tags are written in the decorator class.

11.2.2 Create a Rcfaces JavaScript Class

The Rcfaces API allows to create classes with variable members, statics and aspects. It is possible to extend exisiting JavaScript classes. The followings source code is just an overview that shows how a extend an existing JavaScript class.

12 Accessibility

The ability to access information and service for people with disabilities is an important issue today. In many countries, this has led to initiatives, laws and regulations that aim toward providing easier access to web content.

Today, RCFaces is used by a french public organisation for which accessibility is required. That's why we started to implement the WAI-ARIA specification in RCFaces.

For each component the role attribute is defined. Developers can specified a different text with the arialLabel Attribute which generate the value of aria-label property. The hierarchical level of an element can be modified with the ariaLevel Attribute.

The others ARIA attributes like aria-activedescendant/poseinset/expanded/disabled/selected or labelledby are generated in component's renderer.

WAI-ARIA is implemented on the more used components, tested with Jaws by a professional end-user. For more information or development request contact us at info@vedana.com