Triggers
A Trigger is a script that defines the processing of an entry whenever a particular kind of event takes place. Trigger scripts are written in JavaScript. When a trigger script is executed, it may perform actions like changing an existing entry, creating a new entry, executing an HTTP request, creating a file, performing data validation, etc.
Definitions
We define the following terms:
- Event type
- One of the following:
- Creating an entry
- Updating an entry
- Deleting an entry
- Opening an Entry Edit card
- Adding an entry to Favorites
- Removing an entry from Favorites
- Phase of an Event
- One of a predefined set of moments during entry processing for each Event type during which the user can intervene via a trigger script. See the table of events and phases below.
The Event type and the Phase determine the trigger script(s) to be run.
- Trigger or Trigger Script
- A script that may be defined to run when an event occurs for an entry
The trigger (Event type & Phase) and the corresponding trigger script are one-to-one.
When referring specifically to the script, it is called the trigger script. When referring to the Event type & Phase and its listing in the trigger list, it is referred to merely as a trigger.
Mode of script execution
The phase in which the trigger is activated defines its mode of execution — synchronous or asynchronous.
- Synchronous script execution mode
- Memento suspends user interaction and then executes the script. In the case of Before... phases, there is an impending operation that will take place unless the script forestalls it by calling cancel().
Time-consuming operations are not recommended in this mode.
- Asynchronous script execution mode
- The script runs in the background; user interaction is not suspended. Usually, asynchronous scripts are used in the last phases of the action, after any save or other operation is initiated.
Events & Phases
These are the defined Event types, Phases, and their corresponding modes of execution.
Event type | Phase | Execution mode |
---|---|---|
Creating an entry | Opening an Entry Edit card | synchronous |
Before saving the entry | synchronous | |
After saving the entry | asynchronous | |
Updating an entry | Opening an Entry Edit card | synchronous |
Before saving the entry | synchronous | |
After saving the entry | asynchronous | |
Deleting an entry | Before deleting the entry | synchronous |
After deleting the entry | asynchronous | |
Opening an Entry View card | Before window display | synchronous |
After window display | asynchronous | |
Adding an entry to Favorites | Before the operation | synchronous |
After the operation | asynchronous | |
Removing an entry from Favorites | Before the operation | synchronous |
After the operation | asynchronous |
Creating an entry
This event starts when a user has requested that a new entry be added to the library, normally by pressing the + button on the Entries List screen. It ends after the entry is saved to storage — or else not, depending on the processing of the entry.
Phases
This event has three phases. In sequence:
- 1. Opening an Entry Edit card (synchronous)
- The script will be called once the Entry Edit card is open and before any data is displayed.
Initial field values (defaults) may be set.
- 2. Before saving the entry (synchronous)
- The script will be called after the user has pressed the Checkmark icon and before the entry has been saved to storage.
The entered data may be validated; if validation fails, the save may be forestalled and control sent back to the Entry Edit card so the user may fix the errors.
Once the data is validated, this phase is an opportunity for many other functions to be performed to get data to add to the entry to be saved.
- 3. After saving the entry (asynchronous)
- The script will be called once the save of the entry has been initiated and will continue in parallel with final processing of the new entry.
If you want to do something whenever a new entry is added, but not before the data is saved, this is the place to do it.
Updating an entry
This event starts when a user has requested that an existing entry be edited (updated) within the library, normally by pressing the Pencil button on the Entry View card. It ends after the entry is resaved to storage — or else not, depending on the processing of the entry.
Phases
This event has three phases. In sequence:
- 1. Opening an Entry Edit card (synchronous)
- The script will be called once the Entry Edit card is open and before any data is displayed.
- 2. Before saving the entry (synchronous)
- The script will be called after the user has pressed the Checkmark icon and before the entry has been saved to storage.
The entered data may be validated; if validation fails, the save may be forestalled and control sent back to the Entry Edit card so the user may fix the errors.
Once the data is validated, this phase is an opportunity for many other functions to be performed to get data to add to the entry to be saved.
The script could be used to update some entry data based on other entry data, to keep it all coordinated.
- 3. After saving the entry (asynchronous)
- The script will be called once the save of the entry has been initiated and will continue in parallel with final processing of the new entry.
If you want to do something whenever an existing entry is updated, but not before the data is saved, this is the place to do it.
Deleting an entry
This event starts when a user has requested that an existing entry be deleted (actually, moved to the library's Recycle Bin) within the library, normally by pressing the Trash Can button on the Entry View card. It ends after the entry is moved to the Recycle Bin — or else not, depending on the processing of the entry.
Phases
This event has two phases. In sequence:
- 1. Before deleting the entry (synchronous)
- This script will be called after the user has requested the deletion of the entry and pressed Yes on the "Do you really want to?" card, but before taking the action.
Since the user has at this point already confirmed that he or she really wants to delete that entry, what else needs to be done before doing the delete? And what would cause the delete to need to be forestalled? If the delete is to be forestalled, the script could call cancel() and inform the user as to why via message(), and let the user reconsider what to do.
Mainly, help the user reconfirm that the deletion should take place, and if not, call cancel() and inform the user (via message()).
- 2. After deleting the entry (asynchronous)
- This script will be called after the delete operation is initiated and will continue as that operation takes place.
Anything you want to do whenever an entry is deleted should be done in this script.
Opening an Entry View card
This event starts when the user has selected an entry for view and ends after the entry had been displayed.
Phases
This event has two phases. In sequence:
- 1. Before window display (synchronous)
- This script will be called before the entry is displayed. This provides the opportunity to alter or augment the data before it is seen by the user.
- 2. After window display (asynchronous)
- This script will be called after the data display had been initiated, providing the opportunity to perform an action each time an entry had been viewed, such as logging or timestamping.
Adding an entry to Favorites
This event starts when the user has pressed an empty Star icon to make the current entry a Favorite and ends once it has been made a Favorite.
Phases
This event has two phases. In sequence:
- 1. Before the operation (synchronous)
- This script is run just before the entry is made a Favorite.
Data validation could be done; perhaps only certain entries are allowed to be Favorites. - 2. After the operation (asynchronous)
- This script is called after the entry has been made a Favorite.
This action could be logged, for instance, or it could trigger an action on some other app.
Removing an entry from Favorites
This event starts when the user has pressed a filled Star icon to remove the current entry from Favorites and ends once it has been removed.
Phases
This event has two phases. In sequence:
- 1. Before the operation (synchronous)
- This script is run just before the entry is removed from Favorites.
Confirmation of the user's intent could go here. - 2. After the operation (asynchronous)
- This script is called after the entry has been removed from Favorites.
This action could be logged, for instance, or it could trigger an action on some other app.
See Also
- Memento JavaScript Library
- JavaScript functions, objects, methods, and properties for use with Memento
- Trigger Examples
- Examples of scripts implementing Memento triggers
Security
Since the scripts have access to more actions than a user does, they require additional permissions.
The user must define these permissions manually for each library.
To open a card to set permissions for scripts, open the library triggers list and click the Shield icon on the toolbar. Permissions must be set separately on each device. Permissions are not synchronized between devices.
Permissions for scripts
- Library permission
- determines which other libraries can be affected by the script. You can grant access to all libraries or select only certain libraries. This authorization is required for the libByName() function.
- Read permission
- grants the script read access to a file
- Write permission
- grants the script write access to a file
- Network
- grants to the script the right to execute HTTP requests
Creating a trigger
Each library can have a number of triggers; multiple triggers may exist for each Event type and Phase. To see the list of triggers, open the library, open the menu, and then select Triggers.
To create a trigger, press the 3-dot icon in the upper-right corner of the screen to open the Action Menu; then press Triggers to open the list of existing triggers; then click +. You must then identify the Event type & Phase and write a trigger script that performs the necessary actions.
Writing a Trigger Script
Trigger scripts are JavaScripts. See links to JavaScript documentation below.
- Event & Phase
- Make sure to understand the Event & Phase you are scripting. This will dictate a number of things, such as whether data is present already or not, whether cancel() makes sense or not, whether the user is waiting for script execution or not, and so on.
- Globals get you started
- Note the global functions in the sections below; they generally get you started by providing needed information.
- Inform the user
- Keep the user informed. For instance, if a script is running in a synchronous phase, then a call to cancel() may make sense, but the user won't know what happened and what to do next unless you provide that information, probably via message().
- Debug your script
- Of course, you can put calls to message("Your message") to help to test your script. To further assist, the log("Your message") global function can be used to send messages to a log without bothering the user about it. By default, the log is directed to the Android developer console; to have it directed instead to a file, go to Memento Settings under Debug and turn on Triggers Logs. You can set the location for the file, but by default, it will be in memento/logs. Both messages from calls to log() and system log messages, including JavaScript exceptions, go into the log.
- Permissions
- Certain functions require special permissions; read above about that. One such function is libByName(). Others include the file access and HTTP functions.
- No return
- As of release 4.0.0 of the mobile edition, the script is executed as a top-level script and not as a called function; therefore, for instance, the return statement is not appropriate in a trigger script.
Things to know while writing a trigger script
- No implicit context
- There is no implicit context for the trigger script, as there is, for instance, in a JavaScript field. Instead, there are global functions, such as lib() and entry() that must be used to set up context for the script.
- Entry objects are clones
- The Entry object associated with the Event (the one that entry() gives you) is a clone of the actual entry object. If changes are made to this object, they will be saved if the script returns normally. However, if the script calls cancel(), this clone will be discarded upon return from the script, along with any changes that have been made.
Working with files
With scripts, you can read or write files located in the device's internal memory or on the SD card. All file operations are performed by the File object, which is obtained via a global function called file().
To work with the files, the library should have read/write file access.
File Global Functions
file(name)
Open a file for read or write operations. If the file with the specified name does not exist yet, it will be created.
- Argument
- name — The name and the full path to the file. For example, if the file is located on the SD card, the path should be something like /sdcard/example.txt.
- Result
- File object
Object File
This object is returned by the global function file() and provides access to the requested file. After reading or writing, the file should be closed using the method close().
File Methods
- readAll()
- Reads all lines of the file, and then closes the file
- Returns
- Array containing the lines of the file
- readLine()
- Reads the next line from the file stream
- Returns
- The line
- readLines()
- Reads the remaining lines from the file stream
- Returns
- Array containing the remaining lines of the file
- readChar()
- Reads the next character from the file stream
- Returns
- The character
- write(text)
- Write string(s). Take a variable number of arguments, converts each argument to a string, and writes that string to the file stream.
- writeLine(text)
- Write strings and a newline to the file stream
- close()
- Close the file. It can subsequently be reopened.
File Properties
- exists
- true — if and only if the file exists; false otherwise
- length
- The length, in bytes, of the file, or 0L if the file does not exist.
- getLineNumber
- Get the current line number
- Returns
- The line number, or position, in the file
Files Examples
See Trigger Examples#Files Examples.
Processing an HTTP request
Scripts can send HTTP requests to Web services through their APIs. Processing for HTTP requests allows integration between Memento and the system. All file operations use the Http object, which works through global function http().
HTTP requests must fulfill two requirements:
- Script execution must be asynchronous, so HTTP requests go in the last Phase of an Event.
- The library should have the permission Network.
Object Http
Interface for processing HTTP requests
Http Methods
get(url)
- Execute HTTP get request
- Argument
- url — HTTP address, starting with http or https
- Result
- HttpResult — Object containing the result of the execution of the HTTP request
Object HttpResult
Result of the execution of the HTTP request
HttpResult Properties
- code — HTTP code of the response, if the request is successful (usually 200).
- body — The response in text form
Http Examples
See Trigger Examples#Http Examples.
Interaction with the System
System Global Functions
message(text)
- Shows the user a brief notification
- Argument
- text — Text of the notification
cancel()
- Stop the system operation that caused the event. Many triggers can be a result of an entry manipulation (create, update, delete, etc). The cancel() function can be used during the phases that precede the system operation. For example, this function can be used during data validation before the entry is saved.
system()
- Obtain information about the system
- Result
- System object
log(text)
- Write a line to the log file
- Argument
- text — text to be written to the log
guid()
- Generates random text identifier
- Result
- Random string identifier
intent(action)
- Create an information exchange object — Intent. This function can send a request for action to another application.
- This function is available only on Android.
- Argument
- action — Line that defines standard action (eg, view, pick)
- Result
- Intent object — Information exchange object
- After the object is received, the data will be added to it, and then sent via send().
- Android has many built-in actions. A list of these actions can be found here.
Object System
This object contains information about the system.
System Properties
- os — Name of the operating system executing the script
Object Intent
Information exchange object. This object is created by using the global function intent().
Intent Methods
data(uri)
- Define URI to reference the data
- Argument
- uri — URI referencing data to which the action will be applied. It can be contact ID, path to the file, phone number, etc.
mimeType(mime)
- Define MIME type of the data
- Argument
- mime — MIME type of the data on which the operation will be performed
extra(key, value)
- Define additional data as key-value pairs, as necessary for execution of the required action. Similar to how URI data can be required for certain actions, other actions may require extra data in this format.
- Arguments
- key and value
extraLong(key, value)
- Define additional data as key-value pairs, where data type needs to be Long
- Arguments
- key and value
send()
- Send a message
System Examples
See Trigger Examples#System Examples.
Built-in objects for certain Memento field types
Object JSContact
This object contains the information stored within a Contact field and provides properties and methods for use in accessing and manipulating this information.
When an Entry object's field() method is called, if the Memento field type is Contact, a JSContact object is returned.
If the Contact field contains multiple contacts, use hasNext and next to retrieve them.
JSContact Methods
- show()
- Opens the Contacts app for this contact
- call()
- If the device is a phone, calls the primary phone number of this contact
- sendSMS(message)
- If the device is a phone, sends the provided message (text string) as an SMS message to the primary phone number of this contact
- sendEmail(subject, message)
- Sends an email message to the primary email address of this contact, with subject subject and message message (text string)
JSContact Properties
- fullName
- The full name of this contact
- phone
- The primary phone number of this contact
- The primary email address of this contact
- hasNext
- Returns TRUE if there is a next JSContact object, otherwise FALSE
- next
- Returns the next JSContact object, if there is one.
Object JSGeolocation
This object contains the information stored within a Location field and provides properties and methods for use in accessing and manipulating this information.
When an Entry object's field() method is called, if the Memento field type is Location, a JSGeolocation object is returned.
If the Location field contains multiple locations, use hasNext and next to retrieve them.
JSGeolocation Properties
- lat
- Latitude, as a Real
- lng
- Longitude, as a Real
- address
- Address for this Location
- hasNext
- Returns TRUE if there is a next JSGeolocation object, otherwise FALSE
- next
- Returns the next JSGeolocation object, if there is one.
Built-in Objects Examples
See Trigger Examples#Built-in Objects Examples.
See also
Examples of trigger scripts | Trigger Examples |
JavaScript links
W3Schools | |
---|---|
JavaScript Tutorial | A pleasant, fairly complete, and useful tutorial on JavaScript Best on a computer or tablet in landscape. On a phone or tablet in portrait, scroll to the bottom for navigation. |
Mozilla Developer Network | |
JavaScript Guide | Shows you how to use JavaScript, gives an overview of the language, and presents its capabilities & features |
JavaScript Reference | The entire JavaScript language described in detail |
Introduction to JavaScript | Introduces JavaScript and discusses some of its fundamental concepts |
JavaScript Tutorial | A re-introduction. JavaScript is often derided as being a toy, but beneath its simplicity, powerful language features await. |
JavaScript 1.7 | The JavaScript release upon which Memento is currently based |
About JavaScript | Jumping off point in learning about JavaScript |