RCFaces 1.2.1


User Guide






















  1. 1. Introduction
  2. 2. Requirements
    1. 2.1 Supported JavaSever Faces Implementations
    2. 2.2 Supported Servers
    3. 2.3 Supported Browsers
  3. 3. Getting Started
    1. 3.1 Download
    2. 3.2 Your first Rcfaces application
      1. 3.3 Create project and add libraries
      2. 3.4 Add Rcfaces resources Servlet in web.xml file
      3. 3.5 Create a managed bean
      4. 3.6 Create  a JSP
  4. 4. Rcfaces architecture overview
    1. 4.1 JSF enhancements
    2. 4.2 Object-oriented and aspect-oriented JavaScript framework
    3. 4.3 AJAX Engine
  5. 5. Components List and Feature
    1. 5.1 Basic
    2. 5.2 Non visual
    3. 5.3 Input
    4. 5.4 Complex
  6. 6. Rcfaces configuration
    1. 6.1 Rcfaces servlets
      1. 6.1.1 Rcfaces resources Servlet
      2. 6.1.2 Rcfaces Application version
      3. 6.1.3 Rcfaces Application dynamics Contents
      4. 6.1.4 Rcfaces Client bundle
    2. 6.2 Development Parameters
      1. 6.2.1 Activate The JavaScript console
      2. 6.2.2 Disable cache
    3. 6.3 Runtime Parameters
    4. 6.4 Module Parameters
      1. 6.4.1 Create a CSS repository
      2. 6.4.2 Create a JavaScript repository
      3. 6.4.3 Register a Repository in Rcfaces context and Use it
    5. 6.5 JavaScript optimization
      1. 6.5.1 JavaScriptCollector Tag
      2. 6.5.2 Compiled Versions of the Rcfaces runtime
  7. 7 Basic use of the RCFaces Javascript API
      1. 7.1.1 Find Component with the event object
      2. 7.1.2 Get Item selection
      3. 7.1.3 The f_event public methods
    1. 7.2 The most important function in f_core class
    2. 7.3 Create a new RCFaces Javascript Class
  8. 8. The service component and AJAX request
    1. 8.1 Component declaration
    2. 8.2 Call AJAX service
      1. 8.2.1 Synchronous mode
      2. 8.2.2 Asynchronous mode
    3. 8.3 Get asynchronous response in callback
  9. 9. Client Validators
    1. 9.1 How it works
    2. 9.2 List of existing validator
    3. 9.3 Creating your own validator
  10. 10. Drag & Drop
    1. 10.1 How to set a component draggable or droppable
    2. 10.2 Use dndEvent and Understand each dnd stage
      1. 10.2.1 D&D Listener and event
      2. 10.2.2 D&D Stage
  11. 11. Customize Components
    1. 11.1 Override css
    2. 11.2 Create a lookId
      1. 11.2.1  Create a Rcfaces Java renderer
      2. 11.2.2 Create a Rcfaces JavaScript Class
      3. 11.2.3 Declare a lookId in Faces-config
      4. 11.2.4 Use a LookId in your JSP
  12. 12 Accessibility


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 : 



The distinctive advantages of Rcfaces are :



The project is hosted on SourceForge :  http://sourceforge.net/projects/rcfaces/


Vedana can offer professionnal services and support for projects using Rcfaces (contact us).   



2. Requirements

Rcfaces works with Java 1.4 or higher. The current version is compiled with Java 1.4.  

    2.1 Supported JavaSever Faces Implementations 

    2.2 Supported Servers

Rcfaces has been tested on the following J2EE servers :



Rcfaces was developped with Apache Tomcat.

    2.3 Supported Browsers






3. Getting Started

    3.1 Download

The latest release is available at http://sourceforge.net/projects/rcfaces/files/
Today the lastest release is RCFaces 1.2.1 

Example :


The rcfaces-1.2.1.RELEASE archive file contains the following directories:

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.

      3.3 Create project and add libraries

First, create JSF 1.2 (Sun RI) project named "RcfacesFormSample" and add all necessary libraries in folder WEB-INF/lib :

 
In the same folder, the Rcfaces libraries :

      3.4 Add Rcfaces resources Servlet in web.xml file

Declare the Rcfaces resources Servlet. This servlet provides the resources used by each Rcfaces component: JavaScript, css and images.   

