Event scripts are short pieces of JavaScript that run while an operator works on a batch. They react to things that happen on the Index / Validate screens: a batch opens, a document is shown, a field gets or loses the cursor, a value changes, a button on the form is pressed, a document is completed or the batch is released.
Use them to format values, fill one field from others, move the cursor, show a warning, stop an operator completing a document that is not right, or add line items with one click.
Where you write them
Event scripts belong to a Batch Setup version. You can edit them in three places:
- the Batch Setup's Events tab, which lists all of them;
- the Scripts panel of the screen designer, for a document class's document, field and button scripts;
- the field editor, for the field's own scripts.
All three use the same editor. It colours the code, checks for errors, and offers IntelliSense for the variables and your Batch Setup's field names.
Add an event script
- Open the Batch Setup, work on a draft version, and open the Events tab.
- Click Add and fill in:
- Name;
- Event: see the list below;
- Document class: All classes, or one class;
- Field or Fields of the group, for field and field-group events;
- Runs: In the browser or On the server;
- Enabled.
- Write the Script.
- Under Try it, type field values, one per line as
Name = value, and click Try. - Click Save events.
Click Help in the editor for a summary of events, variables and results.
Browser or server
| In the browser | On the server | |
|---|---|---|
| Speed | Instant, no network round trip. | A call to the server. |
| Best for | BeforeFocus, LostFocus and Change: formatting, filling fields, moving the cursor. | Checks that must not be bypassed, and AfterRelease. |
| Sandbox | A dedicated Web Worker with no network access and no access to the page, cookies or server. Stopped after 1.5 seconds. | DocView Capture's JavaScript sandbox: strict mode, no .NET, file or network access, stopped after 2 seconds or 500,000 statements, 64 MB memory. |
Server Validate scripts run wherever documents are checked: after extraction, on every save and when a document is completed. So a rule written as a server Validate script cannot be skipped.
Try it runs the script on the server. Browser scripts use the same variables and results, so they behave the same.
Events
| Scope | Event | When it runs |
|---|---|---|
| Batch | Open |
The batch is opened on the Index / Validate screen. |
| Batch | Close |
The operator closes the batch (Save & close, Next batch). |
| Batch | BeforeRelease |
The operator releases the batch. Can stop the release. |
| Batch | AfterRelease |
The batch was released. Server only, for example to log or notify. |
| Batch | Route |
A workflow step was completed. Server only. Can send the batch to another step. See Route the batch. |
| Batch | ArrangePages |
A workflow step was completed, before the next step is chosen. Server only. Can split, cut out, turn, copy, move or delete pages and start new documents. See Arrange pages and documents. |
| Document | Load |
A document is shown to the operator. |
| Document | Close |
The operator moves from the document to another one. |
| Document | Validate |
The document is checked: when it is completed, and on the server after every change. |
| Document | BeforeComplete |
The operator completes the document. Can keep it open. |
| Document | Click |
The operator presses a form button that runs this script. |
| Field | BeforeFocus |
The cursor is about to enter the field. |
| Field | LostFocus |
The cursor leaves the field. |
| Field | Change |
The value was changed (typed, picked or clicked on the image). |
| Field | Validate |
The field is checked after a change and when the document is completed. |
| Field group | Change |
Any of the group's fields was changed. |
| Field group | Validate |
The group is checked after a change and when the document is completed. |
Buttons are added to a form in the screen designer (Workflow tab › Design screens). Each button names the Click script it runs. See Screen designer.
What a script can use
The script body runs as a function, so you can use return.
| Variable | Contents |
|---|---|
event |
{ name, scope, script }: which event is running, and the script's name. |
field |
{ name, value, previous }: the field of a Field or Field group event. |
fields |
All fields of the document by name, for example fields.TotalAmount. For batch events, the batch fields. |
tables |
Line items by table name, for example tables.LineItems[0].Amount. |
document |
{ number, className, pages, state }. className is the document class key. |
batch |
{ name, fields, documentCount, pageCount }. |
user |
The operator's user name. |
num(text) |
Reads an amount such as £1,250.00 as a number. |
round(n, digits) |
Rounds a number. |
inDictionary(name, value) |
Server scripts only. true when the value is an entry of the dictionary. |
translate(name, value) |
Server scripts only. The entry's value from the dictionary, or null. |
Field values are text. Use num() before you calculate.
What a script returns
| Return value | Effect |
|---|---|
nothing, or true |
No effect. |
'a message' |
Shows the message. For Validate, BeforeComplete and BeforeRelease it is an error that stops the action. |
false |
Stops the action (BeforeComplete, BeforeRelease) or fails Validate. |
{ set: { Field: value } } |
Changes field values. |
{ setBatch: { Field: value } } |
Changes batch field values. |
{ setTables: { Table: [ { Column: value } ] } } |
Replaces the rows of a table. |
{ action: 'complete' } |
For buttons: then complete the document. Also 'next', 'previous', 'save' (save and close) or 'release'. |
{ message, severity } |
Shows a message. severity is 'info', 'warning' or 'error'. |
{ errors: { Field: 'text' } } |
Marks fields as wrong with a message. |
{ focus: 'Field' } |
Puts the cursor in a field. |
{ cancel: true } |
Stops the action, for events that can be stopped. |
You can combine properties in one object, for example set, message and action.
Examples
Field · Change (browser): upper case and no spaces
return { set: { [field.name]: (field.value || '').toUpperCase().replace(/\s+/g, '') } };
Field group · Change (browser): fill the total
if (!fields.TotalAmount && fields.NetAmount && fields.VatAmount) {
return { set: { TotalAmount: round(num(fields.NetAmount) + num(fields.VatAmount), 2).toFixed(2) } };
}
Field · LostFocus (browser): jump to the PO number when it is needed
if (field.value && !fields.PoNumber) {
return { focus: 'PoNumber', message: 'This supplier needs a PO number.', severity: 'warning' };
}
Document · BeforeComplete (server): stop credit notes without a reference
if (document.className === 'credit_note' && !fields.PoNumber) {
return 'A credit note needs the original invoice or PO reference.';
}
Document · Click (button): add a delivery line, then complete
const lines = (tables.LineItems || []).concat([{ Description: 'Delivery', Quantity: '1', Amount: '25.00' }]);
return {
set: { Currency: 'GBP' },
setBatch: { Reference: fields.Supplier },
setTables: { LineItems: lines },
message: 'Delivery added.',
action: 'complete'
};
Batch · BeforeRelease (server): at least one document
return batch.documentCount > 0 || 'The batch has no documents.';
Arrange pages and documents
An ArrangePages script (Batch scope, on the server) rearranges a batch whenever a step is completed — also when an import releases a batch past Scan straight away. Use it for what separation rules and image steps cannot do: split an A3 sheet into A4 pages, cut a cheque off a page, turn pages, copy a page into two documents, delete pages, or group pages into documents your own way.
The script sees:
step—completed(the step's name),module(for examplescan) andnext.batch—name,priority,sourceandfields.pages— each page in order:id,number,document(its document's number, or null),widthMm,heightMm,size(A5,A4,A3,A2,Letter,Legal,Tabloidorother, either way round),landscape,side(front,backor null),sheet,blankandsourcePage.documents— each document:number,classNameandpages(the ids of its pages).
It returns nothing to leave the batch as it is, or:
{ documents: [ [ /* pages of document 1 */ ], [ /* document 2 */ ] ], loose: [ /* pages in no document */ ], delete: [ /* page ids */ ], reason: 'why' }
Each page in the lists is a page's id (or its number), or an object { page: id, part: 'left', rotate: 90 }:
part—left,right,toporbottom: half of the page. On a page standing upright,leftandrightare its top and bottom half, soleftis always the first half of the sheet.crop— any part of the page:{ x: 0.1, y: 0.5, w: 0.8, h: 0.3 }in fractions of the page.rotate— 90, 180 or 270 degrees clockwise.
Helpers: part(page, 'right'), rotate(entry, 90) and isSize(page, 'A3').
Every page must be placed in a document, left loose or deleted, or the script fails and the batch waits in the exception queue — so a script cannot lose pages by mistake. A page used only in parts is replaced by its parts; the same page placed twice is copied. The existing documents are kept in order (with their type and values) as far as the script returns documents; extra documents are added and documents left over are removed. The batch history records what was done.
Example: A3 sheets as A4 pages. Each A3 sheet starts a document; its front and back become four A4 pages in the order of a folded booklet (front right, back left, back right, front left), and the A4 pages scanned after it stay in its document. Put it on the Batch Setup's Events tab, Batch scope, event ArrangePages, run on the server:
if (step.module !== 'scan') return; // only once, when the batch leaves Scan
var docs = [], doc = null;
for (var i = 0; i < pages.length; i++) {
var p = pages[i];
if (isSize(p, 'A3')) {
// The next A3 page is the sheet's back (unless it is the front of another sheet).
var back = i + 1 < pages.length && isSize(pages[i + 1], 'A3') && pages[i + 1].side !== 'front' ? pages[++i] : null;
doc = [part(p, 'right')];
if (back) { doc.push(part(back, 'left'), part(back, 'right')); }
doc.push(part(p, 'left'));
docs.push(doc);
} else {
if (!doc) { doc = []; docs.push(doc); } // A4 pages before the first A3 sheet
doc.push(p.id);
}
}
return { documents: docs, reason: 'A3 sheets as A4 pages' };
Switch off blank page deletion for such a Batch Setup when every side must be kept.
This example is ready to try as the template A3 sheets as A4 pages (script) on the System features tab of New Batch Setup, with sample files to download; Tidy pages with a script shows deleting blank pages and turning pages upright.
Good practice
- Keep browser scripts short. They must finish within 1.5 seconds.
- Put checks that must always hold into server Validate or BeforeComplete scripts.
- Return values as text, for example
total.toFixed(2). - Prefer validation rules for standard checks such as totals and check digits. Use scripts for what rules cannot express.
- Server script errors are shown to the operator with the script's name. Errors in
AfterReleasescripts, when no operator screen is left, are recorded in the audit log asEventScriptError.