Triggers: Difference between revisions

Jump to navigation Jump to search
7,390 bytes removed ,  10 May 2021
m
no edit summary
mNo edit summary
mNo edit summary
(32 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Stamp|2017-01-24|4.2.1|1.0.8}}
{{Stamp|2021-03-31|4.10.0|1.9.6}}


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 '''[https://developer.mozilla.org/en-US/docs/web/JavaScript 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.
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 '''[https://developer.mozilla.org/en-US/docs/web/JavaScript 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.
-----
-----


Line 8: Line 8:
:; Event type
:; Event type
:: One of the following:
:: One of the following:
::* Opening a library
::* Creating an entry
::* Creating an entry
::* Updating an entry
::* Updating an entry
::* Updating a field
::* Deleting an entry
::* Deleting an entry
::* Linking an entry
::* Unlinking an entry
::* Opening an Entry Edit card
::* Opening an Entry Edit card
::* Adding an entry to Favorites
::* Adding an entry to Favorites
Line 28: Line 32:
:; 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.
:; 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.
-----
-----
<br/>
=== Scripting for creating and for updating entries ===
If you want the same logic to be used in both your ''Creating'' scripts and your ''Updating'' scripts, it is tempting to just copy the code for one and paste it into the other, and that can be  done in '''''in most cases'''''. If you write your ''Updating'' script first, the copy will work. If you write your ''Creating'' script first, then you '''''may''''' still be able to copy, but if you needed for the ''Creating'' Script to be executed ''Before saving'', you'll need to change ''defaultEntry()'' to use ''entry()'' instead.


== Events & Phases ==
== Events & Phases ==
Line 36: Line 41:
|-
|-
! Event type !! Phase !! [[#Mode of script execution|Execution mode]]
! Event type !! Phase !! [[#Mode of script execution|Execution mode]]
|-
|| '''[[#Opening a library|Opening a library]]'''
| '''Opening the library''' || synchronous
|-
|-
| rowspan="3" | '''[[#Creating an entry|Creating an entry]]'''
| rowspan="3" | '''[[#Creating an entry|Creating an entry]]'''
Line 47: Line 55:
| '''Opening an Entry Edit card''' || synchronous
| '''Opening an Entry Edit card''' || synchronous
|-
|-
| '''Before saving the entry''' || synchronous
|-
| '''After saving the entry''' || asynchronous
|-
| rowspan="2" | '''[[#Linking an entry|Linking an entry]]'''
| '''Before saving the entry'''  || synchronous
|-
| '''After saving the entry''' || asynchronous
|-
| rowspan="2" | '''[[#Unlinking an entry|Unlinking an entry]]'''
| '''Before saving the entry''' || synchronous
| '''Before saving the entry''' || synchronous
|-
|-
Line 71: Line 89:
| '''After the operation''' || asynchronous
| '''After the operation''' || asynchronous
|}
|}
=== Opening a library ===
This event occurs when a library is opened before any activity is performed on the library.
This event has only one phase, and it is ''synchronous''. Therefore, the script will fully execute before any other activity takes place in the library.


=== Creating an entry ===
=== Creating an entry ===
Line 81: Line 103:


:; 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.<br/>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.
:; 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.<br/>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.
==== Scripting considerations ====
'''=>''''' Say what here? '''''
===== Creating an entry =====
''Creating'' scripts are different from other trigger scripts in that, since the new entry is being crafted, it is not yet stored within Memento &mdash; the Entry object does not yet exist &mdash; so it needs to be handled differently.
Use the method ''defaultEntry()'', rather than ''entry()'', to get the DefaultEntry object (the ''un''stored template, if you will, for the eventual Entry object).
Once the default entry is saved, it can be referred to by calling ''entry()'' to get the saved Entry object. So ''Before saving'' scripts use ''defaultEntry()'', and ''After saving'' scripts use ''entry()''.


=== Updating an entry ===
=== Updating an entry ===
Line 91: Line 124:


:; 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.<br/>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.
:; 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.<br/>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.
'''<i><b>The following 2 sections are under development.</b></i>'''
=== Updating a field ===
TBD
=== Linking an entry ===
This event starts when a user has added a linked entry to a Link to Entry field either by selecting an existing entry from the entries list for the linked library or by pressing '''+''' (Plus) to create a new entry in the linked library. It ends after the entry is resaved to storage &mdash; or else not, depending on the processing of the entry.
==== Phases ====
This event has two phases. In sequence:
:; 1. Before saving the entry (synchronous): The script will be called before the entry has been saved to storage after the user has either selected an entry from the linked library or pressed the '''Checkmark''' icon after having added a new entry to the linked library from within the Link to Entry field.<br/>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.<br/>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.<br/>The script could be used to update some entry data based on other entry data, to keep it all coordinated.
:; 2. 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.<br/>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.
The script of this event type has access to additional functions:
===== masterLib() ===== 
:Returns the library from which the current record was referenced.
===== masterEntry() =====
:Returns the entry from which the current record was referenced.
===== attr(name) =====
:Get the value of the attribute for the current reference.
===== setAttr(name , value) =====
:Set the value of the attribute for the current reference.
=== Unlinking 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 &mdash; or else not, depending on the processing of the entry.
==== Phases ====
This event has two phases. In sequence:
:; 1. 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.<br/>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.<br/>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.<br/>The script could be used to update some entry data based on other entry data, to keep it all coordinated.
:; 2. 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.<br/>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 ===
=== Deleting an entry ===
Line 153: Line 217:


=== Writing a Trigger Script ===
=== Writing a Trigger Script ===
Trigger scripts are JavaScripts. See '''''[[#JavaScript links|links to JavaScript documentation]]''''' below.
Trigger scripts are in the JavaScript language. See '''''[[#JavaScript links|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.
; 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.
Line 173: Line 237:
<br/>
<br/>


== Libraries and Entries ==
== See Also ==
=== ''Library'' Global Functions ===
; [[Memento JavaScript Library]]: Memento JavaScript functions & objects<br/>
 
; [[Trigger Examples]]: Examples of trigger scripts for common needs
==== entry() ====
; [[How:Write scripts in JavaScript for Memento]]: Guidelines for writing JavaScript scripts for Memento
: Get the Entry object of the Event. For example, if the script is triggered by an Update Entry event, this function will return the entry being updated.
 
: This Entry object is a clone of the actual Entry object. If the entry is saved, this object will become the actual one, but if cancel() is called, this entry clone, along with any changes the script may have performed, will be discarded.
: This function is available to all Events and Phases, with the exception of '''Creating an entry''' &gt; '''Opening an Entry Edit card'''; for this action, use the function ''entryDefault()''.
 
:; Result: [[#Object Entry|'''''Entry''''' object]] &mdash; the current entry
 
==== entryDefault() ====
: Get the Entry object containing the default field values for the entry not yet created. This feature is available specifically and only for the Event '''Creating an entry''' & Phase '''Opening an Entry Edit card'''.
 
:; Result: [[#Object DefaultEntry|'''''DefaultEntry''''' object]]
 
==== lib() ====
: Get the library of the triggering event
 
:; Result: [[#Object Library|'''''Library''''' object]] &mdash; the current library
 
==== libByName(name) ====
: Find the library by name. Permission to use the library is required, based on security settings.
 
:; Argument: The name of the library to find
 
:; Result: [[#Object Library|'''''Library''''' object]] &mdash; the library identified by the argument ''name'', if found. Otherwise ''null''.
 
<br/>
 
=== Object ''Library'' ===
This object provides access to library entries. You can work with the current library &mdash; the ''lib()'' &mdash; or any other library in the database &mdash; ''libByName()''. This function provides the ability to update existing entries and create new ones.
 
==== ''Library'' Methods ====
===== entries() =====
: Get all the entries of the library
:; Result: Array object containing entries, sorted by the time of their creation, from newest to oldest
 
===== find(query) =====
: Search field values within entries in the library matching the given query. This search is similar to searching via Memento's user interface.
:; Argument: '''query''' &mdash; the search string
:; Result: Array object containing matching entries. Entries are sorted by the time of their creation, from newest to oldest.
 
===== findByKey(name) =====
: Search all entries by the Entry Name. The library must be set for unique Entry Names.
:; Argument: '''name''' &mdash; the Entry Name field value
:; Result: [[#Object Entry|'''''Entry''''' object]], if found. Otherwise, ''null''.
 
===== create(values) =====
: Create a new entry in the library
:; Argument: '''values''' &mdash; [https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object '''''Object'''''] containing the field values
:; Result: [[#Object entry|'''''Entry''''' object]] &mdash; the new entry in the library
 
===== show() =====
: Display the library
 
==== ''Library'' Properties ====
: '''title''' &mdash; The name of the library
 
<br/>
 
=== Object ''Entry'' ===
This object holds an entry of the current library, allowing the setting of field values
 
==== ''Entry'' Methods ====
===== set(name, value) =====
: Set the value of the named field. Calling this method results in immediate writing of the value to the library.
 
:'''Note:''' In the case where the field to be set is a Link To Entry field, the second argument should be the entry name of the entry to link to. If there are, in that library, multiple fields set as Entry Name, the entry name for the set() method is formed by separating the value of those fields by a comma (,) &mdash; not a comma and a space, but only a comma.
 
:; Arguments
:: '''name''' &mdash; name of the field
:: '''value''' &mdash; the value of the field
 
===== field(name) =====
: Get the value of the named field
:; Argument: '''name''' &mdash; name of the field
:; Result: The value of the field. The type of the result depends on the type of the field.
 
===== show() =====
: Display the entry
 
==== ''Entry'' Properties ====
: '''name''' &mdash; entry name
: '''title''' &mdash; entry name
: '''description''' &mdash; entry description
: '''favorites''' &mdash; true, if the entry is in Favorites
: '''deleted''' &mdash; true, if the record is deleted (it is in the Recycle Bin)
<br/>
 
=== Object ''DefaultEntry'' ===
Template with default values for a new entry. This feature is available specifically and only for the Event '''Creating an entry''' & Phase '''Opening an Entry Edit card'''.
 
==== ''DefaultEntry'' Methods ====
===== set(name, value) =====
: Set the value of the field
 
:; Arguments
:: '''name''' &mdash; the name of the field
:: '''value''' &mdash; the value of the field
<br/>
 
=== Libraries Examples ===
See '''[[Trigger Examples#Libraries Examples]]'''.
<br/>
-----
<br/>
 
== 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''' &mdash; 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
:: [[#Object File|'''''File''''' object]]
<br/>
 
=== 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 &mdash; 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
<br/>
 
=== Files Examples ===
See '''[[Trigger Examples#Files Examples]]'''.
<br/>
-----
<br/>
 
== 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'''.
<br/>
 
=== Object ''Http'' ===
Interface for processing HTTP requests
 
==== ''Http'' Methods ====
===== get(url) =====
: Execute HTTP get request
:; Argument: '''url''' &mdash; HTTP address, starting with http or https
:; Result: '''HttpResult''' &mdash; Object containing the result of the execution of the HTTP request
<br/>
 
=== Object ''HttpResult'' ===
Result of the execution of the HTTP request
 
==== ''HttpResult'' Properties ====
: '''code''' &mdash; HTTP code of the response, if the request is successful (usually 200).
: '''body''' &mdash; The response in text form
<br/>
 
=== Http Examples ===
See '''[[Trigger Examples#Http Examples]]'''.
<br/>
-----
<br/>
 
== Interaction with the System ==
=== ''System'' Global Functions ===
==== message(text) ====
: Shows the user a brief notification
:; Argument: '''text''' &mdash; 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: [[#Object System|'''''System''''' object]]
 
==== log(text) ====
: Write a line to the log file
:; Argument: '''text''' &mdash; text to be written to the log
 
==== guid() ====
: Generates random text identifier
:; Result: Random string identifier
 
==== intent(action) ====
: Create an information exchange object &mdash; Intent. This function can send a request for action to another application.
: This function is available only on Android.
:; Argument: '''action''' &mdash; Line that defines standard action (eg, view, pick)
:; Result: [[#Object Intent|'''''Intent''''' object]] &mdash; 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 [https://developer.android.com/reference/android/content/Intent.html '''here'''].
<br/>
 
=== Object ''System'' ===
This object contains information about the system.
 
==== ''System'' Properties ====
: '''os''' &mdash; Name of the operating system executing the script
<br/>
 
=== 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 &mdash; 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 &mdash; 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
<br/>
 
=== System Examples ===
See '''[[Trigger Examples#System Examples]]'''.
<br/>
-----
<br/>
 
== 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
 
:; email: 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.
 
<br/>
-----
<br/>
 
=== Built-in Objects Examples ===
See '''[[Trigger Examples#Built-in Objects Examples]]'''.
<br/>
-----
<br/>
 
== See also ==
{| class="wikitable" style="font-size:120%"
|-
| Examples of trigger scripts || '''[[Trigger Examples]]'''
|-
|}
<br/>
-----
<br/>


== JavaScript links ==
[[Category:Spec]]
{{Template:JavaScriptLinks}}

Navigation menu