Add the following lines in web.xml :

 <servlet>

    <servlet-name>Rcfaces resources Servlet</servlet-name>

    <servlet-class>org.rcfaces.renderkit.html.internal.resource.ResourcesServlet</servlet-class>

    <load-on-startup>1</load-on-startup>

 </servlet>

    

 <servlet-mapping>

     <servlet-name>Rcfaces resources Servlet</servlet-name>

     <url-pattern>/rc-fwk/*</url-pattern>

 </servlet-mapping>



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 :

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

      id="WebApp_ID" version="2.5">

      <display-name>RcfacesFormSample</display-name>

      <welcome-file-list>

            <welcome-file>index.jsp</welcome-file>

      </welcome-file-list>

 

      <context-param>

            <param-name>javax.faces.STATE_SAVING_METHOD</param-name>

            <param-value>server</param-value>

      </context-param>

 

      <context-param>

            <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>

            <param-value>resources.application</param-value>

      </context-param>

 

      <listener>

            <listener-class>com.sun.faces.config.ConfigureListener</listener-class>

      </listener>

 

      <servlet>

            <servlet-name>Faces Servlet</servlet-name>

            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

            <load-on-startup>1</load-on-startup>

      </servlet>

     

      <servlet>

            <servlet-name>Rcfaces resources Servlet</servlet-name>

            <servlet-class>org.rcfaces.renderkit.html.internal.resource.ResourcesServlet</servlet-class>

            <load-on-startup>1</load-on-startup>

      </servlet>

 

      <servlet-mapping>

            <servlet-name>Faces Servlet</servlet-name>

            <url-pattern>*.jsf</url-pattern>

      </servlet-mapping>

     

      <servlet-mapping>

            <servlet-name>Rcfaces resources Servlet</servlet-name>

            <url-pattern>/rc-fwk/*</url-pattern>

      </servlet-mapping>

</web-app>


        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;

 

public class GridBean {

 

      private static final 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

      public void addRow(SelectionEvent event) {

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

                        .getBirthDate()));

            newRow = null;

      }

 

      public List<Row> getRows() {

            return rows;

      }

 

      public void setRows(List<Row> rows) {

            this.rows = rows;

      }

 

      public Row getNewRow() {

            if (newRow == null) {

                  newRow = new Row();

            }

            return newRow;

      }

 

      public void setNewRow(Row newRow) {

            this.newRow = newRow;

      }

 

      public class 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) {

                        throw new IllegalArgumentException(ex);

            }

        }

 

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

                  this.name = name;

                  this.city = city;

                  this.birthDate = birthDate;

            }

 

            public String getName() {

                  return name;

            }

 

            public void setName(String name) {

                  this.name = name;

        }

 

            public String getCity() {

                  return city;

            }

 

            public void setCity(String city) {

                  this.city = city;

            }

 

            public Date getBirthDate() {

                  return birthDate;

            }

 

            public void setBirthDate(Date birthDate) {

                  this.birthDate = birthDate;

            }

      }

}



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

<managed-bean>

    <managed-bean-name>gridBean</managed-bean-name>

    <managed-bean-class>org.rcfaces.rcfacesformsample.managed.GridBean</managed-bean-class>

    <managed-bean-scope>session</managed-bean-scope>

</managed-bean>

        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 : 

<?xml version="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">     

      <jsp:forward page="form.jsf"/>    

</jsp:root>


form.jsp source code :

<?xml version="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">

 

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

<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" />

 

<f:view>

      <html>

      <head>

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

      </head>

      <vh:javaScriptCollector>

            <body>

            <h:form>

 

                  <v:fieldSet text="Form">

                        <!-- container  -->

 

                  <div style="margin-top: 10px;">

               What is your name : 

                        <v:message for="field1" showDetail="false" showSummary="true"

                   showIfMessage="true" />

               <v:textEntry id="field1" columnNumber="30"

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

                  </div>

 

                  <div style="margin-top: 10px;">

                      Where do you come from :

                       <v:message for="field2" showDetail="false" showSummary="true"

                  showIfMessage="true" /> 

              <v:textEntry id="field2" columnNumber="30" 

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

                  emptyMessage="your city" />

                  </div>

 

                  <div style="margin: 10px 0;">

                When were you born :

                        <v:message for="fieldDate" showDetail="false" showSummary="true"

                   showIfMessage="true" />

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

                   required="true" />

                        <v:dateChooser id="date" for="fieldDate" />

                  </div>

 

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

                  </v:fieldSet>

 

                  <div style="margin-top: 10px;">

            <v:dataGrid id="tableId"

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

 

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

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

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

                             alignment="center" />

 

                  </v:dataGrid> 

           <v:pager for="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 :


The following diagram shows how the Rcfaces features fit in the JSF application :


All servlets are described in part 6.1 Rcfaces servlets

    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 :




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.   

    5.1 Basic

http://www.rcfaces.org/comps/comp-basic-info.html


    5.2 Non visual

http://www.rcfaces.org/comps/comp-nonvisual-info.html


    5.3 Input

http://www.rcfaces.org/comps/comp-entry-info.html


    5.4 Complex

http://www.rcfaces.org/comps/comp-complex-info.html




6. Rcfaces configuration

In the coming chapter, you will find:


If you choose to use Rcfaces for a real-world project, you will have to understand thoroughly this part of the framework.

   6.1 Rcfaces servlets

         6.1.1 Rcfaces resources Servlet

Rcfaces works with a servlet named "Rcfaces resources Servlet". Its role is to provide stylesheet, javascript and image files used by the Rcfaces components. 


Register this servlet like this in web.xml :


 <servlet>

    <servlet-name>Rcfaces resources Servlet</servlet-name>

    <servlet-class>org.rcfaces.renderkit.html.internal.resource.ResourcesServlet</servlet-class>

    <load-on-startup>1</load-on-startup>

 </servlet>

    

 <servlet-mapping>

     <servlet-name>Rcfaces resources Servlet</servlet-name>

     <url-pattern>/rc-fwk/*</url-pattern>

 </servlet-mapping>


This servlet can be parametrized to define sets of RcFaces components.


The RCFaces servlet is customized by using <init-param> tags.


i.e : 

    <servlet>

            <servlet-name>Rcfaces resources Servlet</servlet-name>

            <servlet-class>org.rcfaces.renderkit.html.internal.resource.ResourcesServlet</servlet-class>

 

            <init-param>

                  <param-name>

                                org.rcfaces.renderkit.html.javascript.modules.GROUP_ALL_FILES

                        </param-name>

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

            </init-param>

 

            <init-param>

                  <param-name>org.rcfaces.renderkit.html.javascript.sets.CORE</param-name>

                  <param-value>

                        basicComponent, tree, toolbar, dialog, image, extraComponent, expandBar, itemsList, gridHelp

                  </param-value>

            </init-param>

            <init-param>

                  <param-name>org.rcfaces.renderkit.html.javascript.sets.EXTRAS</param-name>

                  <param-value>

                         validator, messageComponents, popupComponent, tabbedPane, calendar, asyncRender,  

                         suggest, pager, dataGrid, items

                  </param-value>

            </init-param>

 

            <load-on-startup>1</load-on-startup>

      </servlet>


     <servlet-mapping>

         <servlet-name>Rcfaces resources Servlet</servlet-name>

         <url-pattern>/rc-fwk/*</url-pattern>

     </servlet-mapping>  



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.

            

Register this servlet like this :


 <servlet>

    <servlet-name>Rcfaces Application version</servlet-name>

   <servlet-class> org.rcfaces.core.internal.version.ApplicationVersionServlet</servlet-class>

   <load-on-startup>1</load-on-startup>

 </servlet>

    

<servlet-mapping>

    <servlet-name>Rcfaces Application version</servlet-name>

    <url-pattern>/rc-av/*</url-pattern>

</servlet-mapping>

 

You can force the application version in web.xml :


<context-param>

    <param-name>org.rcfaces.core.APPLICATION_VERSION</param-name>

    <param-value>hashcode</param-value>

        <!-- param-value>v10.0</param-value -->

        <!-- param-value>v10.1</param-value -->

</context-param>

 

An URL looks like :"http://myproject/rc-av/<hashcode>/myResource.gif"    


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.     


Register this servlet like this :


 <servlet>

    <servlet-name>Rcfaces Application Contents</servlet-name>

   <servlet-class> org.rcfaces.core.internal.contentStorage.ContentStorageServlet</servlet-class>

   <load-on-startup>1</load-on-startup>

 </servlet>

    

<servlet-mapping>

    <servlet-name>Rcfaces Application Contents</servlet-name>

    <url-pattern>/rc-content/*</url-pattern>

</servlet-mapping>

 

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


The servlet allows to :


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


<v:image imageURL="images/back64.gif" />                                  

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

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

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

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


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

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

 

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

 

<!--size in px  -->

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

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


<v:imageCheckButton

    imageURL="images/home.gif"

    hoverImageURL="hover::"

    disabledImageURL="disabled::"

    selectedImageURL="selected::"

/>


<v:imageCheckButton disabled="true"

    imageURL="images/home.gif"

    disabledImageURL="disabled::"

/>



<!--GIF to JPEG  -->

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


<!--JPEG to JPEG  -->

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


<!--JPEG to GIF -->

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


<!--JPEG to PNG -->

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


<!--GIF to PNG  -->

<v:image imageURL="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.

   

Register the "Rcfaces Client Bundle" servlet like this :  


 <servlet>

   <servlet-name>Rcfaces client bundle</servlet-name>

   <servlet-class> org.rcfaces.html.internal.clientBundle.clientResourceBundleServlet</servlet-class>

   <load-on-startup>1</load-on-startup>

 </servlet>

    

<servlet-mapping>

    <servlet-name>Rcfaces Client bundle</servlet-name>

    <url-pattern>/rc-cb/*</url-pattern>

</servlet-mapping>

 

In Faces-Config.xml, declare all the needed locales : 


 <application>

     <locale-config>

         <default-locale>en</default-locale>

         <supported-locale>fr</supported-locale>

         <supported-locale>de</supported-locale>

     </locale-config>

 </application>

 


Exemple :


Sample messages.properties file (in the "bundle" package) :


greeting_text=Greeting

forfun_alert=Framework created by Olivier Oeuillot

test=java is {0} and {1}


Sample JSP : 


 

<vh:loadBundle bundleName="messages"  baseName="bundle.Messages" />

<script>

      var bundle=f_resourceBundle.Get("messages");

     

      try {

            alert("Bundle="+bundle.f_format("forfun_alert"));

            alert("Bundle="+bundle.f_format("test""good""powerfull" )); 

      } catch (x) {

            alert("Test: "+x);

      }

</script>

 

<v:textEntry id="demoText" value="#{messages.greeting_text}"  required="true">

      <v:text for="demoText"  text="Label : "/>

</v:textEntry>

 

This feature allows JavaScript access to resource bundles deployed on server. 

    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:javaScript requiredClasses="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 :


<?xml version="1.0" encoding="UTF-8"?>

<repository id="CssApp" 

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

      <module id="myCssModule">

            <file name="rcfaces.css" />

 

            <file name="button.css" />

           

            <file name="ie_cadreRegroupement.css" />

   <file name="combo.css" />         

           

            <file name="grid.css" />

            <file name=grid_ie.css" userAgent="ie" />

 

            <file name="ie_hyperlink.css" />

           

            <file name="menuHorizontal.css" />

            <file name="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 :


<?xml version="1.0" encoding="UTF-8"?>

<repository id="js"

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

      convertSymbols="true" >

 

      <module id="MyJsModule">

            <file name="menuHorizontal.js">

                  <class name="ie_menuHorizontal">

                        <required-class name="f_component" />

                        <required-class name="fa_disabled" />

                        <required-class name="fa_readOnly" />

                        <required-class name="fa_selectionManager" />

                        <required-class name="fa_items" />

                        <required-class name="fa_itemClientDatas" />

                  </class>

            </file>

         

            <file name="menuVertical.js">

                  <class name="pe_menuVertical">

                        <required-class name="f_tree" />

                        <required-class name="fa_items" />

                        <required-class name="fa_itemClientDatas" />

                  </class>

            </file

            […]

            <file name="messages.js">

                  <class name="ie_messages">

                        <required-class name="f_messageContext" />

                        <required-class name="f_messageObject" />

                        <required-class name="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:


<?xml version="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:cssStyle requiredModules="MyCssModule" />

    <vh:javaScript requiredModules="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 :


<?xml version="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:importAttribute scope="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" />

         

            <html lang="fr">

                <jsp:directive.include file="_header.jspf" />                      

                    <vh:javaScriptCollector>


                    <body>

                        <h:form id="ecranGlobal">

                                  

                           <jsp:directive.include file="_body.jspf" />

     

                          <!-- Menu Horizontal -->

                                  

                           <div class="zoning_menuHorizontal">

                              <f:subview id="menuHorizontal">

                                <jsp:include page="${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:button text="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);

                       

     });

                 

      return false;

}


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.


bodyPopup.jsp:


[...]

<v:imageButton

      text="Cancel"

      actionListener="f_shellManager.CloseShell(event, false);return false" />

 

<v:imageSubmitButton

      text="Validate"

      actionListener="f_shellManager.CloseShell(event, true);return false" />

        7.1.2 Get Item selection

This example is based on a tree component with multiple levels of nodes and clientDatas.  


The purpose of this example is to see how to use the functions getValue() and getItem(). 


These functions are often used with components which can contain items like dataGrid, comboGrid, imageCombo, tabbedPane and tree. 


This is a tree in a jsp :


<v:tree id="anId"

    selectable="true"

    height="480"

    width="620"

    selectionCardinality="1"

    selectedValues="#{treeBean.selectedValues}"                             

    selectionListener="return selectTree(event);">

                            

   <f:selectItems value="#{treeBean.noeudsArbre}" />

   <v:menuItem itemValue="valueTest" itemLabel="Label Test" >

                  <v:clientData  name="IDE" value="eclipse"/>

                  <v:clientData  name="Java" value="Is good"/>

    </v:menuItem>     

</v:tree>



Method selectTree :


function selectTree(event) {

      var tree = event.f_getComponent();

      var value = event.f_getvalue();

      var label = tree.f_getNodeLabel(value);

      var clientDatas clientDatas = tree.f_getItemClientDatas(event.f_getItem());

     

      f_otherClass.f_setInfoToDoSomeThing({key: value, label: label, 

        clientDatas : clientDatas});

                       

      return false;

}


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. 


Example : 

 

/**

 * f_scheduler class

 *

 * @class public f_scheduler extends f_component, fa_items, fa_selectionManager

 * @author jbmeslin@vedana.com

 * @version $Revision: 1.0

 */

