Writing scripts: tips and tricks

This topic provides some tips and tricks to use when writing template scripts.

For the basics, see Writing your own scripts.

All features designed for use in the Designer are listed in the Designer's API, with a lot of examples; see Standard Script API.

Looping over elements

If the selector of a script matches more than one element in a template, you may want the script to loop over them.

One way to do this is by setting the script's scope set to Each matched element (see Setting the scope of a script). The script will be called in a loop over the elements that match the selector of the script. It can access each matched element directly via the this object. For an example, see: this.

Otherwise, there are a number of iterator functions that you can use, such as each(), for(..in...) and for...of.

Function Description
each() A generic iterator function, to iterate over the elements in the result set.
for(... in ...)​​​ ​Iterates over the enumerable properties of an object, in arbitrary order. For each distinct property, statements can be executed.

for...of

The for...of statement executes a loop that operates on a sequence of values sourced from an iterable object. See Mozilla's documentation.

Note: A for...of loop currently cannot be used in combination with 'const'.

Retaining values between scripts

The context for user scripts does not reset across records. This means that if a script uses a variable that is not declared or initialized in that script, the variable retains its value from the previous record. This is by design. It allows you, for example, to maintain a running total across all records of a job.

Example: x = 123;

Example: numbering optional elements in Connect template

Let's say there are a number of different, optional elements in the template. Whether the optional elements appear in the template depends on standard scripts. The optional elements that become visible should be numbered in sequence (1, 2, ...).

One solution is to assign a class, e.g. "opt", to all the optional elements in the template. In a Control Script, set a variable, e.g. "SequenceNumber", to 0:

Copy
sequenceNumber = 0;

Then create a script that has the opt class as selector. Set the scope to Each matched element. If an element is visible, the script increments the sequence number and puts it before the element.

Copy
if (!(this.css('display') == 'none')) {
    sequenceNumber++;
    this.prepend(sequenceNumber + ' ');
}

Obviously, this script should run after any optional elements have been made visible.

Note that this solution only works if the optional elements appear in the main flow of the template. It doesn't work for positioned elements.

Defining a function in a Control Script

Do you find yourself copy-pasting the same function into every new script? You can avoid this by defining your own function using a function expression:

Copy
fn = function() { … }

The function fn can be accessed from all subsequent scripts.

Tip: Define the function in a Control Script. Control Scripts are executed first, so the function will then be available in all Standard Scripts and Post Pagination Scripts.