JavaScript event handler examples
The following examples illustrate some of the common functions that you can use JavaScript event handlers to perform.
JavaScript onPrepare example
The onPrepare event fires for all report elements during the preparation phase of the generation process. This location is ideal for changing the design of a particular report element before generating the individual report item instances.
For example, BIRT supports grouping in tables and lists. To permit the user to group the data, you can implement this feature by performing the following developer tasks:
*Add a group to a table.
*Select the group in the Outline view of the report.
*Create an onPrepare script that changes the group definition for the table.
Listing 37‑21 groups a table by country or city using a Boolean parameter to determine the grouping column to use.
Listing 37‑21 Setting a table grouping key
if( params[ "grp_p" ].value == true ){
this.keyExpr = "row[ 'CITY' ];";
grpname = "City";
}else{
this.keyExpr = "row[ 'COUNTRY' ];";
grpname = "Country";
}
JavaScript onCreate examples
The onCreate event fires when the generation process creates an instance of the report element. Writing an event handler for an onCreate event is useful when changing an instance of a report item. The following examples illustrate this concept.
Image elements can source image data from a URL, an embedded image in a report, an image file in the resource folder, or a blob type from a database. To retrieve the data for the image at run time, use an onCreate event handler. Listing 37‑22 illustrates how to use Java to read the data from an image stored on the local file system.
Listing 37‑22 Accessing an image from a file
importPackage( Packages.java.io );
importPackage( Packages.java.lang );
 
var file = new File( "c:/temp/test.png" );
var ist = new FileInputStream( file );
var lengthi = file.length( );
 