var __statics = {

     

      /**

       * @field private static final String

       */

      _PERIOD_STYLE: "f_scheduler_period",


      /**

       * @method private static

       * @param Event event

       * @return boolean

       * @context object:scheduler

       */

      _OnPeriodMouseOver : function(evt) {

            var scheduler = this._scheduler;

            if (!evt) { //pour IE

                  evt = f_core.GetJsEvent(this);

            }

        scheduler.f_update();

         

            [...]

      }    

};

 

var __members = {

 

      //constructor

      f_scheduler : function() {

            this.f_super(arguments);

            this._selectionCardinality=fa_cardinality.OPTIONAL_CARDINALITY;

      },

 

      //destructor

      f_finalize : function() {

            this.f_super(arguments);    

            this._anObject = undefined;

            this._aListener = null;

            //this._primitifType = undefined

      },

     

       /**

       * @method public

       * @param Object item

       * @return void

       */

      f_addPeriod: function(item) {

            item._begin = f_core.DeserializeDate(item._begin);

            item._end = f_core.DeserializeDate(item._end);

            this.f_addItem(this, item);

      },

 

       /**

       * @method protected

       * @return void

       */

      f_update: function() {

           

            [...]

      },

     

      /**

       * @method protected

       * @return void

       */

      fa_updateElementStyle: function(divNode) {

            [...]

      },

           

      /**

       * @method private

       * @return Object

       */

      f_aPrivateMethod: function() {

            [...]

      }

};

 

