J4Fry Script Injection

Characteristics

Attribute Value
Project name J4Fry Script Injection
Prerequisites JSF >= 1.1
CVS module Part of the example project
Responsible developer Ganesh Jung

J4Fry Script Injection aims

Enrich JSF h:dataTable with JavaScript enhancements like rollover effect and row selection. Inject the necessary JavaScript through a naming convention.

J4Fry Script Injection usage

Download scriptInjection.js (right-click and save as...) and add <script type="text/javascript" src="/yourPath/scriptInjetion.js" /> after the closing f:view tag of your page. Some developers had problems with this type of script include at the end of the page, because their page layout wasn't designed to have a <script /> tag a the end of the page. In this case add <%@ include file="/yourPath/scriptInjection.js" %> to your page and put <script> and </script> at the beginning and the end of the file scriptInjection.js.

The script offers 5 types of script injection: SIRolloverTable injects a rollover effect into dataTables, SIClickTable allows single row selection for 1 row per table, SIClickPage is for 1 row per page, SIClickRow allows multiple row selection and SIRadioGroup enables RadioGroups within dataTables or with RadioButtons distributed all over the page.

Add "SIRolloverTable" to the id of your h:dataTable tag to enable the rollover effect for a table. If the id of your table was "MyStuff" change it to "SIRolloverTableMyStuff" for the rollover effect. The JavaScript will add onMouseOver and onMouseOut events to each row of the table. When running over the row with the mouse pointer the style class of the row will change to "rollOverEffect". This is similar to the hover style that doesn't work for able rows in IE. Define a style class "rollOverEffect" to define how the rollover effect should look like.

Add "SIClickTable" to the id of your h:dataTable tag to enable single row selection for a table. If the id of your table was "MyStuff" change it to "SIClickTableMyStuff" for single row selection. The JavaScript will add an onClick event to each row of the table. When clicking the row the style class of the row will change to "rowClickEffect" and the style class of the previously clicked row will be set back to its previous style.

A SIClickTable transports the selected row through an input field to the model. Prepend your table with a input field that has the same id as the table with a trailing "SIKey". If your table has got the id "SIClickTableMyStuff" put a <h:inputHidden id="SIClickTableMyStuffSIKey"> in front of the table and connect it through its value to a bean property that holds the selected row number. If you want the selected value to be visible use an h:inputText instead of the h:inputHidden.

You can combine both effects (rollover and click) by using both naming conventions together. A table "MyStuff" would then get the new id "SIRolloverTableSIClickTableMyStuff" and the hidden field would get the id "SIRolloverTableSIClickTableMyStuffHidden".

If you use "SIClickPage" instead of "SIClickTable" you get basically the same effect. Only if you have more than one table on your page, SIClickPage will only allow one row to be selected througout the page, while a SIClickTable will have one selected row per table. With the SIClickPage naming convention you don't need an input field per table, but instead you add two inputs to the page: One that contains the selected table and another one for the selected tables row id. Use the Ids "SIClickPageTableKey" and "SIClickPageRowKey" for this two input fields. Again they may be hidden or visible.

Add "SIClickRow" to the id of a h:panelGrid that is nested inside the single column of your h:dataTable tag to enable multiple row selection for a table. If the id of your h:panelGrid was "MyStuff" change it to "SIClickRowMyStuff" for multiple row selection. The JavaScript will add an onClick event to each row of the h:panelGrid. When clicking the row the style class of the row will change to "rowClickEffect" and when clicking it again it will be set back to its previous style.

An SIClickRow transports the row selection states through hidden fields to the model. Prepend your h:panelGrid with a hidden field that has the same id as the h:panelGrid with a trailing "SIKey". If your h:panelGrid has got the id "SIClickRowMyStuff" put a <h:inputHidden id="SIClickRowMyStuffSIKey"> in front of the table and connect it through its value to a bean property that holds the row selection state.

By default the naming conventions SIClickPage and SIClickTable for table row clicks use the row number (starting with 0) to identify the selected row. In many cases your table will have a column with the id you want to set in your backing bean when the row is selected. Use a h:inputText or h:inputHidden that has the same id as the h:dataTable followed by a trailing "SIRowId" and that is part of a column of your table to make script injection set this id into your key field.

The "SIRadioGroup" naming convention allow the usage of independent h:selectOneRadio Tags througout the page that are connected by a groupId to form a radio group. If you name your radio group "MyGroup" and the Ids of the h:selectOneRadios you want to group are "Radio1", "Radio2" and "Radio3", then change them to "Radio1SIRadioGroupMyGroup", "Radio2SIRadioGroupMyGroup" and "Radio3SIRadioGroupMyGroup", add the script to the end of your page and there you go with a new RadioGroup.

The SIRadioGroup naming convention leaves you with the problem, that every h:selectOneRadio has its own value binding. Here's a solution how to bind the group to a single value: First use the same value binding for every h:selectOneRadio of your group. Now you have to avoid that the non-clicked radios overwrite the clicked radio when updating the model. For this purpose class ExpressionLanguageUtil from jsf-components contains a method setRadioProperty(). Either include the jar into your project or copy the Method from our Sourceforge Repository (right-click and save as...).

Change the setter of you backing bean from:

public void setProperty(String property) {
this.property = property;
}

to:

public void setProperty(String property) {
ExpressionLanguageUtil.setRadioProperty(this, "setPropertyInternal", property);
}
public void setPropertyInternal(String property) {
this.property = property;
}