Scriptlets

Elixir Report Designer allows small scripts to be executed to control or interact with the rendering process. Within each script, the keyword this identifies the current template component - which might be a ReportHeader, PageHeader, Field, Image etc. See the list of objects in the Elixir Report Designer JavaScript API. The this keyword is optional in the scripts:

this.setFontColor("Red")

is equivalent to:

setFontColor("Red")

Each part of a report - from the Report object itself, down to Sections, Report Bands (e.g. a Group Header), and every component can have up to four scripts: RenderIf, OnRenderBegin, OnRenderEnd and OnLayout associated with it. The scripts will be executed based on the order the objects are rendered. For report bands, this is document order, for components it is the order they appear in the shape tree (Z-order, from back to front). OnRenderEnd and OnLayout will occur after all child components have been rendered, so Report OnRenderBegin will be the first script to run and Report OnRenderEnd the last.

RenderIf -- except for Report
OnRenderBegin
-- any child components rendered here
OnRenderEnd
[OnLayout] -- only applies to report bands

RenderIf

RenderIf is evaluated to determine whether a component should be rendered. If the script evaluates to true, the component is rendered normally, if it evaluates to false, the component is not rendered and occupies no space in the output. Here's a sample renderIf script:

Parameters.get("user")=="Elixir"

This script returns true if the value of the dynamic parameter "user" is equal to the value "Elixir", otherwise it returns false. Thus the component will only be rendered if the "user" is "Elixir".

If no renderIf script is defined the default is true - the component is rendered.

Elixir Data Designer supports the RenderIf script at the cell level. You can use the RenderIf script to control which cells will display, and the remaining cells will automatically expand to fill the gap. The cells include those in Horizontal Boxes and Vertical Boxes. To control the visibility of cells, run the Render Wizard, and then make your selections in the Dynamic Parameters window.

OnRenderBegin

OnRenderBegin is executed before each component is rendered. For example, if the report has ten details, onRenderBegin will be called on each component in the detail section ten times, once per render of the component. The keyword this identifies the component being rendered. Here's a sample onRenderBegin script:

if (count%2==1)
{
    setBackgroundColor("Yellow");
}

This script checks the count variable. If the number is odd (1,3,5 etc,) the background colour of the component is changed to "yellow". Note that this modified template component will be used for all further renderings, so all subsequent even renderings (2,4,6 etc.) will be yellow as well - that's probably not what we intended, so it would often be advisable to include:

else
{
    setBackgroundColor("White");
}

to ensure changes to the template are not propagated to subsequent details.

OnRenderEnd

OnRenderEnd is executed after each component is rendered. This script is useful for incrementing counters and modifying the results of rendering (e.g. formatting) before the report is finalized. The this keyword still refers to the template component used to render the output. Another variable result now references the rendered component. Here's a sample onRenderEnd script:

field = result.getLogicalElement(0);
if (field.getText()<0) result.setBackgroundColor("Red");

This script extracts the text from a field, checks whether the value is less than zero. If it is, the background colour gets set to red. Notice JavaScript will automatically turn the field text - a string - into a number for comparison. In this case, there's no need to provide an alternate colour for a positive result as the change is to the result element, not the template element. Changes to this affect the rest of the rendering from this template, whereas changes to result only affect the generated report.

Here's another:

field = result.getLogicalElement(0);
field.setText(field.getText().toUpperCase());

This script extracts the text from a field component and changes the formatted text to upper case. This can't be done in onRenderBegin, because the formatting is only performed during rendering. The call to getLogicalElement is required to conform to the logical RML structure, which is explained in detail in the JavaScript API section below.

OnLayout

OnLayout is only applicable for bands in the report. When a particular band, for example a Detail, has been rendered the OnRenderEnd script is called. Following this, the band may be paginated - even split into multiple chunks so that it can fit within the page boundaries. As this task is done, immediately after each chunk has been added to a page, the OnLayout script is invoked. At this point you can access this, result (the same as OnRenderEnd) and page - the page object on which this chunk has been put.

OnLayout is useful for controlling page-based information - for example, a page total that is displayed in a page footer. It is only at the point of pagination, after OnRenderEnd, that we know what page (or pages) a particular band will be assigned to. Hence this is the time to update page totals. The OnLayout for a chunk will be invoked before the OnRenderBegin of the Page Footer belonging to the Page that it is placed on. Here is an example sequence of scripts when the Detail band fits at the bottom of the page:

  1. Detail RenderIf // assume returns true
  2. Detail OnRenderBegin
  3. Detail OnRenderEnd
  4. Detail OnLayout // because it fits the page
  5. PageFooter RenderIf // assume returns true
  6. PageFooter OnRenderBegin
  7. PageFooter OnRenderEnd

Here is the same sequence when the Detail band doesn't fit on the page:

  1. Detail RenderIf // assume returns true
  2. Detail OnRenderBegin
  3. Detail OnRenderEnd // by the end of this we know how big the detail is, and can see it won't fit
  4. PageFooter RenderIf // assume returns true
  5. PageFooter OnRenderBegin
  6. PageFooter OnRenderEnd
  7. PageHeader RenderIf // next page now - assume returns true
  8. PageHeader OnRenderBegin
  9. PageHeader OnRenderEnd
  10. Detail OnLayout // delayed to here because the detail didn't fit before