new f_class("f_scheduler", {

    extend : f_component,

    aspects : [ fa_items, fa_selectionManager ],

    statics : __statics,

    members : __members

});



 

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:button text="Call Service"

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

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

 

<v:text id="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. 


Here is the java method that builds the sentence:


public String getResults(ServiceEvent event) {

    Map<String, String> data = (Map) event.getData();

    String param = data.get("param2");  //setted in the js function callService  

      return "Hello " + param ;

}


The ServiceEvent parameter is required. It is a specialized FacesEvent. 


This java object can provide additional parameters based on its data attribute which can be a String or a Map like in this example. This map was created in the function "callService" described below. 

    8.2 Call AJAX service


Now that we have the service tag and the java bean, the next step is to write the javaScript function which creates the link between them.

       8.2.1 Synchronous mode


Even if AJAX is basically asynchronous,  the service component can do a synchronous request like this : 


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

    var servComp = event.f_findComponent(idService);

    if (servComp) {

         var result  = servComp.f_syncCall({param1:idResult, param2:otherParam});

         var resComp = f_core.GetElementByClientId(idResult);

         if (resComp) {

             resComp.f_setText(result);

      }

    }

}


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 :



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 :


<clientValidator id="number">

            <parameter name="num.signed" value="false" />

            <parameter name="num.decimal" value="0" />

            <parameter name="num.negSign" value="-" />

            <parameter name="num.decSign" value=",." />

            <parameter name="num.sepSign" value=" " />

            <filter call="f_vb.Filter_num" class="org.rcfaces.core.internal.validator.impl.NumFilter"/>

            <translator call="f_vb.Translator_num"

                           class="org.rcfaces.core.internal.validator.impl.NumTranslator"/>

            <checker call="f_vb.Checker_num" class="org.rcfaces.core.internal.validator.impl.NumChecker"/>

            <formatter call="f_vb.Formatter_num" class="org.rcfaces.core.internal.validator.impl.NumFormatter" />

            <converter object="f_vb.Converter_num" />  

        

