A previous post shows how events fire and their sequence as a user interacted with your form. If you explore the form you will see how some events fire quite often, in particular the calculate event, validate event and the form:ready event.
The intention of the example is to show that some events fire many times and as a result can adversely affect performance.
Here I want to focus on the layout:ready event. While it may appear on the surface that this event only fires occasionally, that is not necessarily the case.
When developing forms you should appreciate the impact of your script and make it as efficient as possible.
XFA supports three categories of events:
- Process events, which fire automatically.
- Interactive events, which fire as a results of a user’s action.
- Application events, which fire as a result of the actions of the client application, such as Acrobat.
The layout:ready is a process event and this fires every time the form changes. This can be a very useful event where you want to update the form using script, when the form changes. For example, a page number on the Master Page. When the user’s actions causes the form to overflow and a new page to be created, the page numbers will automatically update.
However the layout:ready event should be used with a little degree of caution, especially in dynamic forms where the user can add new instances of repeating objects. What is important to realise is that the layout:ready event fires every time the form changes, even if the change is in a field that does not have script in its layout:ready event.
If we look at an example of a form that has two objects:
- a TextField, which allows the user to input their name. This object does not have any script.
- a page number object, which has script in the layout:ready event to calculate the page number.
In this example, when the user types in their name and exits the TextField, the layout:ready event will fire. Even though there is no change in the page number itself, the form has changed and the layout:ready event fires automatically.
In the above example, the performance hit will not be a worry, as there is only one object with script in the layout:ready event and the form is unlikely to grow to multiple pages.
There may be trouble ahead
Problems can arrise when you use the layout:ready event in several objects, particularly objects that are set to repeat. Take the example above where you include a Page x of y on the Master Page. This includes two objects with script in the layout:ready event. When the form is contained on one page, it is not too bad. Every time there is a change the layout:ready event fires twice. Now take the case where the content overflows the first page and a new page is rendered. When this happens every change means that there are now four layout:ready events firing. And so it escalates.
Another common use case is where you have a table in your form and you want a row index number for each row that is added to the table at runtime. This can be achieved with a single line of script in the layout:ready event:
this.rawValue = this.parent.index + 1;
However, every time a new row instance is added, it is adding an object with a layout:ready event firing.
Here is a form to demonstrate the affect of having multiple objects with script in the layout:ready event.
First off this example includes a Flash Field object (to visually indicate when the layout:ready event is firing). Because of this you will need to open the form in either Acrobat X or Reader X (version 10.1 or later).
This page only has one object with script in a layout:ready event.
What you will see is that every time you interact with a field (type in data, click a button, check/uncheck the checkbox), the layout:ready event will fire once.
In this example however, there are five objects with script in the layout:ready event. Four of them are in objects that repeat. For example the row index in the table and the date and page numbers in the Master Page.
Now when you interact with the form, the layout:ready event is firing multiple times.
In addition the more instances of the repeating objects, the more layout:ready events there are to fire.
For example, if you press Shift when you click the Add row button, 100 rows will be added to the table. This extends the table over multiple pages and now when you interact with the form, you will see the hour glass as the multitude of layout:ready events fire. Sign!
Lessons to be learnt
The main takeaway from this example, would be to use the layout:ready event sparingly.
For example, instead of using Page x of y, just use Page x, which will halve the number of layout:ready events firing without sacrificing the functionality.
Once you have developed your form you should test it and see if there are delays or poor performance. If this is the case, then review your script and try and cut out some of the layout:ready events.
Please use the comment form below if you would like to share your experiences with this or other events.