bytesa = new ByteArrayOutputStream( lengthi );
var c;
while( ( c=ist.read( ) ) != -1 ){
bytesa.write( c );
}
ist.close( );
this.data = bytesa.toByteArray( );
If the image element is in a table, you can choose the selected file based on the data retrieved from the dataset. For example, the onCreate script in Listing 37‑23 selects an image from the resource folder based on calculations made on the table bound columns.
Listing 37‑23 Conditionally selecting an image file
if ( ( ( this.getRowData( ).getColumnValue( "total2005" ) / 5 ) /
( this.getRowData( ).getColumnValue( "total2004" ) / 12 ) )
>= .96 ) {
this.file ="up.gif";
}
else if( ( ( this.getRowData( ).getColumnValue( "total2005" ) /
5 )/( this.getRowData( ).getColumnValue( "total2004" ) / 12 ) )
<= .85 ) {
this.file ="down.gif";
}
else {
this.file ="even.gif";
}
BIRT supports conditional element formatting, using the highlight editor. You can also use the onCreate event handler to do conditional formatting, as shown in Listing 37‑24. This example is an onCreate event handler for a table row. If the table column QUANTITYORDERED is greater than 40, the row height increases to 2 centimeters, is highlighted in yellow, and the content appears in the middle of the row.
Listing 37‑24 Conditionally formatting a report item
if( this.getRowData( ).getColumnValue( "QUANTITYORDERED" ) > 40 ){
this.getStyle( ).backgroundColor = "yellow";
this.getStyle( ).verticalAlign = "Middle";
this.height = "2cm";
}
JavaScript onRender examples
Rendering content may occur anytime after generation. Often users run a report and re-render it many times in different formats. The onRender events support some customization at render time. For example, a user may want a label in the page footer to show the render time of the report or the day of the month the report rendered. You can achieve this effect by using the onRender method of a label element, as shown in the following script:
importPackage( Packages.java.util );
cl = new GregorianCalendar( );
this.text = cl.get( Calendar.DAY_OF_MONTH );
Cross tab script examples
Cross tabs support writing event scripts. As with other report items the cross tab supports an onPrepare, onCreate, and onRender event. Each of these events supports writing a handler for the cross tab or the cross tab cell. When implementing an onCreate event for the cross tab cell, the handler is passed a cellInst object. This object is an instance of a cell object that provides methods to determine the cell properties. For example, the developer can call cellInst.getCellType( ). This method returns either aggregation or header, representing a cross tab. Use the cellInst.getCellID( ) to determine what specific design‑time cell is being processed. This method returns the Element ID defined in the general properties for a cell. The cellInst object also provides a method, getDataValue, which returns the specific value of a cross tab binding at the time the cell is created. The method getStyle( ) supports customizing the appearance of a specific cell.
The script in Listing 37‑25 illustrates the mechanics of using these methods. The script resides in the CrossTab.onCreate method. It is automatically executed for each cell in the CrossTab. The script styles the header cells for rows and columns, checking to see if the dimension value for the specific cell is equal to Planes. If it is, then the background is set to red and the font size is set to 12. All other header cells are set to yellow.
Finally, the cell id is checked and if the element ID is 24, the cell background color is set to orange.
Listing 37‑25 Setting cross tab header cell properties
function onCreateCell( cellInst, reportContext )
{
//Can reference cells by type or id - valid types "header" or "aggregation"
if( cellInst.getCellType( ) == "header" ) {
//Get data values see binding tab on crosstab
if( cellInst.getDataValue("PRODUCTLINE") == "Planes" ){
cellInst.getStyle( ).setBackgroundColor( "#FF0000") ;
cellInst.getStyle( ).setFontSize("12");
}else{
//Set the rest to yellow
cellInst.getStyle( ).setBackgroundColor( "#FFFF00") ;
cellInst.getStyle( ).setFontSize("12");
}
}
//refer to crosstab header
if( cellInst.getCellID( ) == 24){
cellInst.getStyle( ).setBackgroundColor( "Orange" );
}
The script in Listing 37‑26 continues the onCreateCell script in Listing 37‑25, handling setting colors for the aggregation elements which make up the bulk of the cross tab. First, if the product line is Planes the cell background color is set to blue-gray. This setting ensures all the cells in the particular row or column that correspond to the Planes value of the product line appear blue‑gray. Finally, if the measure amount is greater than 50000, the cell background color is set to green and the font color is set to white. In this example, you can use getDataValue to retrieve data binding values that are defined in the bindings tab for the cross tab.
Listing 37‑26 Setting aggregation cell properties
if( cellInst.getCellType( ) == "aggregation" ){
//Can reference value using getDataValue or
if( cellInst.getDataValue( "PRODUCTLINE" ) == "Planes" ){
//set color to blue-gray
cellInst.getStyle( ).setBackgroundColor("RGB(169,170,226)");
}
//by using reportContext.evaluate
//if( reportContext.evaluate("measure['amount']") > 50000 ){
if( cellInst.getDataValue( "amount_DateGroup/quarter_ProductGroup/PRODUCTLINE" ) > 50000 ){
cellInst.getStyle( ).setBackgroundColor( "Green" );
cellInst.getStyle( ).setColor( "White" );
}
}
Alternatively, you can use the reportContext.evaluate( ) method to evaluate a specific expression. In the example:
if( reportContext.evaluate( "measure['amount']" ) > 50000 ){
and
if( cellInst.getDataValue( "amount_DateGroup/quarter_ProductGroup/PRODUCTLINE" ) > 50000 ){
are equivalent if the expression for the amount_DateGroup/quarter_ProductGroup/PRODUCTLINE binding is measure['amount']. The value for this binding is the value for row‑column intersection point.
JavaScript dynamic script example
Development of a complex report design can make use of libraries to ensure consistent appearance of all items. When a library is used, a change to the parent item in the library changes all report items that descend from that item. However, sometimes a change is required to a complex report design that has been developed without using a library. For example, applying mapping to a library data item can change the appearance of zeros or null values in descendant data items in a report, but if there are a large number of data items that are not controlled by a library item, making changes is tedious and error-prone. In this case, the report developer can use dynamic script generation in the beforeFactory to apply an onRender script to the data items, as shown in Listing 37‑27.
Listing 37‑27 Creating a dynamic script
//Get table handle
var mytable = reportContext.getDesignHandle().findElement( "mytable" );
//Get number of columns
var columnCount = mytable.getColumnCount();
//Get number of detail rows
var detailRowCount = mytable.getDetail().getCount();
 
for (drc=0;drc<detailRowCount;drc++) //For each detail row
{
for (cc=0;cc<columnCount;cc++)
{ //For each column
var dataItem = mytable.getDetail().get( drc ).getCells( ).get( cc ).getContent().get(0); //Get data Item
if(dataItem)
{
dataItem.setOnRender("if (this.getValue() == null || this.getValue() == 0) {this.setDisplayValue(\"-\");}");
} //Set onRender value
}
}