</clientValidator>    

 

As shown in this example, a client validator may use a converter to convert a string field to an object and vice versa.


   9.2 List of existing validator


Name Description Parameters
noblank No white space
scientific
Check number scientific : [0-9\.\-eE]
money
Check money field: [0-9\.\+\-]

code entering a listing: [a-zA-Z]

alpha
entering a listing: [a-zA-Z]
alpha.otherChars
number
seizure of any number num.signed, num.decimal, num.negSign, num.decSign, num.sepSign 
card
card number: [0-9\.]
name
seizure of name: [ a-zA-Z0-9\*\.\-]
removeaccent
replace all accented characters
skipBlank
remove blank at the begin and the end of String
alpha_fr
allow all french charaters alpha.otherChars
alpha_fr_upper
replace alphabetic characters and accented characters in capital (Uppercase)
alpha_fr_lower
replace alphabetic characters and accented characters in lowercase

digit
Check number : [0-9]

alpha_digit
Allow alphabetic charaters and digit [ a-zA-Z0-9]

upper
Performing the translation validation of all characters wuth uppercase equivalent
lower Performing the translation validation of all characters wuth lowercase equivalent

dps
allow only the ACII printable characters (32-127)
insee
check diget and alfa and translate in the INSEE format
date
Check Date
email Check validity of an e-mail

    9.3 Creating your own validator


Just for fun, the aim of this exercise will be to create a client validator which does a Caesar cipher. 

When the user enters a character, the validator filters the letters of alphabet, then change to upper case and finally calls the formatter to do cipher algorithm.  


First In the base source directory of your project (src), create a META-INF folder and a rcfaces-config.xml file in this folder. Paste the following text :  


<?xml version="1.0" encoding="UTF-8"?>

<rcfaces-config>


      <repositories>

            <repository>

                  <type>javascript</type>

                  <location>org/rcfaces/rcfacesformsample/js/repository.xml</location>

            </repository>

      </repositories>

 

      <clientValidators>

            <render-kit>

                  <!--

                        /** * Validaor CAESAR * * Caesar cipher*/

                  -->

                  <clientValidator id="CAESAR">

                        <parameter name="nb.shift" value="5" />

                              <!-- if is letter -->

                        <filter call="f_vb.Filter_alpha"

                             class="org.rcfaces.core.internal.validator.impl.AlphaFilter" />

                        <!-- To upper case -->

                        <translator call="f_vb.Translator_uppercase"

                              class="org.rcfaces.core.internal.validator.impl.UpperCaseTranslator" />

                        <!-- Caesar cipher  -->

                        <formatter call="av_caesar.DoIt" />

                  </clientValidator>

            </render-kit>

      </clientValidators>

 

</rcfaces-config>


The parameter named "nb.shift" allows to change the shift of the cypher. The filter phase of this validator calls a javascript function named Filter_alpha and its  java class which do the same.

Tanslator calls a Rcfaces javascript function named Filter_alpha and its  java class which do the same formatting.


Then formatter calls a new function wich must added in a repository.xml file :


<?xml version="1.0" encoding="UTF-8"?>

<repository id="javascript" baseDirectory="org/rcfaces/rcfacesformsample/js" convertSymbols="true">

     

      <module id="clientValidator">

            <file name="av_caesar.js">

                  <class name="av_caesar">

                  </class>

            </file>

      </module>

     

</repository>


The av_caesar.js file : 


/**

 * class av_caesar.

 *

 * @class av_caesar

 * @author JBM

 *

 */

 

var __statics = {

 

      /**

       * @method public static

       * @context object:validator

       */

      DoIt : function(validator, inVal) {

 

            if (!inVal) {

                  validator.f_setObject(null);

                  return inVal;

            }

 

            k = validator.f_getIntParameter("nb.shift");

            Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ';

            var clair = inVal;

            while (k < 0) {

                  k += 26

            };

            while (k > 25) {

                  k -= 26

            };

            n = 0;

            chiffre = "";

            for ( var count = 0; count < clair.length; count++) {

                  var alpha = clair.charAt(count);

                  idx = Alphabet.indexOf(alpha);

                  if (idx > -1) {

                        if ((n % 5 == 0) && (n > 0)) {

                             chiffre += " ";

                        };

                        n++;

                        chiffre += Alphabet.charAt(idx + k);

                  }

            }

            return chiffre;

      }

 

}

 

new f_class("av_caesar", {

      statics : __statics

});


Finally, we create a jsp file that use the new custom validator  :


<vh:javaScript requiredModules="clientValidator" />


<v:textEntry id="field" clientValidator="CAESAR">


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. 


Example :


<v:tree draggable="true"

      dragTypes="text/*"

          dragEffects="copy"   


      droppable="true"

      dropTypes="text/*, app/object"

      dropEffects="copy"

    

      dropCompleteListener="return serviceOrBean();#{aCleverBean.doDndInData}">

    ...

</v:tree>


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 : 



You can also download the dnd project example. 

        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:textEntry id="demoText" required="true"  styleClass="test_class" />


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


.test_class .f_textEntry {

    border:1px solid #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.   


Note : To retrieve these suffixes there are some tools like Firebug for Firefox, Internet developer toolbar and Debugbar for IE. 


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 :



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:



Example of overriding a Renderer :


public class TabbedPaneRenderer extends CardBoxRenderer {


protected String getJavaScriptClassName() {

        return JavaScriptClasses.TABBED_PANE;

}

 

protected String getMainStyleClassName() {

      return "ie_tabbedPanne";

}


protected void encodeBegin(IComponentWriter writer) throws WriterException {

    // call parent methode

    super.encodeBegin(writer);

    

    //get component context

     IComponentRenderContext componentRenderContext = writer

            .getComponentRenderContext();


    //get componen

    CardBoxComponent tabbedPaneComponent = (CardBoxComponent)                                                            

        componentRenderContext.getComponent();

 

       //getFacesContect

    FacesContext facesContext = writer.getComponentRenderContext()

               .getFacesContext();

 

      //get Component Attribute thanks facesContext

    String text = tabbedPaneComponent.getToolTipText(facesContext);

    String height tabbedPaneComponent.getHeight(facesContext);


    //use an htmlWriter    

    IHtmlWriter htmlWriter = (IHtmlWriter) writer;


    //start write html tags component

    htmlWriter.startElement(IHtmlWriter.UL);

    writeHtmlAttributes(htmlWriter);

    writeJavaScriptAttributes(htmlWriter);

    writeCssAttributes(htmlWriter)


    writer.startElement(IHtmlWriter.LI);

    writer.writeClass(getMainStyleClassName()+ "_left");

    writer.endElement(IHtmlWriter.LI);

    writer.startElement(IHtmlWriter.LI);

    writer.writeClass(getMainStyleClassName()+ "_mid");

 

    […]//write Label for example

 

    writer.endElement(IHtmlWriter.LI);

    writer.startElement(IHtmlWriter.LI);

    writer.writeClass(getMainStyleClassName()  + "_right");

      writer.endElement(IHtmlWriter.LI);

 

    […]//call other function like doHeader

 

}

 

protected void encodeEnd(IComponentWriter writer) throws WriterException {

 

    IHtmlWriter htmlWriter = (IHtmlWriter) writer;

    htmlWriter.endElement(IHtmlWriter.UL);

       super.encodeEnd(writer);

}

}


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.


ie_tabbedPane.js :


/**

 * @class public ie_tabbedPane extends f_cardBox

 */

 

var __statics = {

     

      […]

     

      /**

       * @method private static

       * @param Event

       *            evt

       * @return boolean

       * @context object:tabbedPane

       */

      _TabbedPane_mouseout: function(evt) {

            var tab=this._tab;

            var tabbedPane=tab._cardBox;

 

            if (!evt) {

                  evt = f_core.GetJsEvent(this);

            }

 

            if (tabbedPane.f_getEventLocked(evt, false)) {

                  return false;

            }

 

            tabbedPane._tabMouseOut(this._tab, evt);

           

            return f_core.CancelJsEvent(evt);

      }

     

     

      […]

     

}

 

var __members = {

     

      //constructor

      ie_tabbedPane: function() {

            this.f_super(arguments);

            this._tabIndex=f_core.GetAttribute(this"v:tabIndex");

           

      },

      //destructor

      f_finalize: function() {

            this._overTab=undefined// f_tab

            this.f_super(arguments);

      },

     

      […]   //see source code


      /**

       * @method protected

       * @param f_tab tab

       * @return void

       */

      f_updateCardStyle: function(tab) {

            var textTitle;

            var textTitleLeft;

            var textTitleMid;

            var textTitleRight;

           

            var className = "ie_tabbedPane";  

            if (this._selectedCard==tab) {

                 

               textTitle = className+"_UL "+className+"_selected_UL";

               textTitleLeft =className+"_left "+className+ "_selected_left";

               textTitleMid = className+"_mid "+className+ "_selected_mid";

               textTitleRight =className+"_right "+className+

" _selected_right";

            }else {

                [...]

            }

 

            if (tab._disabled) {

               textTitle =className+" _UL "+className+ " _disabled_UL";

               textTitleLeft = textTitleLeft =className+" _left "+className+

"_disabled _left";

   textTitleMid = className+" _mid "+className+ " _disabled_mid";

               textTitleRight = className+" _right "+className

+" _disabled _right";

            }

     

            tab._textTitle.className=textTitle;

            tab._rightTitle.className=textTitleRight;

            tab._leftTitle.className=textTitleLeft;

            tab._midTitle.className=textTitleMid;   

 

    },   

[...]


}

 

new f_class("ie_tabbedPane", {

      extend: f_cardBox,

      members: __members,

      statics: __statics

});

    

Add this .js file in your own javaScript repository (see part 6.4.2 Create a JavaScript repository

             11.2.3 Declare a lookId in Faces-config

After these previous steps, the renderer must be registered. Add the following lines to rcfaces-config.xml : 


<renderer>

    <component-family>rcfaces</component-family>

   <renderer-type>org.rcfaces.core.tabbedPane:ie_tabbedPane</renderer-type>

   <renderer-class>com.project.renderer.TabbedPaneRenderer</renderer-class>

</renderer>


The ie_tabbedPane suffix signal that this renderer is a Rcfaces LookId. 

             11.2.4 Use a LookId in your JSP

Example JSP file :


<v:tabbedPane lookId="ie_tabbedPane"

    width="750" height="555">

  

    <v:tab prependId="true" lookId="ie_tab" text="Titre">

          <jsp:directive.include file="ongletBody1.jspf" />

      </v:tab>

           

      <v:tab prependId="true" lookId="ie_tab" text="Titre 2">

            <jsp:directive.include file="ongletBody2.jspf" />

      </v:tab

</v:tabbedPane>


In Css File javascript class like "*f_" are replaced by "ie_*" : 


@charset "UTF-8";

 

.ie_tabbedPane {

      border-bottom: 0;

   &nbsp;  display: block;        

}

 

.ie_tabbedPane_content {

      -moz-box-sizing: border-box;

      box-sizing: border-box;

      border: 1px solid #ABA6A1;

      border-top: 0;   

      padding: 10px;

      display: block;

      xheight: 531px;

      font-size: 11px;

}

 

.ie_tabbedPane_left{

      background: transparent url("tab_left.gif") left bottom no-repeat;

      width: 6px;

}


.ie_tabbedPane_mid {

    background: transparent url("tab_mid.gif") left bottom repeat-x;

      line-height: normal;

      font-family: Verdana;

      font-size: 13px;

      color: #333333;

      font-weight: normal;

}

 

.ie_tabbedPane_right {

      background: transparent url("tab_right.gif") left bottom no-repeat;

      width: 11px ;

}

 

.ie_tabbedPane_selected_left {

      background: transparent url("tab_selected_left.gif") left bottom no-repeat;

      width: 5px;

}

 

.ie_tabbedPane_selected_mid {

    border-top: 1px solid #ABA6A1;

      background: white;

      font-family: Verdana;

      font-size: 13px;

      color: #333333;

      font-weight: bold;

      line-height: normal;

}

 

.ie_tabbedPane_selected_right {

    background: transparent url("selected_right.gif") left bottom no-repeat;

      width: 13px ;

}

 

.ie_tabbedPane_title {

    background: transparent url("tab_header.gif") right center repeat-x;

      height: 34px;

      float: none;

}

 

.ie_tabbedPane_tab {

      -moz-box-sizing: border-box;

      box-sizing: border-box;

      display: block;

      overflow-y: auto;

      overflow-x: hidden;

      xwidth: 738px;

      xheight: 510px;

}

    

A good practice is to do a ie_tabbedPane.css and add it in a Css repository (see part 6.4.1 Create a CSS repository  )

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